Creating a Windows Control

function OpenWin(url, w, h) { if(!w) w = 400; if(!h) h = 300; window.open(url, "_new", "width=" + w + ",height=" + h + ",menubar=no,toobar=no,scrollbars=yes", true); } function Print() { window.focus(); if(window.print) { window.print(); window.setTimeout('window.close();',5000); } }
Team-Fly    

Special Edition Using Microsoft® Visual Basic® .NET
By Brian Siler, Jeff Spotts
Table of Contents
Chapter 16.  Creating Your Own Windows Controls


Assembling a new custom control from existing controls provides many advantages. First, when you add an existing control from the Toolbox to your new custom control, you get the existing control's complete functionality an important consideration when you think about how many event handlers, methods, and properties are supported by an average control. Second, combining a number of controls into one allows them to be treated as a single unit, which may make things easier from an application architecture standpoint; this approach also allows them to be drawn on the form all at once. An additional advantage is that your users can easily understand a new control made up of controls they already know.

One way to create a custom control is to make it part of a Windows application; the control can then be used only in that application. To do so, choose Project, Add User Control from the menu system, and follow the general guidelines outlined in this section. If you choose to create your control in this manner, a new class module for the control is added to the open project.

More likely, you will prefer to create Windows controls as part of a Windows Control Library project, which initially consists of a single class module in which you will create a control, and which will in turn be compiled into a Dynamic Link Library (DLL) file. (Note that you can include multiple controls in a single Windows Control Library project by adding a new class module for each new control.) Controls created in this manner can be made available to other projects, and even deployed for use on other computers. This is the technique we will use in this example.

The complete MySampleControls sample project that you will create in this section, parts of which are excerpted in code listings, is available for download from www.quepublishing.com. Look for the file named ControlDemo.zip.

Starting the NameText Control Project

Now that you have some background information on Windows controls, you can get started by creating your first custom control. The control that you will build in this section is the NameText control, which will allow the user to enter his or her name by supplying the various parts title; first, middle, and last names; and suffix/honorific individually. The NameText control will be built entirely of existing Label, TextBox, and ComboBox controls. We will build this control as part of a Windows Control Library project so it can be used by other applications.

This example will give you a hands-on understanding of the issues involved in developing custom Windows controls in the Visual Basic .NET environment. First, you will draw the user interface of the control and then add a small amount code to give it functionality.

To build the NameText control, follow these steps:

  1. Start Visual Basic .NET, then click the New Project button. (If Visual Basic .NET is already running, choose File, New, Project.)

  2. From the New Project dialog box, make sure "Visual Basic Projects" is selected in the Project Types box, and choose Windows Control Library in the Templates box. In the Name box, type MySampleControls . When you have entered all the correct information into the New Project dialog box, it should look like Figure 16.1.

    Figure 16.1. The New Project dialog box is used to create a Windows Control Library project.

    graphics/16fig01.gif

  3. Click OK. A new project is created containing a User Control object named UserControl1.vb, as shown in Figure 16.2. Note how the User Control object's design area looks like a small form with no borders.

    Figure 16.2. A Control object is similar to a small form but has no borders or other standard window elements.

    graphics/16fig02.gif

  4. Click UserControl1.vb in the Solution Explorer. In the Properties window, change the FileName property of the Control object to NameText.vb.

  5. Click the blank design area for the User Control object so the Properties window displays the object's properties. Change the Name property from UserControl1 to NameText.

  6. Change the GridSize property of the control to 4, 4. I find this grid size makes it much easier to align labels and text boxes with each other.

  7. Add five Label controls in a vertical column along the left-hand side of the control's design area. Set their Text properties to Title:, First Name:, Middle Name:, Last Name:, and Suffix:. Set their TextAlign properties to TopRight. Size the labels appropriately; in my sample application, the Size property for all the labels is 80, 16. Arrange the labels so they look like Figure 16.3.

    Figure 16.3. Label controls form the captions for the NameText control.

    graphics/16fig03.gif

  8. Change the Size property of the control itself (not the labels) to 200, 124 to make room for the text boxes that you are about to add, and to remove the extra space at the bottom.

  9. Add a ComboBox control to the right of the Title label. Change its Name property to cboTitle and clear its Text property. Make it about 60 pixels wide. Click the ellipsis button next to cboTitle's Items property to invoke the String Collection Editor. Enter the titles Mr., Mrs., Miss, Ms., Dr., and Rev. on separate lines in the String Collection Editor. Click OK to update the Items property; this will add the titles you entered to the Items collection of the combo box, allowing them to be displayed to the user at runtime.

  10. Add three TextBox controls, 100 pixels wide, to the right of the First Name, Middle Name, and Last Name labels. Set the values of their Text properties to empty strings, and set their Name properties to txtFirstName, txtMiddleName, and txtLastName.

  11. Add another combo box to the right of the Suffix label and clear its Text property. Set its name to cboSuffix. Use the String Collection Editor to add several possible suffixes such as Sr., Jr., III, IV, M.D., Ph.D., and so on.

  12. Make sure the TabIndex properties are set so that the controls will be presented to the user in order. CboTitle should have the lowest TabIndex; cboSuffix should have the highest.

  13. When you have finished adding controls, your completed NameText control interface should look something like Figure 16.4.

    Figure 16.4. The full set of constituent controls is drawn on the NameText Control object.

    graphics/16fig04.gif

  14. As with all projects, saving your work is important. Do so now before continuing.

