Back ] Up ] Next ]

Chapter 9

Building ActiveX Controls

Building ActiveX Controls *

Certification Objectives *

Creating an ActiveX Control *

Exposing Properties, Methods, and Events *

Creating an ActiveX Control that Exposes Properties *

Using Control Events to Save and Load Persistent Properties *

ActiveX Control Interface Wizard *

Testing a Control *

Testing and Debugging an ActiveX Control *

Creating Property Pages *

Creating and Enabling Property Pages for an ActiveX Control *

Using the Property Page Wizard *

Creating a Data-Bound Control *

Enabling the Data-Binding Capabilities of an ActiveX Control *

Creating a Data Source Control *

Creating an ActiveX Control that Is a Data Source *

From the Classroom *

The ActiveX Generation *

Certification Summary *

Two-Minute Drill *

Self Test *

 

Certification Objectives

ActiveX controls are custom controls that you can create and add to an application or HTML document. Programmers of ActiveX controls often are called authors, while the programmers who use these controls often are called developers. ActiveX controls are compiled as OCX files. Developers add these controls to the Visual Basic development environment through the Components item under the Project menu. When added to a project, an icon for the control appears in the VB Toolbox. Once added to the Toolbox, developers can then use it in their applications.

The ability to create ActiveX controls first appeared in VB version5, but as we’ll see in this chapter, version 6 has a number of exciting new features for such controls. By creating ActiveX controls, you’ll be creating controls that specifically suit your needs in developing applications.

Creating an ActiveX Control

There are three ways to create an ActiveX control. The first, and most common, is to select New Project from the File menu and choose ActiveX control from the New Project dialog box that appears. In doing so, a form-like container called a UserControl appears, and a new node labeled User Controls appears in the Project window. The UserControl, explained in greater detail later, is a container into which you add other objects to create your ActiveX control.

The second method is to change an existing project into an ActiveX control. This is done through Project Properties, which is accessed from the Project menu. By selecting the General tab, you’ll see a listbox named Project Type. Clicking the listbox reveals the possible types of projects into which you can change the project. Selecting ActiveX Control converts the project into an ActiveX control project.

Finally, you can create an ActiveX control by adding a user control to a project. This is done by selecting Add User Control from the Project menu. Doing so brings up a dialog box with the following choices, which are covered later:

In addition to adding one of the above ActiveX controls to your project, you can click the Existing tab and search your hard disk for an existing ActiveX control.

As touched on earlier, the UserControl is similar to a form in a standard EXE project. It acts as a container that holds controls and features you add to your ActiveX control. To add a control from the Toolbox to a UserControl, you first need to bring up the Form object so it is visible on the screen (by selecting the UserControl from the Project window, then clicking View Objects). It is then a matter of double-clicking a control on the Toolbox, or clicking a control from the Toolbox and drawing it on your UserControl. Also like forms, the UserControl has properties and events that you can manipulate, which are covered later.

The differences between a UserControl and a form really stand out. An example of which is how you are able to refer to the UserControl itself in code. Unlike forms, you don’t refer to the UserControl by its name in code. If you had a UserControl named UserControl1 or MyControl, you would always refer to it as UserControl, as seen in the following example:

UserControl.BackColor=vbBlue

If you wrote the above code with the UserControl’s name as Me, an error would result.

As far as names go, it is important to remember that, like forms, you can’t name your UserControl with the same name as your project. This is a more common occurrence with UserControls than with forms, as many people feel their project should reflect the name of the control. If you give your UserControl the same name as your project (or vice versa), an error results.

Colorful control is a UserControl that has a Shape object, color, and code already added that affect its appearance. This control is useful if you want to create an ActiveX control with a bit of pizzazz.

The Events control is also a UserControl with code that’s already been added. Much of this code writes to the Local window. Code within this UserControl displays such things as mouse movement, Click events, and so forth in the Immediate window.

The MacButton control provides a control that changes color when clicked. This is useful as a foundation for a control where you want the person to visually recognize that the click has been made. Special effects are generally well received by end users, so this is a useful UserControl to start with in many cases.

The ActiveX Control Interface Wizard starts a wizard that steps you through the process of adding properties, methods, and events to your control, as well as creating code for the interface. Contrary to its name, it does not help you with creating an interface for the control itself. Before using this wizard, you’ll need to add elements of a user interface to a UserControl and add Property Pages (discussed later in this chapter).

When you add a UserControl to an existing project or create a new ActiveX control project, one of the properties you should change is the ToolBoxBitmap. This property allows you to select an image that will appear in the VB Toolbox when your control is added to a project. By selecting the ToolBoxBitmap property of a UserControl, a button with an ellipsis appears. Clicking this button brings up the Load Bitmap dialog box, which you use to browse your hard disk for a graphic file to use as an icon for the control in the Toolbox.

When you compile an ActiveX control project, it is compiled as a file with an .OCX extension. Each custom control added to the project is saved as a file with the extension .CTL. If you’ve created your ActiveX control as part of an existing project, like a standard EXE, the CTL file is included as part of your EXE or DLL project.

Exercise 9-1: Creating an ActiveX Control

From the File menu, select New Project, then choose ActiveX Control from the dialog box.

In the Property window for the UserControl, change the Name property to Y2K.

Add four TextBox controls to the UserControl, and erase the value of each of their Text properties in the Property window. Arrange them in a vertical row, so they appear like the textboxes in Figure 9-1.

Figure 1: Y2K control

Add a label to the UserControl. Change the Caption property to There are. Place the caption above the textboxes, so it appears like the label in Figure 9-1. Change the font size (with the Font property) if you want, so it appears similar to that in the figure.

Add a label to the UserControl. Change the Caption property to "until the millennium!" Place the caption below the textboxes, so it appears like the label in Figure 9-1. Change the font size (with the Font property) if you want, so it appears similar to that in the figure.

Add four labels to the UserControl. Change the Caption property for the labels, so one reads Years, another says Days, and the remaining two have the caption Hours and Minutes. Place the labels so they appear like the ones in Figure 9-1.

Add a CommandButton control to the UserControl. Change the Caption property to Calculate. Double-click the command button. This will bring the Click event up in the Code window. Add the following code:

