I am trying to create a customized form class (CustomBorderlessForm) in VB.NET.
My Progress So Far
I created a new Class and named it CustomBorderlessForm.vb
I then proceeded to write the following code:
CustomBorderlessForm.vb
Public Class CustomBorderlessForm
Inherits Form
Dim _form As Form = Nothing
Public Sub New(form As Form)
_form = form
MsgBox("Testing: New()")
End Sub
Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
MyBase.OnMouseMove(e)
MsgBox("Testing OnMouseMove()")
End Sub
End Class
Form1.vb
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim form As New CustomBorderlessForm(Me)
End Sub
End Class
Results of progress
A message box displays "Testing: New()" on load
Nothing shows on mouse move
As you can see, my problem lies with the events
Questions
Is it possible to create a form object and use that instead of the pre-populating form?
If so, can I give this form custom properties, such as, a border and some boolean values (shadow...etc), just like any other custom object/class?
What am I doing wrong in my current approach?
Why isn't the OnMouseMove being overridden?
Am I initialising the class wrong?
Can it even be done this way?
After creating a form you also need to show it. Change your logic to:
Dim form As New CustomBorderlessForm(Me)
form.Show()
Before you do that, I'd recommend changing from MsgBox to Console.WriteLine(), otherwise you can run into a fun/frustrating little cat and mouse game.
EDIT
Based on the comments, if, from VS you did a "Add New, Windows Form" you can just right-click the project, select property and on the Application tab change the Startup object to your new form. VS only allows you to do this with forms it creates for you (by default, more on this later).
If you wrote that file by hand (which is absolutely fine) you can perform the Show() like I did above and call Me.Hide() to hide the "parent" form. Unfortunately the Load event is fired before the Show event so if you place this in Form1_Load() it won't work. Instead you can use the Shown event like this:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim form As New CustomBorderlessForm(Me)
form.Show()
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Me.Hide()
End Sub
Another option has to do with "Application framework". You can read about it here however it basically handles application events that other languages have to manually implement. If you go into your project properties you can uncheck the "Enable application framework" checkbox. This will give you more option in the "Startup object" dropdown. If you add the following code to your project one of the items in the Startup object dropdown menu should now be "Loader"
Public Module Loader
<STAThread()>
Public Sub Main()
Dim form As New CustomBorderlessForm(Nothing)
form.ShowDialog()
End Sub
End Module
You'll notice that the above bypasses Form1 completely. Also, instead of Show() I'm using ShowDialog() because otherwise the form shows and then the program ends.
Related
The user enters data in Form1 for example his name and phone number, he clicks on the "next" button that opens Form2 and Hide Form1, if he clicks on the "back" button I want the program to show Form1 with the data he entered before
The code for the "Next" Button in Form1:
Private Sub NextButton_Click(sender As Object, e As EventArgs) Handles NextButton.Click
Dim MyForm As New Form2
MyForm.Show()
Me.Hide()
End Sub
What should I do in order to keep the data the user entered if he comes back to Form1?
The code for the "Previous" button in Form2:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Form1.Show()
Me.Close()
End Sub
One approach you could use is to only the use the DEFAULT INSTANCES of your Forms. These are accessed by using only the name of the Form, WITHOUT ever using the "New" keyword.
You're doing exactly that in Form2 when you show Form1 with:
Form1.Show()
This works because Form1 is your startup object and VB.Net used the default instance to start the application.
You could do the same thing in Form1, to show Form2:
' ... code in Form1 ...
Private Sub NextButton_Click(sender As Object, e As EventArgs) Handles NextButton.Click
Form2.Show() ' show the default instance of Form2 (do NOT use the "new" keyword)
Me.Hide()
End Sub
Just make sure in all places you Hide() the current form instead of closing it.
You can access the properties/fields of the default instances using the same syntax to show them, using only their name. For example, here is a made up value being accessed on Form2:
Dim userName As String = Form2.txtAddress1.Text
This assumes that Form2 was previously displayed and populated by the user. You could access the Forms from anywhere in the code using this type of syntax.
If you want to implement your own "default instance" mechanism, you could use Shared members in a class:
Public Class WizardForms
Public Shared F1 As New Form1
Public Shared F2 As New Form2
Public Shared F3 As New Form3
End Class
Then you could use code like this to display one:
WizardForms.F2.Show()
This would work as long as you are only HIDING the forms. If you allow the user to close the Forms (or close them via code), then you'd need extra code to make sure they get recreated as needed.
I'm using office developer tools and made a ribbon to access some functions. Thing is, it looks like I can't open a userform from a button, other commands seems to run normally.
Code:
Public Class Empresa
Private Sub Button1_Click(sender As Object, e As RibbonControlEventArgs) Handles btn_DBSol.Click
'Dim wnd As New frm_DBSolventes
'wnd.Show()
MsgBox("Hello World")
End Sub
End Class
This code have this result on excel ribbon:
https://s24.postimg.org/6z16l6g43/Print_1.jpg
Now using this code:
Public Class Empresa
Private Sub Button1_Click(sender As Object, e As RibbonControlEventArgs) Handles btn_DBSol.Click
Dim wnd As New frm_DBSolventes
wnd.Show()
'MsgBox("Hello World")
End Sub
End Class
Results in nothing:
There are no errors on Error List window. frm_DBSolventes is a userform on a userform referenced project, there is nothing on the form right now, just made a new project of userform and trying to show it. Is there something I'm missing? Is there any other way where I can use a userform on ribbon?
As Requested the frm_DBSolventes is
https://s29.postimg.org/6w6ae15qd/Print_3.jpg
Just add a datagridview cause I need to continue working. if it makes difference I can change it. There is no code on the form:
Public Class frm_DBSolventes
End Class
Try to show it as a modal Window.
I am getting a an Null reference exception when trying to add an item to a listbox in a different form.
This is my error at run time.
An unhandled exception of type 'System.NullReferenceException'
occurred in ... Additional information: Object reference not set to an
instance of an object.
I am trying to connect the Mainform by initializing it at the top of the class of the secondForm. after I have my data i want to add it to a listbox it the mainform.
Public Class FormHairdresser //The second form
Dim varMainForm As FormMain //connecting the forms ?
Private Sub btnAddHairdresser_Click(sender As Object, e As EventArgs) Handles btnAddHairdresser.Click
hairdresser = HairdresserChoices(HairdresserID) // get the data
varMainForm.lstListBox.Items.Add(hairdresser) //Run time error breaks here.
All i had to to was write the form name instead of ininalised variable.
FormMain.lstListbox.Items.Add("item")
Instead of
Dim varMainForm As FormMain
varMainForm.ListBox.Items.Add("item")
You cannot simply create a new instance of your main form (as has been suggested and expect that to work, you need an actual reference to the mainform that you have created. To help you see the logic involved;
Create a new Winforms project. In the default Form1 add a textbox and a button.
Now add a new form to this application (you can leave it with its default name of Form2. To this form add a TextBox (call it myTextBox) and a button.
Now go back to your first form and doubleclick the button to access the click handler in code. Add the following:
Dim frm as New Form2
frm.Show
Press f5 and click the button and you'll see a new form 2. So far so good.
Now open up the code for Form2 and add the following code so that it ends up looking like this:
Public Class Form2
Private frm As Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
frm.TextBox1.Text = myTextBox.text
End Sub
End Class
build, press f5 and click the button on form1, in the new form2 enter some text in the text box and click the button, you get your null reference exception. The reason you get this is because at the moment the private field frm inForm2 refers to Nothing.
Now open up the code in Form2 and add a constructor and the following code so that it ends up looking like this:
Public Class Form2
Private frm As Form1
Public Sub New(byval frm1 As Form1)
'first we should make sure that we have a parameter to play with
If Not IsNothing(frm1) Then
frm = DirectCast(frm1,Form1)
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
frm.TextBox1.Text = myTextBox.text
End Sub
End Class
Finally go back to your first forms buttonclick handler and change the code slightly so that it looks like this;
Dim frm as New Form2(Me)
frm.Show
Build and run your application, now when you enter text into the textbox in form2 and click the button it will appear in the textbox in Form1.
The reason why this happens is because you have passed an actual reference to the form1 that was originally created when the application started to form2. By casting that reference to your private field used to represent form1 in form2 you can then use it to properly refer to things on form1. This is a very simple concept but one which you need to learn before you will make progress programming.
the Problem is with your initialization of the formmain.with out proper initialization the object you are creating is nothing other than Null.To avoid this we use New Operator.The New operator can often be used to create the instance when you declare it.
So the initialization will look like
Dim varMainForm As New FormMain
Hope this Helps.For more Reference Object Initialization Errors
update:
Dim varMainForm As FormMain //connecting the forms ?
Private Sub btnAddHairdresser_Click(sender As Object, e As EventArgs) Handles btnAddHairdresser.Click
hairdresser = HairdresserChoices(HairdresserID) // get the data
varMainForm = New FormMain
varMainForm.lstListBox.Items.Add(hairdresser) //Run time error breaks here.
Try This.
Public Class FormHairdresser //The second form
Private Sub btnAddHairdresser_Click(sender As Object, e As EventArgs) Handles btnAddHairdresser.Click
Dim varMainForm As FormMain
hairdresser = HairdresserChoices(HairdresserID)
varMainForm.lstListBox.Items.Add(hairdresser)
I'm relatively new to Windows Forms development and my first real application has reached a point where a lot of code starts to build up in my main Form file, so I decided to restructure my project using the MVC pattern.
One major problem I have is dealing with the different control events of the form. I have several buttons, textfields, comboboxes and also a tabcontroll element which again contains different input elements and so far, every procedure for handling clicks, updates and other changes is defined in my main class.
For example:
Private Sub btnOk_Click(sender As Object, e As EventArgs) Handles btnOk.Click
some code...
End Sub
So my question is: what would be the best way to handle these events outside of my main form? I'm more familiar with building GUIs in Java where you can use ActionListeners to achieve this but I have found nothing similar for my work with Windows Forms.
To subscribe to a Control event outside of your main form class, make your control public, so you can access from another class). This can be done using the Modifier property at design-time. Then, use the AddHandler keyword to subscribe to any event programmatically.
After researching a bit more, I found that there is probably not THE correct answer to this problem but I found 2 approaches which provide a solution in the way I was looking for. In both cases, I use a controller class which is responsible for handling any user interaction from my main form.
The first approach makes use of what DmitryBabich suggested, adding a handler to the object and referencing it to a method of my controller class:
in Form1:
Dim ctrl as new Controller(Me)
AddHandler Button1.Click, AddressOf ctrl.doSomething
Controller class:
Public Class Controller
Private myForm As Form1
Public Sub New(ByVal f As Form1)
myForm = f
End Sub
Public Sub doSomething(sender As Object, e As EventArgs)
MsgBox("Button clicked.")
End Sub
End Class
For an example this simple it is not necessary to pass an instance of Form1 over to the controller but if for example I'd like to access the values of other control elements as well, I can address them by using this instance of Form1.
For example:
Public Sub doSomething(sender As Object, e As EventArgs)
MsgBox("You clicked the button, by the way: The value of TextField1 is " & myForm.TextField1.text)
End Sub
The other approach is almost identical except that here the controller knows all the relevant user control objects of the form and can handle their events directly, meaning that in the main form I have to do nothing more than create an instance of the controller. In the controller however, I have to assign every user control I want to access to its own variable as soon as the main form is loaded:
in Form1:
Dim ctrl as new Controller(Me)
Controller class:
Public Class Controller
WithEvents myForm As Form1
WithEvents button1 As Button
WithEvents button2 As Button
Public Sub New(ByVal f As Form1)
myForm = f
End Sub
Public Sub formLoad() Handles myForm.Load
button1 = myForm.Button1
button2 = myForm.Button2
End Sub
Private Sub b1Click() Handles button1.Click
MsgBox("You clicked button1!")
End Sub
Private Sub b2Click() Handles button2.Click
MsgBox("Button #2 was clicked!")
End Sub
End Class
What I am trying to do is make a custom MenuStrip control with several items (Main Menu, Log Out, Exit, etc...) already attached. There would be methods to handle items being clicked. I think this would save me a some redundant code in the long run and I might learn a little something too.
The end product would basically be a custom MenuStrip control that I can throw on my forms and already have the functionality for the items within it.
So my question is, can this be done? I am a novice but if it can be done and is actually a good idea, then I want give it a shot.
Errors abound but this is what I was thinking...
Public Class MenuStripCustom
Inherits MenuStrip
Add MenuItem(MainMenuToolStripMenuItem)
MainMenuToolStripMenuItem.Text = Main Menu
Protected Sub MainMenuNav(e As System.EventArgs) _
Handles MyBase.MainMenuToolStripMenuItem.Click
MainMenu.Visible = True
Me.Close()
End Sub
End Class
Thanks!
Yes, can be done no problems. Just create a new user control, and make it inherit from MenuStrip. Then put in code similar to the below for a user control called "UserControl1".
Public Class UserControl1
Inherits MenuStrip
Private WithEvents NavToolStrip As New ToolStripMenuItem("Nav")
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Dim tsi As New ToolStripMenuItem
Me.Items.Add(NavToolStrip)
End Sub
Private Sub NavToolStrip_Click(sender As Object, e As EventArgs) Handles NavToolStrip.Click
MsgBox("Nav clicked")
End Sub
End Class
Compile the code then you will be able to drag "UserControl1" from your toolbox onto your form.