Windows Forms Programming in Visual Basic .NET
Most WinForms projects start in the New Project dialog box, available via File New Project (Ctrl+Shift+N) and shown in Figure 1.1. Figure 1.1. WinForms Projects
To build an application, you'll want the Windows Application project template. To build a library of custom controls or forms for reuse, you'll want the Windows Control Library project template. When you run the Windows Application Wizard, choosing whatever you like for the project name and location, you'll get a blank form in the Designer, as shown in Figure 1.2. Figure 1.2. The WinForms Designer
Before we start the drag-and-drop extravaganza that the Designer enables, let's take a look at a slightly abbreviated version of the code generated by the WinForms Application Wizard (available by right-clicking on the design surface and choosing View Code or by pressing F7):
Public Class Form1 Inherits System.Windows.Forms.Form #Region " Windows Form Designer generated code " Public Sub New() InitializeComponent() End Sub 'NOTE: The following procedure is required by 'the Windows Form Designer 'It can be modified using the Windows Form Designer. 'Do not modify it using the code editor. Private Sub InitializeComponent() Me.ClientSize = New System.Drawing.Size(292, 266) Me.Text = "Form1" End Sub #End Region End Class None of this code should be alien; there is a public class, which derives from the Form class and exposes a public constructor. Notice that there is no Shared Sub Main(). Visual Basic .NET Windows Application projects have a property called Startup Object available from the Project Properties dialog. By default, this property is set to the first Form-derived class in the application, but it can be changed to point at any Form-derived class or Sub Main(). If you leave the default setting, then when you compile the application, a Shared Sub Main() is created for you that essentially calls Application.Run on the specified startup form. The only thing that's different from what we did ourselves is the call to InitializeComponent in the form's constructor to set the form's properties instead of doing it in the constructor itself. This is done so that the WinForms Designer, which we can use design our form visually, has a place to put the code to initialize the form and the form's contained controls. For example, dragging a button from the Toolbox onto the form's design surface will change the InitializeComponent implementation to look like this:
Friend WithEvents Button1 As System.Windows.Forms.Button Private Sub InitializeComponent() Me.Button1 = New System.Windows.Forms.Button() Me.SuspendLayout() ' 'Button1 ' Me.Button1.Location = New System.Drawing.Point(104, 80) Me.Button1.Name = "Button1" Me.Button1.TabIndex = 0 Me.Button1.Text = "Button1" ' 'Form1 ' Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(292, 266) Me.Controls.AddRange(New System.Windows.Forms.Control()_ {Me.Button1}) Me.Name = "Form1" Me.Text = "Form1" Me.ResumeLayout(False) End Sub Notice again that this code is very similar to what we built ourselves, but this time created for us by the Designer. Unfortunately, for this process to work reliably, the Designer must have complete control over the InitializeComponent method. In fact, notice that the Wizard-generated InitializeComponent code is wrapped in a region, which will hide the code by default, and is marked with a telling comment:
'NOTE: The following procedure is required by 'the Windows Form Designer It can be modified using the Windows Form Designer. 'Do not modify it using the code editor. It may look like your favorite programming language, but InitializeComponent is actually the serialized form of the object model that the Designer is using to manage the design surface. Although you can make minor changes to this code, such as changing the Text property on the new button, major changes are likely to be ignored ”or worse , thrown away. Feel free to experiment with just how far you can go by modifying this serialization format by hand, but don't be surprised when your work is lost. We recommend putting custom form initialization into the form's constructor, after the call to InitializeComponent, giving you confidence that your code will be safe from the Designer. Of course, we put up with the transgression of the Designer because of the benefits it provides. For example, instead of writing lines of code to set properties on the form or the controls contained therein, all you have to do is to right-click on the object of interest and choose Properties (or press F4) to bring up the Property Browser for the selected object, as shown in Figure 1.3. Figure 1.3. The Property Browser
Any properties with nondefault values, as indicated by values in boldface in the browser, will be written into the InitializeComponent method for you. Similarly, to choose an event to handle for the form or the form's controls, you can choose the appropriate class from the upper-left wizard bar in the code editor window. Then choose the event you wish to handle from the upper-right wizard bar, as shown in Figure 1.4. Figure 1.4. List of Events
Handling an event from the wizard bars is easy: Find the event you would like to handle, and click its name in the wizard bar. A procedure will be generated with the appropriate signature and following the standardized naming scheme described earlier. The cursor will be placed in the middle of this procedure, ready for you to implement:
Private Sub button1_Click(sender As Object, e as EventArgs)_ Handles button1.Click End Sub After you've added a handler to a form, you can use that handler again to handle other events with the same signature ”for example, multiple buttons with the same handler. Simply add the new object and event after the Handles keyword. You can use the sender argument to determine which object fired the event:
Private Sub Button1_Click(sender As Object, e As EventArgs) _ Handles Button1.Click, Button2.Click Dim button As Button = sender MessageBox.Show(button.Text & " was clicked") End Sub If, as is often the case, you'd like each event that you handle for each object to be unique or you just don't care what the name of the handler is, you can simply click on the name of the event in the wizard bar and a event handler name will be generated for you, based on the name of the control and the name of the event. For example, if you double-clicked on the Load event for the Form1 form, the event handler name would be Form1_Load. Furthermore, if you're handling the default event of an object, you can handle it simply by double-clicking on the object itself, an action that will generate an event handler name just as if you'd double-clicked on that event name in the Property Browser event list. The default event of an object is meant to be intuitively the most handled event for a particular type. For example, I'm sure you won't be surprised to learn that the default event for a button is Click and that the default event for a form is Load. Unfortunately, neither the Designer nor the wizard bars give any indication what the default event will be for a particular type, but experimentation should reveal few surprises . |