Dim yearsleft, daysleft, hoursleft, minutesleft
yearsleft = 2000 - (Year(Now) + 1)
daysleft = Int(DateSerial(Year(Now) + 1, 1, 1) - Now)
hoursleft = 24 - Hour(Now)
minutesleft = 60 - Minute(Now)
Text1.Text = yearsleft
Text2.Text = daysleft
Text3.Text = hoursleft
Text4.Text = minutesleft

Press F5 to run the control. Since it hasn’t been added to a project, a Project Properties debugging dialog box will appear. To continue, select Start Component and check Use Existing Browser. An HTML document will be automatically created, and the control will be displayed in your browser. Click the Calculate button to view the amount of time left until 2000.

When you’ve completed this exercise, save it. We will be using it for future exercises in this chapter.

Exposing Properties, Methods, and Events

When you create an ActiveX control, the properties of the UserControl aren’t visible to the end user. This applies not only to the UserControl itself, but also to controls, such as the constituent controls added from the Toolbox. To have these properties become visible, you will have to expose them.

As mentioned earlier in this chapter, the ActiveX Control Interface Wizard can be used to automate the task of adding and deleting properties, methods, and events. However, to get the most out of the wizard, you will need to understand how to delegate or map properties. By understanding this, you will also be able to deal with situations that are too complex for the wizard to handle. In this section, we will deal with exposing properties, methods, and events manually, as well as how to use the ActiveX Control Interface Wizard.

Implementing methods in an ActiveX control is similar to the way that methods are implemented in other ActiveX components and class modules. You can create your own custom methods as Public procedures in the UserControl, then invoke the methods in code. After adding code to your Public procedure, you can then add the ActiveX control to a form. Code within the form (or a control on the form) invokes the method, as you would any other method of an object. For example, let’s say you created a Public procedure called BoldAll to your UserControl. After adding the control to a form and naming it MyControl, you could then have code in the form invoke the method as follows:

MyControl.BoldAll

When adding constituent controls (that is, controls from VB’s Toolbox) to a UserControl, its methods are unavailable to any developer using your control. This is because the methods of a constituent control are Private. If you’ve authored a control, and want a developer to access the methods of a constituent control on your UserControl, you must create a "wrapper" for it, which delegates a method as Public. This is shown in the following example:

Public Sub TextHelp()
Text1.ShowWhatsThis
End Sub

While the ShowWhatsThis method for a TextBox control on our ActiveX control isn’t available to the developer using our control, the Public procedure wrapping it allows access to the method.

Implementing custom events into a UserControl is also similar to creating custom events in class modules and other ActiveX components. This is done with the words Public Event, as seen in the following example:

Public Event MyNewEvent()

After creating this event, you can then raise it with RaiseEvent, as seen here:

RaiseEvent MyNewEvent

Like methods, the events of a constituent control are unavailable to a developer using your control. As such, you need to implement delegated events, which act as wrappers for a constituent controls. To do this, you first add a Public event to your UserControl, which is used to reflect the Private event of the constituent control. In the constituent control’s event that you want made Public, you then raise the new custom event you just created. Doing so allows the developer using this control to see that constituent control’s event.

Creating an ActiveX Control that Exposes Properties

You can create custom properties for an ActiveX control with either Public variables or Property procedures. It is advised that you use Property procedures (that is, Property Let, Property Set, and Property Get) rather than Public variables. This is because if more than one instance of your ActiveX control is used by a developer, problems could arise if the system accessed a property used in the two instances. By using Property procedures, such an occurrence of the system accessing the property wouldn’t occur.

Using Property procedures for ActiveX control properties is virtually identical to using Property procedures in class modules (which we covered in Chapter 5). The first step to implementing a property is to create a Private variable that will be used to store the property’s value. Property Get is used to retrieve the value from this variable. Property Let and Property Set are used to store the property’s value.

Property Let or Property Set procedures are used to in a manner similar to Sub procedures. A parameter is used to accept a value, which is assigned as the new value of the property. This value is stored in the Private variable you set up to store the property value.

The Property Get procedure is used in a similar way to a function, in that it returns a value. Property Get is used to return the Private variables value.

The major difference between using Property procedures in ActiveX controls is the use of the PropertyChanged method. This method is used to notify VB that the property has been modified, and it is used to ensure that the WriteProperties event (explained in the next section) fires. By using PropertyChanged, Property procedures, and a Private variable, you are able to expose properties.

Using Control Events to Save and Load Persistent Properties

In using events to load and save persistent properties, the PropertyBag object is used. PropertyBag is just what it sounds like—an object of the UserControl that allows you to store property values. It allows the property values to persist because the object itself persists, as instances of a control are created and destroyed.

Exam Watch: Expect the PropertyBag object to make an appearance on questions dealing with ActiveX controls. It is fundamental to storing and retrieving persistent property values.

The PropertyBag object is used in the parameters of the WriteProperties and ReadProperties events. The WriteProperties event is used to save property values to the PropertyBag object using the WriteProperty method. ReadProperties event is used to load property values from the PropertyBag object using the ReadProperty method. In the following paragraphs, we will review each of these in greater depth.

When at least one property value has changed, the WriteProperties event occurs immediately before the UserControl’s Terminate event. This allows a property value to be saved just before an instance of a UserControl is destroyed. To save a property value, the WriteProperty method of the PropertyBag object is used. This is seen in the following example of code:

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
Call PropBag.WriteProperty("BackColor", Text1.BackColor, &H80000005)
End Sub

In this example, an event parameter called PropBag is used as a PropertyBag object. The WriteProperty method of PropBag is then invoked to save the value of the BackColor property of a TextBox control called Text1.

As mentioned earlier, the PropertyChanged method is used to ensure that the system knows a property has been changed. If this method isn’t used, it is possible the system will overlook a changed property value. By invoking this method, you make sure that the WriteProperties event is fired.

The ReadProperties event is used to load values of properties from the PropertyBag. The PropertyBag is a parameter of ReadProperties, under the name of PropBag. Also similar to WriteProperties, the PropertyBag is used to invoke a method within the event. ReadProperty is a method of PropertyBag that has two arguments: the property’s name (as a String value) and the value of the property.

The ReadProperties event occurs almost every time a control is instantiated. The only time the property doesn’t occur when the control is instantiated is when a developer puts the control on a container (such as a form) from the Toolbox. This is because the properties haven’t been initialized yet. When this happens, the InitProperties event occurs.

