This chapter's project officially kicks off the coding of the Library Project (muted applause). We'll start off with something simple: building the "About" form that provides basic information about the application, including its version number.
Load the "Chapter 5 (Before) Code" project, either through the New Project templates, or by accessing the project directly from the installation directory. To see the code in its final form, load "Chapter 5 (After) Code" instead.
Our goal is a pleasant form that conveys basic information about the program, a form that looks something like Figure 5-4.
Figure 5-4. Everything you wanted to know about the program
Like any Visual Basic application for Windows, the creation of this form involves two steps: (1) adding controls to the form; and (2) writing the related code.
If there is one area where Visual Basic excels, it is form creation. Codeless programs can be created by the simple dragging and dropping of pre-built controls onto the surface of a pre-built form. It's all done from within the comfort and convenience of the Visual Studio Integrated Development Environment (IDE), as shown in Figure 5-5.
Figure 5-5. The Visual Studio environment
The displayed environment includes four key areas, which I've labeled with letters in Figure 5-5.
If you haven't done so already, open the form Form1.vb in design view by double-clicking it in the Solution Explorer. We'll add eight text labels, three shape and line elements, two web-style hyperlinks, a command button, and a picture to the form's surface. I've already added the picture to the form for you, with an image of some books, naming it SideImage.
Set up the form by adjusting the following properties from their defaults. Click on the form surface, and then modify these property values using the Properties panel.
Next, add the eight basic text labels to the form's surface using the Label control. You'll find this control in the toolbox. As you add each Label control, use the following list of settings to set the properties for each label. The included text matches my situation, but feel free to modify the content as needed.
Let's add some lines and colored sections to the form. Visual Basic 6.0 included distinct shape controls for lines, rectangles, and ellipses that you could apply directly to the form surface. .NET no longer includes these items; you have to add them by hand using source code-specified drawing commands. But you can simulate lines and rectangles using the standard Label control, sans the text.
If the BackgroundSide label obscures the graphic, right-click on the label, and select Send To Back from the shortcut menu that appears.
The LinkLabel control is similar to the more basic Label control, but you can include "links" in the text, clickable sections that are similar to the links on a web page. We'll use these to display the web site and email address. Add two LinkLabel controls to the form and use the following settings to configure each control's properties.
The final control to add is a button that lets the user close the form. Add a Button control to the form with the following properties.
Forms can be configured so that a press of the Escape key triggers a Button control on the form. To do this, click on the form surface, and then set its CancelButton property to "ActClose." We had to delay this step until the button was actually added to the form; the CancelButton property would not have allowed a setting for a non-existent button.
Well, the form should look pretty good by now. The last thing I like to do is to set up the tab order, the order in which the user accesses each field on the form when pressing the Tab key on the keyboard. To edit the tab order, select the form surface, and then select the View Tab Order menu command. Each control on the form that can be given a tab order value will suddenly have a tab order number next to it. Click on each number or control in order until you get the arrangement you want. (See Figure 5-6 to view how I ordered the controls.) Finally, select the View Tab Order menu command again, or press the Escape key, to leave the tab ordering process.
Figure 5-6. Nice and orderly
You can also set the tab order for each control by modifying its TabIndex property using a zero-based numbering system. However, it's usually faster to set these values by clicking on each control in order.
Adding the Code to the Form
Now it's time to add some real Visual Basic code. Not that we haven't added any until now. Everything we did on the form, although we didn't see it happen, was converted into Visual Basic source code. Let's take a quick look. In the Solution Explorer, click on the Show All Files button, the second button from the left. When all the files appear, click on the "plus sign" next to Form1.vb, and finally double-click on the Form1.Designer.vb file (see Figure 5-7).
Figure 5-7. Accessing the hidden, secret, forbidden code. Yeah, it's out there
Because it's over 200 lines of source code bliss, I won't be printing it here. But look it over; it's all pretty interesting. As you dragged-and-dropped controls on the form, and modified its properties, Visual Studio edited this file on your behalf. It's part of your form's class (all forms are classes that derive from System.Windows.Forms.Form). You can tell by the "Partial" keyword at the top.
Partial Public Class AboutProgram Inherits System.Windows.Forms.Form
Most of the action happens in the InitializeComponent procedure. When you are finished looking it all over, close up the designer code, and return to the form surface. To make our form a real and interesting form, we need it to do three things.
Let's start with the easy one, closing the form. I'm sure you remember about events from Chapter 1. Events are blocks of code that are processed in response to something happening, most often a user action like a mouse click. All of the actions we want to perform on this form will be in response to a triggered event (lucky us). The easiest way to get to the "default" event for a control is to double-click the control. Try it now; double-click the Close button. When you do, the IDE opens the source code view associated with the form, and adds an empty event handler (the ActClose_Click subroutine).
Public Class AboutProgram Private Sub ActClose_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles ActClose.Click End Sub End Class
Every forms-based event (and in fact, most other types of events) in .NET have pretty much the same arguments: (1) a sender argument that indicates which object triggered this event; and (2) the e argument, which allows sender to supply any additional information that may be useful in the event. In this case, the sender argument will be a reference to the ActClose button, because that's the object that will generate the Click event. A button's Click event doesn't have any more useful information available, so e is the default object type, System.EventArgs, which is pretty much just a placeholder, and the object from which all of the more interesting e argument types derive.
The name of this event handler is ActClose_Click, but if you want to change it to FredAndWilma, that's fine; it won't mess up anything. But you must keep the Handles ActClose.Click clause intact. This is the part that links the event handler to the actual event.
The code to close the form is extremely simple. Enter it now, either by using the first code snippet for this chapter, or by typing it directly.
Insert Chapter 5, Snippet Item 1.
' ----- Close the form. Me.Close()
This statement says, "I'm the AboutProgram form/object, and I command myself to close." If you run the program right now (press the F5 key), you close the form by clicking on the Close button. Because the AboutProgram form was the only form in the application, closing it automatically ended the entire application, no questions asked.
Okay, back up to the second item, the web-style links. You could go back to the form surface and double-click on each link label to create an event handler for each label's default event (in this case, the LinkClicked event). But you can also add the event handler subroutines right in the editor, either by typing the code yourself (which is no fun), or by using the two drop-down lists just above the editor window (see Figure 5-8).
Figure 5-8. The Class Name and Method Name fields
The Class Name list appears on the left side. Selecting an entry from this list updates the right-hand list, the Method Name list. To add an event handler template for the CompanyWeb's LinkClicked event, first select "CompanyWeb" from the Class Name list, and then select "LinkClicked" from the Method Name list. The following code block appears in the code window.
Private Sub CompanyWeb_LinkClicked(ByVal sender As Object, _ ByVal e As System.Windows.Forms. _ LinkLabelLinkClickedEventArgs) _ Handles CompanyWeb.LinkClicked End Sub
This template's argument list is a little more interesting, because its e argument is an object of type System.Windows.Forms.LinkLabelLinkClickedEventArgs. The LinkLabel control allows you to have multiple web-style links in a single control, interspersed among regular text. The e argument has a Link property that tells you which of the links in the control was clicked by the user. Because our labels have only a single link, we won't bother to check it. We'll just show the web page immediately anytime the link is clicked.
Insert Chapter 5, Snippet Item 2.
' ----- Show the company web page. Process.Start("http://www.timaki.com")
The Process object is part of the System.Diagnostics namespace, and Start is one of its shared members that lets you start up external applications and resources. You pass it any valid URL, and it will run. Let's try it again with the CompanyEmail's LinkClicked event. Add in the template any way you choose, and then type or insert the code that starts a new message to an email address.
Insert Chapter 5, Snippet Item 3.
' ----- Send email to the company. Process.Start("mailto:firstname.lastname@example.org")
The last event to design is one of the first events called in the lifetime of the form: the Load event. It's called just before the form appears on the screen. Double-clicking on the surface of the form creates an event handler template for the Load event. If you prefer to use the Class Name and Method Name drop-down lists instead, select "(AboutProgram Events)" from the Class Name list before using the Method Name list.
Private Sub AboutProgram_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Load End Sub
Let's add code to this event handler that displays the correct version number, using the version information found in My.Application.Info.Version, an instance of the System.Version class.
Insert Chapter 5, Snippet Item 4.
' ----- Update the version number. With My.Application.Info.Version ProgramVersion.Text = "Version " & .Major & "." & _ .Minor & " Revision " & .Revision End With
This code uses a With statement to reduce the amount of typing needed in the main assignment statement. Inside of the With . . . End With statement, you aren't required to retype the object name that appears just after the With keywordin this case, My.Application.Info.Version. You can just refer to that object's members by typing a dot (".") followed by the name of the member. You could forgo the With statement and type the full object name each time you wanted to use one of the version values, but this way keeps the code cleaner and less overwhelming.
Setting the Version Number
If you run the program, it will display the currently defined version number, "1.0 Revision 0," as shown in Figure 5-9.
Figure 5-9. The version number from the AboutProgram form
My questionand I hope I can answer it before the paragraph is finishedis, "Where is that version number defined, and how can it be changed?" It turns out that I do know the answer: The version values are stored as metadata within the assembly. Visual Studio includes a form that let's you modify the basic informational metadata stored in the assembly. To access the form, display the project's properties (double-click on "My Project" in the Solution Explorer), select the Application tab, and then click on the Assembly Information button (see Figure 5-10).
Figure 5-10. The Assembly Information form, filled out with some relevant values
Our AboutProgram form displays the assembly's version number, which is set using the four text fields next to the Assembly Version label. Those four fields represent the Major, Minor, Build, and Revision numbers of the assembly. Go ahead, set them to some other values, click OK, and run the program again.
Although this form is convenient, it's just another example of Visual Studio writing some of your project's code on your behalf. Every field on this form gets saved in a source code file included with your project. To view it, make sure you have the Show All Files button still selected in the Solution Explorer. Expand the My Project item using its "plus sign," and then double-click on the AssemblyInfo.vb item. This file defines several assembly-specific attributes (which we'll explore in Chapter 17, "GDI+"), including the following informational entries.
<Assembly: AssemblyTitle("The Library Project")> <Assembly: AssemblyDescription( _ "ACME Library Database System")> <Assembly: AssemblyCompany("ACME")> <Assembly: AssemblyProduct("Library")> <Assembly: AssemblyCopyright( _ "Copyright © 2006 by Tim Patrick")> <Assembly: AssemblyTrademark("")> <Assembly: AssemblyVersion("188.8.131.52")>
As you can see, this file has been updated with the values I typed into the Assembly Information form. Thank you, Visual Studio! You see the "AssemblyVersion" attribute defined here. If you modify these values, the changes will be reflected in the Assembly Information form, and also in your running application and final compiled assembly.
The last thing we will do for now to the AboutProgram form is to give it a meaningful file name. Currently, it is named "Form1.vb," but "AboutProgram.vb" would be much more descriptive. To change the name, select Form1.vb in the Solution Explorer, and modify the File Name property to "AboutProgram.vb" in the Properties panel. If you still have all the files showing, you will see Visual Studio also update the names of the file's two subordinate files, the designer file (AboutProgram.Designer.vb) and the resource file (AboutProgram.resx).
Now would be a great time to save your work (File Save All).
Adding the Main Form
As useful and full featured as the AboutProgram form is, such forms are seldom the core focus of an application. In the Library Project, this form will only be displayed when triggered from the "Main" form, so let's add a simple Main form now. In Visual Studio, select the Project Add Windows Form menu command. When the Add New Item form appears, select "Windows Form" from the list of available forms, and give it a name of "MainForm.vb" before clicking the Add button.
When the new form appears, adjust the following properties as indicated.
From the toolbox, add a Button control to the form with the following properties.
If you're familiar with Visual Basic development from its pre-.NET days, you will recognize the "&" characters in the button's text. This special character sets the "shortcut" for the button. When you press the Alt key and the letter that follows "&" (in this case, "A"), the program acts as if you clicked on the button with the mouse.
Double-click on the button and add the following code to the click event procedure.
Insert Chapter 5, Snippet Item 5.
' ----- Show the About form. AboutProgram.ShowDialog()
Here we specify a direct reference to the AboutProgram form. Before the 2005 version of Visual Basic, showing a new form required that you create an instance of the form class before showing it.
That syntax still works, and is the way to do if you need to display multiple copies of the same form on-screen at the same time. However the "AboutProgram.ShowDialog()" syntax is much cleaner for single-use forms, and more closely reflects how form presentation was done in Visual Basic since its initial release. Actually, this statement is using the My namespace. The full statement looks like this.
The My.Forms collection allows you to reference any form within it without having to say "My.Forms" first. The members of the My.Forms collection represent default instances of each form in the project.
That's all the code we need for now, but if you run the program, it will still only show the AboutProgram form. That's because the AboutProgram form is set as the "startup" form. To alter this, open the project properties window, select the Application tab, and set the Startup Form field to "MainForm."
Because the AboutProgram form is now being shown as a "dialog" form (through the call to the ShowDialog method), its behavior is somewhat different. Each form includes a DialogResult property whose value is returned by the ShowDialog method when the form closes. Each button on your form can be configured to automatically set this property and close the form. The Close button on the AboutProgram form does just that; its own DialogResult property is set to Cancel, which is assigned to the form when the user clicks the Close button.
The upshot of that drawn-out paragraph is that you can now delete the event handler for the Close button's Click event, and the button will still close the form. Delete the ActClose_Click procedure from the AboutProgram's source code, run the program, and see what happens. The Close button still closes the form, even without the event handler.
You could also have left the procedure there, cleared the Close button's DialogResult, and added the following statement to that button's event handler.
Me.DialogResult = Windows.Forms.DialogResult.Cancel
That brings to three the total different ways we can use to close the AboutProgram form. It's the flexibility of .NET at work; there are many different ways to accomplish the same task. So be creative!
Extra Credit: Adding an Icon
If you've still got a little energy left, we can make one more change before this chapter runs out of paper: adding a custom icon to the main form. Just follow these step-by-step instructions:
Save Your Work
Make sure you always save changes. By default, Visual Studio is configured to save your changes every time you run your program, but I like to save often just in case.
This chapter included a lot of manual instruction because there were just so many cool Visual Studio features to play with; I just couldn't help myself. We'll probably keep up this pace somewhat for a few chapters, but eventually there will be so much code that a lot of it will come from the code snippets.