Adding Resize Code to the Control

As you know from using standard controls such as a text box, you can adjust the size of a control in design mode by using the mouse, or by setting its Size property or Width and Height sub-properties. A TextBox control responds appropriately by automatically redrawing itself at the new size. When you are designing your own Windows control, especially one that is made up of existing controls, resizing is an important consideration. As you resize your control, you need to take action to make sure that the constituent controls are not hidden from the user or arranged in a way that prevents useful operation of the control.

To handle this concern, you can add code that responds to the Resize event of the NameText control object. This code will be executed whenever someone is drawing or resizing your control in a Visual Basic .NET (or other environment) project, and will ensure that the control does not get sized smaller than its original size. It will also resize the text boxes to fill up most of the available area.

Note

Although the task of having the TextBox control fill out the entire form area could be accomplished with no code by setting its Dock property, the technique used here helps to illustrate the process of writing code for your custom controls.


To add the necessary code for the NameText control, take the following steps:

  1. Right-click NameText.vb in the Solution Explorer window and choose View Code from the pop-up menu to display the Code window for the NameText control.

  2. In the Class Name box of the Code window, select (Base Class Events); then in the Method Name box, select the Resize event. This creates a NameText_Resize event handler, which will be invoked whenever a NameText control is resized in a host application.

  3. Add code to the NameText_Resize event handler so it looks like the following:

     Private Sub NameText_Resize(ByVal sender As Object, _      ByVal e As System.EventArgs) Handles MyBase.Resize      If Me.Width < 200 Then Me.Width = 200      If Me.Height < 124 Then Me.Height = 124      txtFirstName.Width = Me.Width - 100      txtMiddleName.Width = Me.Width - 100      txtLastName.Width = Me.Width - 100  End Sub 

  4. Save the changes to your project.

Note the use of the Me keyword in the program code you added in Step 3. Me refers to the current instance of the class; therefore, Me.Width, for example, refers to the Width property of the current instance of the NameText control.