InitProperties is used to set the default values of the custom properties you create. They are constant values used to initialize values to default properties, when an instance of the control is created for the first time. In fact, the only time it fires is when a developer places your control on a container for the first time. This allows your suggested settings to be applied to the control, but doesn’t affect changes made by the developer once the control is used.

ActiveX Control Interface Wizard

The ActiveX Control Interface Wizard is used to define the properties, methods, and events of a user interface and create code for the members you define. Using this program automates much of the programming we’ve covered in this section.

To run the wizard, open an ActiveX control project to which you wish to apply the wizard’s settings. From the Project menu, select Add User Control, and select ActiveX Control Interface Wizard from the dialog box that appears. This will start the wizard.

Like VB version 5, you can also load the ActiveX Control Interface Wizard into the Add-Ins menu by way of the Add-In Manager. To have the wizard appear as a menu item in your Add-Ins menu, click the Add-Ins menu and select Add-In Manager. The Add-In Manager will appear with a listing of available Add-Ins. Select VB 6 ActiveX Ctrl Interface Wizard from the list. To load the wizard into the menu check the Loaded/Unloaded check box. To have the wizard automatically load when you start VB, check the Load on Startup checkbox. Click OK, and you can now start the wizard from your Add-Ins menu.

The first screen of the wizard explains what it is used for. If you don’t want to see the introduction screen in the future, click the check box labeled Skip this screen in the future. Clicking Next will bring you to the Add Interface Members screen, shown in Figure 9-2. Here, you can select properties, methods, and events you’d like to use for your control. The left pane lists available members to add to the control, and the right pane lists all members that have been made Public in your UserControl. By clicking the arrow buttons between the panes, you are able to add and remove members from your control.

Figure 2: Select Interface Members screen of the ActiveX Control Interface Wizard

After selecting the members you want from your control, click Next to bring yourself to the Create Custom Interface Members screen. This screen allows you to add, edit, and delete events, properties, and methods to your control. By clicking the New button, you are greeted with the Add Custom Member dialog box. This dialog box allows you to enter a name for your member and select whether it is a property, method, or event. The screen that appears when clicking Edit is similar to this, allowing you to choose what kind of member it will be. You are not able to actually enter code for the member through this screen.

The next screen is Set Mapping, which allows you to map properties, events, and methods to specific constituent controls in your ActiveX control. For example, if you wanted to apply the BackColor property to a text box, you would first select BackColor from the left pane. In the Maps to section, you would select your TextBox object from the Control listbox and the control’s member (such as BackColor) from the Member listbox.

Any members you don’t map on this screen are dealt with when you click Next. The Set Attributes screen allows you to set the attributes—data type, default value, arguments, and read and write behavior—for any members you didn’t map in the previous screen. Members listed here have default values already set for them, which will be applied if you don’t change them. After you’ve set these attributes, clicking Next brings you to the final screen. Clicking Finish here or on the final screen will apply your settings to the UserControl.

Testing a Control

Because developers will be using your ActiveX control in their applications, it is important to test the Design time behavior of your control in addition to its runtime behavior. This means seeing how the control behaves in VB’s Design time environment, when it is added to a form and coded. When you’ve finished testing its Design time behavior, it is equally important that your run the control, to see that it doesn’t cause errors at runtime.

Testing and Debugging an ActiveX Control

The easiest way to test the Design time behavior of a control is to add a separate VB project to your ActiveX control project. In doing so, you can add your control to the test project, and determine if its behavior is what you expected or desired. To create a test project for your control, select Add Project from the File menu, and then choose Standard EXE. This will create a project group.

When you have a project group, you can work on the design of a form and the control at the same time. However, when you have the ActiveX control’s designer open, its icon in the Toolbox will be disabled, and appear grayed-out. This means you must close the designer if you want to add it to a form in your test project.

Exam Watch: Microsoft loves to hit people with questions that deal with things that go wrong. Remember that if your ActiveX control is grayed-out in the Toolbox, you most likely have the UserControl open in the background.

Once the control’s icon becomes available in the Toolbox, you are able to add it to a form, just as you would any standard control. After adding it to a form, you can then see if its features act properly in the Design time environment, by using it as any developer would. You should add code to the form that manipulates its properties and events to see if these result in errors. Once you’ve confirmed that its Design time behavior is what you expected, you are then ready to see how the control performs at runtime.

Before running the project, you must specify which project you want to set as the start-up project. This is the project that you want to start when Start is chosen from the Run menu. Right-clicking a project in the Project window and selecting Set as Start Up will set it as the start-up project. If you want to see how your control runs by itself in a browser, set the ActiveX control project as the start-up. If you want to see how code in a form interacts with the control and view it in a window, set the standard EXE project as start-up.

When debugging an ActiveX control, you should add Debug statements to the control’s code to see if values are what you expect them to be and to ensure that code is acting as expected. For example, if you had a variable name intNum, you could add the following line of code to view what its value is at runtime:

Debug.Print intNum

When this line of code is reached, the value of intNum will be displayed in the Immediate window. You can also set watch variables and use other debugging tools in VB (as covered in Chapter 11) to test and debug your control.

Exercise 9-2: Testing and Debugging an ActiveX Control

Open the project you created in Exercise 9-1.

From the File menu, select Add Project, and then choose Standard EXE.

Open your control’s designer and double-click the command button, so the Code window appears. Below the code you added in Exercise 9-1, add the following code:

Debug.Print yearsleft
Debug.Print daysleft
Debug.Print hoursleft
Debug.Print minutesleft

Close the control’s designer and open the form of your new standard EXE project. Double-click the Y2K icon in the Toolbox to add the control to your form. Resize the control and form, so the control is fully visible in the form.

In the Project window, select the standard EXE project. Right-click it and select Set as Start Up.

From the View menu, select Immediate window. This will bring up the Immediate window, which you will use to view the values of your variables.

Press F5 to run your project. Notice that it starts in a window. Click the command button and view the values of your variables in the Immediate window.

Stop your project, and return to Design time. In the Project window, select the ActiveX control project as your start-up project. Right-click the project and select Set as Start Up.

Press F5 to run your project. Notice that your Internet browser starts, displaying the control. Click the command button and view the values of your variables in the Immediate window.

Creating Property Pages

In using VB, you’re probably already somewhat familiar with the concept of Property Pages. They allow you to display properties through a screen that appears when the user right-clicks the control and chooses Properties. Rather than just displaying properties in the Properties window, the developer is able to use a more organized, and occasionally more advanced, grouping of properties.

The first step to creating a Property Page is to select Add Property Page from the Project menu. This will display a dialog box with two choices. You can select Property Page to add a blank Property Page to your project, or Property Page Wizard, which steps you through the process of creating a Property Page. In this section, we’ll cover both options.

Creating and Enabling Property Pages for an ActiveX Control

Once you’ve decided which route you’re going to use (that is, the wizard or creating a Property Page manually), you must decide what properties you want to add to the page. Choosing Property Page places a blank Property Page in your project that looks like a UserControl or form. It is in this container that you can add the controls you want to use for accessing various properties.

When you create a Property Page you should place complex properties on different pages or tabs. For example, on a Fonts tab, you could have Font Size, Font Name, and other related properties. As you go through the Properties window, you can spot such complex properties by the ellipsis button that appears when a certain property is selected.

While a Property Page appears similar to a form, it quickly becomes apparent that it is not one. For example, one thing lacking is a Load event, while a number of events that aren’t part of a form appear in the Property Page. These events are essential to programming with Property Pages.

The SelectionChanged event is used to check the values of properties and change them. This event fires when the Property Page is displayed, or when there is a change in the selected controls. A change in selected controls is a result of the SelectedControls collection. This is a collection of all controls that have been selected on the page. When you hold the control key down while clicking controls or lasso a number of controls by holding down the left mouse key and dragging over them, they become elements of the SelectedControls collection. The collection is zero-based, making its first element designated as shown in the following example:

SelectedControls(0)

It also has a Count property that allows you to tell how many controls are part of the collection. To refer to a property of one of the controls in the collection, you use the following syntax:

SelectedControls(Index).BackColor

The ApplyChanges Event is used to write information from a Property Page to the actual property of a selected control. This event occurs when the user clicks an Apply or OK button on the Property Page or switches to another Property Page on the control. For the Apply button to work, however, the Changed property of the Property Page has to be set to true. The Changed property acts as a flag that enables the Property Page to determine if some property has indeed been changed.

After you’ve added code to the different events, you are then ready to connect the Property Page to your control. This is done by double-clicking the UserDocument in the Project window. Doing this will bring up the properties for the UserDocument in the Properties window. In the Properties window, select the PropertyPages property, and then click the button (with an ellipsis) that appears. This will bring up the Connect Property Pages dialog box.

This dialog box contains a list of all Property Pages available in the current project. By clicking the check box beside the name of a Property Page, the pages are associated with your control. The up and down arrows adjacent to the listing allow you to specify the order these pages will appear. In other words, when the developer chooses Properties, he or she sets the order of the tabs that appear.

Using the Property Page Wizard

The Property Page Wizard automates the task of creating a Property Page. Once this wizard is started, you are greeted with an introduction screen. To avoid seeing this in later sessions, click the Skip this screen in the future check box.

The Select the Property Pages screen is next in the wizard. This screen allows you to specify what Property Pages, which are already part of the project, you’d like to associate with your control. By clicking a check box beside a Property Page name, it will be added to the group of pages for that control. If you would like to add a new page, click the Add button and type in a name for your new Property Page. The Rename button allows you to rename an existing Property Page.

The next screen is Add Properties, shown in Figure 9-3. The right-hand side of this screen has a number of tabbed pages, with each tab possessing the name of each Property Page added in the previous screen. Clicking on these tabs allows you to switch from one Property Page to another. After selecting the Property Page you want to modify, you can add various properties from a pane on the left side of the screen. These are all Public properties that are part of your control. Arrows between this pane and the tabbed pages allow you to add and remove properties from the pages. When you’ve arranged the properties you want on each page, click Next to continue to the final page. After clicking Finish, your Property Page will be built and associated with your control.

Figure 3: The Add Properties screen of the Property Page Wizard

Once you’ve created the page, you are then ready to add any necessary code to its events and test it. To view the Property Page, simply right-click your control and choose Properties. The Property Page will appear.

On the Job: The Property Page Wizard is a handy tool for creating Property Pages. It is often easiest to create Property Pages with this wizard and then edit or add code to the necessary events afterward. Many programmers turn their noses at wizards because of their limited uses. This is because many wizards take longer to use than it takes to create something manually. This is not the case with the Property Page Wizard, which creates and associates Property Pages faster than you could ever do it manually.

Creating a Data-Bound Control

VB enables you to bind properties of your ActiveX control to a data source, thereby making data-aware controls. This means your control needs a DataSource and DataField property to indicate which control and which field to bind to, respectively. In creating a data-bound control, you can bind the properties and display data from the data source.

Enabling the Data-Binding Capabilities of an ActiveX Control

To enable the data-binding capabilities of an ActiveX control, you must first open the Code window of your UserControl and move to the Property procedure to which you want to bind the data. This is done through the Procedure Attributes dialog box, which is accessed from the Tools menu. From this dialog box, confirm that the Property procedure that will reflect the data is displayed in the Name listbox. If it isn’t, select the correct Property procedure from the listbox, then click the Advanced button. This expands the dialog box to look like the screen illustrated in Figure 9-4.

Figure 4: Procedure Attributes dialog box expanded

The Data Binding section of this dialog box is where you will enable the data-binding capabilities of the control. First you must click the Property is data bound check box. This will enable the settings below it. Checking the This property binds to DataField check box finishes your task.

When this is done, the DataField and DataSource properties will display in the Properties window when developers use your control. They are then able to set what field and source will be used to retrieve data from, and save data to.

Creating a Data Source Control

In Chapter 5 we learned how to create a data source from a class module. Creating a data source from a UserControl is essentially the same process. In many ways, you will find this section a review of what you learned in Chapter 5.

Like class modules, an ActiveX control can act as a data source for any type of data. This includes ActiveX Data Objects (ADO), OLE (object linking and embedding) providers, ODBC (open database connectivity) sources, and so on. When you’ve created your data source, you are then able to have data consumers use it to display and manipulate data.

Creating an ActiveX Control that Is a Data Source

The first step to creating a data source is to make a reference to an object library. The object library you choose depends on the type of data you wish to use. If you were creating a data source for ADO, you would need to make a reference to Microsoft ActiveX Data Objects 2.0 Library. This is done by selecting References from the Project menu and selecting the library from the list that appears.