As the user changes the dimensions of the NameText control, the Resize event handler will be executed. The first two lines in the procedure prevent the user from making the control instance too small. The remaining lines resize the TextBox controls based on the size of the NameText control, so that they will always be 100 pixels narrower than the form. (The 100-pixel figure accounts for the width of each TextBox control's matching Label control, plus a little extra as a margin.)

Adding a New Property to Your Control

Including multiple controls within a single Windows control groups them visually and allows you to draw the entire set of controls on the form at once. However, for a custom control to be useful, you also need to be able to access its properties, methods, and events as a single control. In other words, if you intend to treat all the constituent controls separately, you really have not gained anything by combining them into one control.

When designing your own controls, you can create properties that can be accessed by the programs that use the controls. Consider how the properties of a standard control work. For example, the Text property of a TextBox control is a commonly used property. When designing an application that uses a TextBox control, you can set (assign) the value of the Text property in the design environment (or by using code at runtime). You can get (or read) the value of the Text property at design time or at runtime as well.

When creating a property for custom-created Windows controls, you create a Property procedure in the control's Code window. The typical Property procedure has two sections: the Get section allows users of your control to read the property's value, whereas the Set section allows your users to assign the property's value. The general syntax of a Property procedure is as follows:

 [Default|ReadOnly|WriteOnly] Property propertyname As type      Get          'statements that retrieve the value of the property      End Get      Set          'statements that assign the value of the property      End Set  End Property 

If the control's user should only be allowed to read (Get) the value of the property but not assign (Set) it, then you should use the ReadOnly keyword in the procedure declaration, and omit the Set section. Likewise, if the user should be able to assign the property but not retrieve it, you should use the WriteOnly keyword and omit the Get section.

For the NameText control, we will begin by providing a read-only FullName property that assembles the various pieces that the user has entered into the constituent controls into a single value. The FullName property is much like the Text property of a text box. The difference here is that the FullName property returns text from all the controls on the form in a single string.

The user has no need to set the FullName property. Later in this chapter, we will create properties for the individual pieces of the full name that the user can set or get.

To set up the FullName property, open the Code window for the NameText control, and add the code in Listing 16.1 at the very bottom (just above the End Class line):

Listing 16.1 rolDemo.zip Creating the FullName Property
 ReadOnly Property FullName() As String      Get          Dim s As String          s = ""          If cboTitle.Text > "" Then              s &= trim(cboTitle.Text) & " "          End If          s &= trim(txtFirstName.Text) & " "          If trim(txtMiddleName.Text) > "" Then              s &= trim(txtMiddleName.Text) & " "          End If          s &= trim(txtLastName.Text)          If cboSuffix.Text > "" Then              s &= " " & trim(cboSuffix.Text)          End If          FullName = s      End Get  End Property 

Recall that because there is no need for the user to be able to set the value of FullName, the Property procedure is read-only. Consequently, there is only a Get portion, and no need for a Set portion.

The Get portion of the Property procedure code is not complex; it just combines the contents of the constituent controls and returns a single string to the calling application. However, the creation of this custom property illustrates the concept of taking a programming task (combining the address fields into a string) and encapsulating it in an object (the NameText control). The advantage is that other programmers can use this property without having to understand the details of its implementation.

More New Properties

Now that you have learned how to create a read-only property (using the Get portion of a Property procedure), let's enhance the control by adding a few more properties. Specifically, we want to allow a hosting application to be able to read and/or write the values of the individual components of the name. In addition, the code will use the StrConv function to convert the text contained in the constituent controls into proper case values. The five new properties we will create are

  • Title

  • FirstName

  • MiddleName

  • LastName

  • Suffix

The Title Property Get

If the user attempts to retrieve (Get) the value of a NameText control's Title property, our code should create a value for that property by returning the current value of the cboTitle combo box control's Text property. This technique is similar to the process of creating and returning the FullName property we discussed earlier. To code the Get portion of the Title property, begin by typing Property Title As String and pressing Enter (note that because this property will be read/write, you use neither the ReadOnly nor the WriteOnly keyword). Fill in the Get portion of the Property procedure by entering the following line of code between Get and End Get:

 Title = StrConv(cboTitle.Text, VbStrConv.ProperCase) 
The Title Property Set

If, however, the user attempts to assign (Set) the value of a NameText control's Title property, we must do a little more work. Notice that the Set portion of the Property procedure shell that was created for you includes an argument, ByVal Value As String. The Value argument, whose type must match the overall type of the Property procedure itself, will be populated with the value to which the user is attempting to set the Title property. We can use this value to populate or change the cboTitle control's Title property. Add the following code between Set and End Set:

 cboTitle.Text = Value 

Note

The Set portion of the Property procedure gives you an opportunity to validate the user's attempted property value. For example, if your control has a property that should only accept a certain range of values, you can verify that the desired value is acceptable before actually setting the internal property.


The Complete Title Property Procedure

The complete code for the Title Property procedure is as follows:

 Public Property Title() As String      Get          Title = StrConv(cboTitle.Text, VbStrConv.ProperCase)      End Get      Set(ByVal Value As String)          cboTitle.Text = Value      End Set  End Property 
Coding the Other Property Procedures

Now that you know how to create a read/write property, the code for the remaining procedures should be fairly easy to understand. The complete code for the remaining four property procedures is listed here in Listing 16.2:

Listing 16.2 ControlDemo.zip Creating the Individual Name Component Properties
 Public Property FirstName() As String      Get          FirstName = StrConv(txtFirstName.Text, VbStrConv.ProperCase)      End Get      Set(ByVal Value As String)          txtFirstName.Text = Value      End Set  End Property  Public Property MiddleName() As String      Get          MiddleName = StrConv(txtMiddleName.Text, VbStrConv.ProperCase)      End Get      Set(ByVal Value As String)          txtMiddleName.Text = Value      End Set  End Property  Public Property LastName() As String      Get          LastName = StrConv(txtLastName.Text, VbStrConv.ProperCase)      End Get      Set(ByVal Value As String)          txtLastName.Text = Value      End Set  End Property  Public Property Suffix() As String      Get          Suffix = StrConv(cboSuffix.Text, VbStrConv.ProperCase)      End Get      Set(ByVal Value As String)          cboSuffix.Text = Value      End Set  End Property 

    Team-Fly    
    Top
     



    Special Edition Using Visual Basic. NET
    Special Edition Using Visual Basic.NET
    ISBN: 078972572X
    EAN: 2147483647
    Year: 2001
    Pages: 198

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net