Once you’ve made the reference, you must then change the DataSourceBehavior property of your UserControl, as shown in Figure 9-5. This property appears in the Property window and is used to set whether the UserControl will act as a data source. In this property, you have two choices: 0—vbNone and 1—vbDataSource.

Figure 5: Properties window, showing how the DataSourceBehavior property is changed

By default, vbNone is selected for a UserControl, and signifies that the UserControl isn’t set to be a data source. When the DataSourceBehavior is set to vbDataSource, it sets the control as a data source and adds a new procedure to the UserControl. If you checked through the events of your UserControl, you would see a new event called GetDataMember.

GetDataMember is an event that’s used to set the source of data used by the control. It is here that you’ll specify what record set is to be used. A Recordset object contains a set of records from a database. Should you wish to provide an option of multiple data sources, you could use a Select Case statement in this procedure. The source name would be passed to the Select Case statement as a DataMember argument. In most cases however, you’ll use a single source of data that is set as shown in the following syntax:

Set Data = RecordsetName

or, as is more commonly done:

Set Data = rs

By using Set Data = rs, you are assigning the variable rs (which would be the record set) to Data, which is an argument of GetDataMember. For this example to work however, the variable rs would be declared as a Recordset object, as shown below:

Private rs as ADODB.Recordset

The next step is to create a new instance of the Recordset object in the Initialize event of your UserControl. This is done with the following example of code, which creates a new instance of a record set called rs:

Set rs = New ADODB.Recordset

Having created your record set, you must then add any necessary properties to it. This is done the same way that properties are added to components, but since we’re using ADO, we’re able to use a shorthand method of appending Field objects. These are objects that represent columns of data that have the same data type. These Field objects are what make up the Fields collection, which you use to append Field objects that show, delete, and modify data. To append a field, you would use the following syntax:

Fields.Append "fieldname", data type

Using this example of code, we can create fields that are then populated with data, as shown below:

Dim intNum As Integer
intNum=1000
With rs
.AddNew
.Fields("MyNumber") = intNum
.Update
End With

In the above example, a variable called intNum is declared as an Integer and assigned the value of 1,000. We then add a new field to the Fields collection, which is assigned the value of intNum. The record set is then updated, populating it with our first record.

Begin Q&A

I want to change the icon that will appear in VB’s Toolbox, representing my ActiveX control. How do I do that? Use the ToolBoxBitmap control to specify what icon will represent your control in the Toolbox.
I’ve created a project group consisting of an ActiveX control project and a standard EXE. I want the form with my control to start when I press F5, but Internet Explorer keeps starting to display my control. Why? You haven’t set the standard EXE project as the start-up project. To do this, right-click the project in the Project window and select Set as Start Up.
I want to add properties, methods, and events to my ActiveX control. What’s the easiest way? Use the ActiveX Control Interface Wizard. It will step you through the process of defining members for your control.
I want to create a Property Page. What’s the easiest way? Use the Property Page Wizard. It will step you through the process of creating a Property Page for your control.
What is the DataSourceBehavior property in a UserControl? This is used to set whether the UserControl will act as a data source.

From the Classroom

The ActiveX Generation

What does a developer call a $300 million industry of third-party OLE or COM objects? The ActiveX Generation of course! Visual Basic programmers born into the fold with version 5 have grown up on a diet of ActiveX controls. Given the rapid rise in popularity, especially in web-based development where the developer can dictate the brand of browser used as a thin-client host container, ActiveX controls are one hot form of COM object. Now with the 2nd edition of Visual Basic capable of authoring ActiveX controls, the ActiveX control industry is poised to explode.

In addition to the introduction of database application support in VB 3.0 and classes and OLE automation servers in VB 4.0, Visual Basic 5.0 brought on the first introduction to ActiveX controls, continuing the march of Microsoft’s first product into the universe of object-oriented development.

ActiveX controls start with a Visual Basic ActiveX Control project. This creates a default UserControl object which provides the windowless canvas for adding user interface elements. ActiveX can leverage Property Pages, Property value persistent, as well as be used to expose properties, methods, and/or events. In essence, ActiveX controls are mini applications that can be embedded in a variety of host applications, including Internet Explorer, other ActiveX controls, and, of course, stand-alone applications.

Exam concerns should focus on the basic elements involved in creating ActiveX controls, syntax for embedding ActiveX controls in web pages, registration of controls on a client system, syntax for using the Web Browser control, and syntax issues for exposing properties, methods, and events defined within an ActiveX control. Be aware of how to define read-only properties and digital signature issues.

By Michael Lane Thomas, MCSE+I, MCSD, MCT, A+

Certification Summary

ActiveX controls can be created in VB by creating a new project and choosing ActiveX control, adding a User Control to an existing project, or by changing an existing project to an ActiveX control project through Project Properties. When you have created an ActiveX control, you can then begin to add features and controls to it.

By implementing code into a UserControl, you are able to expose properties, methods, and events to other objects. This can be done by creating new Public members or by delegating members through wrapper code.

Because other developers may use your ActiveX controls, it is important to test it in both Design mode and runtime. By creating a project group, you can add your control to a form and determine if it behaves as expected in Design mode. By using VB’s debugging tools and Debug statements in your code, you are able to debug your control during runtime.

Property Pages provide an alternate way of displaying properties. Property Pages allow your control to have an interface for displaying related and detailed properties. These can be created either manually or by used the Property Page Wizard.

Creating a data-bound control is a relatively simple procedure. Creating a control that acts as a data source, on the other hand, is more involved. This requires setting the DataSourceBehavior to vbDataSource, creating a record set, and populating it. If these procedures aren’t followed correctly, your data source will fail to work.

Two-Minute Drill

There are three ways to create an ActiveX control. The first is to select New Project from the File menu and choose ActiveX control from the New Project dialog box that appears. The second method is to change an existing project into an ActiveX control. This is done through Project Properties, which is accessed from the Project menu. Finally, you can create an ActiveX control by adding a user control to a project.

The UserControl is similar to a form in a standard EXE project. It acts as a container that holds controls and features you add to your ActiveX control. Unlike forms, you don’t refer to the UserControl by its name in code.

Implementing methods in an ActiveX control is similar to implementing methods in other ActiveX components and class modules. You can create your own custom methods as Public procedures in the UserControl, then invoke the methods in code. After adding code to your Public procedure, you can then add the ActiveX control to a form. Code within the form (or a control on the form) invokes the method.

You can create custom properties for an ActiveX control with either Public variables or Property procedures. It is advised that you use Property procedures (that is, Property Let, Property Set, and Property Get) rather than Public variables.

The PropertyBag object is used to load and save persistent properties. It allows property values to persist because the PropertyBag object itself persists, as instances of controls are created and destroyed. The PropertyBag object is used in the parameters of the WriteProperties and ReadProperties events. The WriteProperties event is used to save property values to the PropertyBag object using the WriteProperty method. TheReadProperties event is used to load property values from the PropertyBag object using the ReadProperty method.

The ActiveX Control Interface Wizard is used to automate the task of defining the properties, methods, and events of a user interface, and to create code for the members you define. Using this program automates much of the programming.

It is important to test the Design time behavior of your control by seeing how the control behaves in VB’s Design time environment when it is added to a form and coded. When you’ve finished testing its Design time behavior, it is equally important that your run the control, to see that it doesn’t cause errors at runtime. The easiest way to test the Design time behavior of a control is to add a separate VB project to your ActiveX control project. You can then add your control to the test project, and determine if its behavior is what you desired.

When you have the ActiveX control’s designer open, its icon in the Toolbox will be disabled, and appear grayed-out. You must close the ActiveX control's designer if you want to add it to a form in your test project. Once the control’s icon becomes available in the Toolbox, you can add it just as you would any standard control.

Before running the project group, you must specify which project you want to set as the start-up project. This is the project that you want to start when Start is chosen from the Run menu. Right-clicking a project in the Project window and selecting Set as Start Up will set it as the start-up project. If you want to see how your control runs by itself in a browser, set the ActiveX control project as the start-up. If you want to see how code in a form interacts with the control and view it in a window, set the standard EXE project as start-up.

Once you’ve decided to create a Property Page (manually, or by using the Property PageWizard) you must decide what properties you want to add to the page. Choosing Property Page places a blank Property Page in your project that looks like a UserControl or form. You add the controls you want to use for accessing various properties in this container.

VB enables you to bind properties of your ActiveX control to a data source and make data-aware controls. Your controls then need a DataSource and DataField property to indicate which control and which field to bind to, respectively. In creating a data-bound control, you can bind the properties and display data from the data source.

To enable the data-binding capabilities of an ActiveX control, you must first open the Code window of your UserControl and move to the Property procedure to which you want to bind the data. This is done through the Procedure Attributes dialog box, which is accessed from the Tools menu.

Like class modules, an ActiveX control can act as a data source for any type of data. When you’ve created your data source, you are able to have data consumers use it to display and manipulate data. The first step to creating a data source is to make a reference to an object library. The object library you choose depends on the type of data you wish to use. Once you’ve made the reference, you must then change the DataSourceBehavior property of your UserControl. This property appears in the Property window and is used to set whether the UserControl will act as a data source. By default, vbNone is selected for a UserControl. When the DataSourceBehavior is set to vbDataSource, it sets the control as a data source and adds a new procedure to the UserControl.

GetDataMember is an event that’s used to set the source of data used by the control. It is here that you’ll specify what record set is to be used. A Recordset object contains a set of records from a database. Should you wish to provide an option of multiple data sources, you could use a Select Case statement.

Self Test

The following Self Test questions will help you measure your understanding of the material presented in this chapter. Read all the choices carefully, as there may be more than one correct answer. Choose all correct answers for each question.

  1. Which of the following are valid ways to refer in code to a UserControl named UserControl1?
    1. UserControl
    2. Me
    3. UserControl1
    4. None of the above
      A. UserControl. When referring to a UserControl in your code, you must use the word UserControl rather than its name. The Me keyword doesn’t work either.
  2. Which of the following are valid ways of creating an ActiveX control?
    1. Select New Project from the File menu, then choose ActiveX Control
    2. Change the project type of a current project to ActiveX control in Project Properties
    3. Click the ActiveX Control button from the VB toolbar
    4. Select Components from the Project menu, then select ActiveX Control
    5. Select Add User Document from the Project menu, and select an ActiveX Control
      A. (Select New Project from the File menu, then choose ActiveX Control) and B. (Change the project type of a current project to ActiveX control in Project Properties.)You can create an ActiveX control by selecting New Project from the File menu, then choosing ActiveX Control. You can also change the Project Type of the current project to ActiveX Control in Project Properties to create an ActiveX control.
  3. You have decided to use the ActiveX Control Interface Wizard to create a user interface for your ActiveX control. When you try to use this wizard, it refuses to create the interface. Why?
    1. You must start with an empty UserControl before starting the wizard.
    2. You must have a form added to your project before starting the wizard.
    3. The wizard isn’t used to create user interfaces.
    4. The project must be saved before starting the wizard.
      C. The wizard isn't used to create user interfaces. The ActiveX Control Interface Wizard isn’t used to create user interfaces. You must add the elements of a user interface to a UserControl before starting the wizard.
  4. What are ActiveX control projects compiled as?
    1. DLL files
    2. EXE files
    3. CTL files
    4. OCX files
      D. OCX files. ActiveX control projects are compiled into OCX files.
  5. What property will determine the icon representing an ActiveX control, which will appear in the developer’s VB Toolbox?
  6. Picture
  7. Image
  8. ToolBitmap
  9. ToolBoxBitmap
    D. ToolBoxBitmap. The ToolBoxBitmap property is used to specify what icon (representing the control) will appear in the VB Toolbox.
  10. You want to test an ActiveX control’s behavior in Design mode. How can you do this?
    1. Set the Debug property in Project Properties to Design mode
    2. Compile the project into a CTL, then start a new EXE project for testing
    3. Add a standard EXE project to your ActiveX control project to create a project group
    4. You can only test ActiveX controls at runtime
      C. Add a standard EXE project to your ActiveX control project to create a project group. By creating a project group, you can test the Design mode behavior of an ActiveX control.
  11. You have created a project group consisting of your ActiveX control and a standard EXE project. Each time you attempt to run your ActiveX control from VB, Internet Explorer opens and displays the control. You want to see how the control runs on the form to which you added the control. Why is it always starting in Internet Explorer, and how can you get the project with the form to start when you click Run?
    1. The default behavior of an ActiveX control is to start in a browser, so you must uninstall Internet Explorer from your system.
    2. The start-up project hasn’t been set. Right-click the ActiveX Control project in the Project window and select Set as Start Up.
    3. The start-up project hasn’t been set. Right-click the standard EXE project in the Project window and select Set as Start Up.
    4. The control won’t run in a form until it’s compiled. The ActiveX control must be compiled first by select the Make… item from the File menu.
      C. The start-up project hasn't been set. Right-click the standard EXE project in the Project window and select Set as Start Up. If you want the control to start in the form, you need to set the standard EXE project in your project group as the start-up project.
  12. Which of the following will create a custom event in a UserControl that will be exposed to other objects?
    1. Private Event MyEvent()
    2. Public Event MyEvent()
    3. Public MyEvent
    4. Private MyEvent
      B. Public Event MyEvent(). Using Public Event will create a custom event that will be exposed to other objects.
  13. Which of the following is used to store persistent property values?
    1. PropertiesBag
    2. PropertyBag
    3. PropBag
    4. Pbag
      B. PropertyBag. The PropertyBag object is used to store persistent property values.
  14. When doesn’t the ReadProperties event occur?
    1. When a developer puts the control on a form from the Toolbox
    2. When the container is instantiated
    3. When the developer enters runtime from the Design mode environment
    4. When a property value needs to be read
      A. When a developer puts the control on a form from the Toolbox, the InitProperties event fires, not the ReadProperties event.
  15. Which of the following are not events of a Property Page?
    1. Load
    2. SelectionChanged
    3. ApplyChanges
    4. SelectedControls
      A. (Load)and D. (SelectedControls) Property Pages don’t have a Load event. SelectedControls isn’t an event, but a collection of controls that have been selected.
  16. You want to connect a Property Page to a UserControl. How will you do this?
    1. Through Project Properties, under the Project menu
    2. Select PropertyPages from the Properties window, then select the pages to connect
    3. Select Pages from the Properties window, then select the pages to connect
    4. Through References from the Tools menu
      B. Select PropertyPages from the Properties window, then select the pages to connect.
  17. Which event is used to write information from a Property Page to the actual property of a selected control?
    1. Change
    2. OnChange
    3. Apply
    4. ApplyChanges
      D. ApplyChanges is an event used to write information from a Property Page to the actual property of a selected control.
  18. Which method ensures that the WriteProperties event is fired?
    1. PropertyChanged
    2. Change
    3. Write
    4. PropertyWrite
      A. The PropertyChanged method ensures that the WriteProperties event is fired.
  19. Which of the following events is used to check the values of properties and change them?
    1. SelectedChanged
    2. PropertyChanged
    3. Changed
    4. WriteProperties
      A. SelectedChanged is an event that’s used to check the values of properties and change them.
  20. Which property in the Properties window is used to set whether a UserControl is to act as a data source?
    1. DataSource
    2. DataBindingBehavior
    3. DataSourceBehavior
    4. Data
      C. The DataSourceBehavior property is used to set whether a UserControl is to act as a data source.
  21. You have changed a property value in your ActiveX control. When will the WriteProperties event fire?
    1. After Load
    2. Before Terminate
    3. After Terminate
    4. Before GetDataMember
      B. Before Terminate. The WriteProperties event occurs immediately before the UserControl’s Terminate event, when one or more property values have changed.
  22. Which of the following objects contain a set of records from a database?
    1. Record
    2. Recordset
    3. Field
    4. Fields
      B. The Recordset object contains a set of records from a database. It is made up of Field objects, which are part of the Fields collection.
  23. You have decided to create a data source. What must you set to create the GetDataMembers event?
    1. Set DataBindingBehavior to vbDataBound
    2. Set DataSourceBehavior to vbDataSource
    3. Set DataBindingBehavior to vbSimpleBound
    4. Set DataBindingBehavior to vbComplexBound
      B. Set DataSource Behavior to vbDataSource. When DataSourceBehavior is set to vbDataSource, the GetDataMembers event is created.
  24. Where will you go to enable the data binding capabilities of an ActiveX control?
    1. From Tools, select Procedure
    2. From Tools, select Procedure Attributes
    3. From Tools, select Procedure Attributes, then click the Advanced button
    4. From Project, select Procedure Attributes, then click the Advanced button
      C. From Tools, select Procedure Attributes, then click the Advanced button. Enabling the data-binding capabilities of an ActiveX control is done through the Procedure Attributes dialog box, which is accessed from the Tools menu. From here, click the Advanced button to bring up the screen where you can enable data binding.
  25. You are creating a custom property for your ActiveX control. In this property you have created a Private variable, which will be used to store the property’s value. What will you use to retrieve the value of this variable?
    1. Property Get
    2. Property Let
    3. Property Set
    4. Property Net
      A. Property Get is used to retrieve the value from this variable.
  26. You are debugging an ActiveX control, and want to monitor the value of a variable called strName in the Immediate window. What code will you add to your project to view this?
    1. Debug.strName
    2. Debug.Print strName
    3. Debug strName
    4. None. Set the variable in the Immediate window, and it will automatically watch its value
      B. Debug.Print strName. Debug.Print can be used (followed by the variable’s name) to monitor the value of a variable in the Immediate window.
  27. You have created a new ActiveX control project. In the Name property of the UserControl, you attempt to change its name so it’s the same as the project’s name. An error results. Why?
    1. There is already a UserControl that has been given the same name as the project.
    2. There is already a form that has been given the same name as the project.
    3. You are not allowed to give a UserControl the same name as the project containing it.
    4. There is no reason. You must not have created a new ActiveX project.
      C. You are not allowed to give a UserControl the same name as the project containing it. VB won’t allow you to give a UserControl the same name as the project containing it. If you try to do so, an error results.
  28. You have created an ActiveX control project. You want to be able to test the control, by creating a project group and testing the control on a form in the other project. How can you create a project group?
    1. From the Project menu, select Add Project
    2. From the Project menu, select Add Project, then choose a new project from the dialog box that appears
    3. From the File menu, select Add Project, then choose a new project from the dialog box that appears
    4. From the File menu, select New Project, then choose a new project from the dialog box that appears
      C. From the File menu, select Add Project, then choose a new project from the dialog box that appears.
  29. You have authored an ActiveX control and want developers who use your control to have the ability to access methods of constituent controls on your UserControl. How will you do this?
    1. Methods of constituent controls are visible by default, so you don’t need do anything.
    2. Methods of constituent controls must have its methods exposed by setting the control’s Exposed property (in the Properties window) set to True.
    3. Since constituent controls are Windows controls that appear on the Toolbox, you don’t need to do anything. Windows will have the methods exposed.
    4. Create a wrapper for it in code that delegates the method as Public.
      D. Create a wrapper for it in code that delegates the method as Public. If you’ve authored a control and want a developer to access the methods of a constituent control on your UserControl, you must create a wrapper for it, which delegates a method as Public.
  30. You’ve created a custom method in an ActiveX control. After adding the control to a form, you decide to invoke the method from the form’s code. If the UserControl is named MyControl and the method is called GetName, how would you do this?
    1. UserControl.MyControl.GetName
    2. UserControl1.GetName
    3. Me.MyControl
    4. MyControl.GetName
      D. MyControl.GetName. You can invoke a custom method like any other method. In this case, to invoke the MyControl GetName method, you would type MyControl.GetName.
  31. A user selects several controls on your ActiveX control. What code can you implement to determine how many controls have been selected?
    1. The Count property of Controls
    2. The Count property of SelectedControls
    3. The Control property of UserControl
    4. The Selected property of Controls
      B. The Count property of SelectedControls allows you to determine the number of controls that have been selected on a UserControl.
  32. Which of the following will create a new instance of an ADO database record set called rs?
  33. Set rs = New ADODB.Recordset

    1. Set rs As Recordset
    2. ADODB.Recordset = rs
    3. Property Get rs = New ADODB.Recordset
      A. Set rs = New ADODB.Recordset. To create a new record set meeting the criteria given, the correct line of code would be Set rs = New ADODB.Recordset.
  34. You have created a new ActiveX control and want to add it to a form. How will you do this?
    1. Double-click the control’s icon in the Toolbox
    2. Double-click the control’s icon in the Toolbox, then draw the control on the form
    3. Click the control’s icon in the Toolbox
    4. Click the control’s icon in the Toolbox, then draw the control on the form
    5. None of the above. You can only add a custom ActiveX control to a form through code
      A. (Double-click the control's icon in the Toolbox) and D. (Click the control's icon in the Toolbox, then draw the control on the form). To add an ActiveX control to a form, double-click the control’s icon in the Toolbox, or click the control’s icon and then draw the control on the form.
  35. You want to run the ActiveX Control Interface Wizard. How will you start this wizard?
    1. From the Tools menu, select ActiveX Control Interface Wizard
    2. From the Project menu, select ActiveX Control Interface Wizard
    3. From the Project menu, select Add User Control, the select ActiveX Control Interface Wizard when the dialog box appears
    4. From the Project menu, select Add User Control, then select ActiveX Control
      C. From the Project menu, select Add User Control, then select ActiveX Control Interface Wizard when the dialog box appears, to run the wizard.
  36. You have created a custom event called GetNames. Which of the following examples of code will cause this event to fire?
    1. Raise GetNames
    2. RaiseEvent GetNames
    3. GetNames.RaiseEvent
    4. GetNames.Raise
      B. RaiseEvent.GetNames. The RaiseEvent keyword is used to cause an event to fire. In this case, you would use the code RaiseEvent GetNames.
  37. What event is used to set the source of data used by a control?
    1. WriteProperties
    2. ReadProperties
    3. Initialize
    4. GetDataMember
      D. The GetDataMember event is used to set the source of data used by the control.
  38. You want to change the BackColor of the third element of the SelectedControls collection. Which is the correct code to use to access this element?
    1. SelectedControls.BackColor
    2. SelectedControls.BackColor
    3. SelectedControls.BackColor
    4. SelectedControls.BackColor
      B. SelectedControls.BackColor. The SelectedControls collection’s first element is zero. Therefore, to access the third element, the correct code would be SelectedControls.BackColor.
  39. When does the InitProperties event occur?
    1. Any time a control is instantiated
    2. When a developer places a control on a form from the Toolbox
    3. Whenever ReadProperties event is fired
    4. Whenever PropertyChange is invoked
      B. When a developer places a control on a form from the Toolbox. When a developer places a control on a container (such as a form) from the Toolbox, the InitProperties event fires.
  40. What is wrong with the following example of code, which is used in a UserControl named MyUserControl?
  41. MyUserControl.BackColor=vbRed

    1. There is no property called BackColor for a UserControl.
    2. You can’t refer to a UserControl by its name in code.
    3. The Me keyword should have been used to refer to the UserControl.
    4. You must specify the color by its hexadecimal value.
      B. You can’t refer to a UserControl by its name in code.
  42. You have created a project group to test your ActiveX control project, but when you go to add the control to a form, you find the ActiveX control is grayed-out in the Toolbox. Why?
    1. You must close the form for the control to become available.
    2. You must close the ActiveX control’s designer before the control becomes available.
    3. You need to initialize variable values before the control becomes available.
    4. You need to give the control a custom icon before it becomes available.
      B. You must close the ActiveX control's designer before the control becomes available. The ActiveX control’s designer must be closed before the ActiveX control’s icon becomes available in the Toolbox.
  43. Which of the following can an ActiveX control act as a data source for?
    1. ADO
    2. OLE providers
    3. ODBC sources
    4. All of the above
      D. All of the above. An ActiveX control can act as a data source for any type of data.
  44. You are using the Property Page Wizard. You have reached the Add Properties screen. What does this screen enable you to do?
    1. Add properties, methods, and events to your ActiveX control
    2. Add properties, methods, and events to your PropertyPage object
    3. Add properties to a Property Page, which will display when Properties is invoked from the contextual menu
    4. Add custom properties to your ActiveX control
      C. Add properties to a Property Page, which will display when Properties is invoked from the contextual menu. The Add Properties screen of the Property Page Wizard is used to add properties to a Property Page. These will display on the Property Page when Properties in invoked from the contextual menu.
  45. You are creating a custom property for your ActiveX control. In this property you have created a Private variable, which will be used to store the property’s value. What will you use to store the value of this variable?
    1. Property Get
    2. Property Let
    3. Property Set
    4. Property Net
      B. (Property Let) and C. (Property Set) Property Let or Property Set is used to store the property’s value.
  46. Which of the following events is used to load property values from the PropertyBag object?
    1. WriteProperties
    2. GetDataMember
    3. ReadProperty
    4. ReadProperties
      D. The ReadProperties event is used to load property values from the PropertyBag.