Basically Visual

June/July 1997

by Peter G. Aitken (c)1997

Originally published in Visual Developer magazine .


ActiveX and the Single Programmer, Part 2

Of all the improvements to be found in Visual Basic 5, the most significant is the ability to create ActiveX components. Many readers may think that compilation to native code is more important, and I admit that is an important and long overdue feature – but in my mind it still only gets second place! ActiveX is Microsoft's way of saying "software components," and we all, especially Visual Basic programmers, need to speak the lingo.

In my previous column we started to create a relatively simple ActiveX control called FancyCmdButton. We gave the control a visual interface, and wrote the code permitting it to respond to events and to pass events along to its container. In this column we will complete the control, giving it properties and a property page. We will also take a look at distribution and security issues.

Creating Control Properties

To provide an ActiveX control with a property, you'll need two things. The first is a place to store the property value within the control. This can be a regular Basic variable or it can be property of one of the ActiveX control's constituent controls. The second thing is a pair of property procedures, which provide the outside world (the container) with access to the property. There are three types of property procedures, although any given property will require at most two of them:

The name of the Property procedures is the same as the property name. Here's how it works: when the container uses the property name (qualified by an object reference, of course) on the left side of an assignment statement, the Property Let procedure is called and passed the value of the expression on the right side of the assignment statement as an argument. Code in the Let procedure must assign that value to the internal storage location for the property. When the property name is used in an expression, the Property Get procedure is called. Code in the procedure sets the current property value as the return value of the function. To create a read-only property, you create a Get procedure without a corresponding Let procedure.

Code in the property procedures can do more than simply set and retrieve property value. You can use these procedures to trigger actions and to perform validity checking, verifying that a new property value is within the permitted range, for example. At their most basic, however, Let and Get procedures are used simply to set and retrieve a property value.

Our FancyCmdButton control will need only one property, called Caption. As you can probably guess, this property will determine the text that is displayed on the control. Because the value will be stored in the Label control’s Caption property, we do not need to declare a separate variable to hold it. Here are the steps to follow to define the Caption property:

  1. Open the FancyCmdButton designer, and then open its code window.
  2. Select Add Procedure from the Tools menu to display the Insert Procedure dialog box.
  3. Specify Caption as the procedure name, and select the Property and Public options.
  4. Click OK.

Visual Basic will create skeletons of the Let and Get procedures for you, and display them in the code editing window. Add the code shown in Listing 1. Be sure to change the type of the Get procedure from Variant to String. Make the same change for the type of the argument to the Let procedure. It is important to remember that the Get procedure’s return type must be the same as the Let procedure’s argument type.

Listing 1: Get and Let procedures for the Caption property.

Public Property Get Caption() As String
Caption = lblButton.Caption
End Property

 

Public Property Let Caption(ByVal vNewValue As String)
lblButton.Caption = vNewValue
End Property

 

Once you have added this code, close the ActiveX designer to put the FancyCmdButton in run mode. Display the test form with the FancyCmdButton on it, and click the button to select it. Look in the Properties window and you’ll see that the control’s property list now includes a Caption property, the one you just defined. If you change this property during design, the text you specify will be displayed on the FancyCmdButton when the test project runs. You can also set the property in code.

Giving the Control a Property Page

We have already seen that ActiveX control properties that you define are automatically displayed in the Visual Basic Properties window. This is fine for some situations, but sometimes you will want to connect a property page to the control. A property page is simply a different method of displaying and accessing the control’s properties. If you want to see a property page in action, put a Microsoft Chart Control (MSChart) on a form, right-click it, and select Properties from the pop-up menu.

You can define one or more property pages for a control. Each page that you define will become a separate tab in the control's Properties dialog box. You are responsible for designing each page, which you do in much the same way as designing a Visual Basic form. Once the page is designed, Visual Basic takes care of all the details of displaying the tabs, and manages the OK, Cancel, and Apply buttons.

Why would you want to use a property pages? Isn't the regular Visual Basic properties window good enough? Property pages are useful when a group of properties interact in a complex fashion. You can design the property page so that related properties are grouped together, making it easier for the user to set them properly. Property pages are useful for controls that you plan to distribute internationally, because the captions on the Property page can easily be changed to suit different language requirements. Finally, Property pages permit controls to be used with development tools that don’t have a Properties window.

Now let's add a Property page to the FancyCmdButton. Make the control project current, then select Add Property Page from the Project menu. In the next dialog box, select the Property Page icon; you can explore the other option, the Visual Basic Property Page Wizard, on your own if you like. Visual Basic adds a property page to the project. The property page form is displayed, and its properties are listed in the Properties window. Note that the Visual Basic title bar indicates that the property page designer is active by displaying [PropertyPage1 (PropertyPage)]. Note also that a property page entry is added to the listing in the Project window.

In the Properties window, change the property page’s Name property to FCBGeneral, and change its Caption property to General. The Caption property will be displayed as the tab title in the Properties dialog box, and the Name property identifies it as the FancyCmdButton’s General property tab (a control can have more than one tab in its Properties dialog box). Select Save from the File menu and save the property page under the suggested name, which is the same as the Name property that you just assigned, FCBGeneral. Visual Basic automatically adds the PAG extension to property page files.

The next task is to design the property page itself – to place controls on it to permit the user to read and set the control’s properties. Since the FancyCmdButton control has only a single property, Caption, this will be a quick task. Designing a property page is essentially the same as designing a regular Visual Basic form, and you have some of the same controls available.

Start by placing a Label control on the Property page. Set the Label’s Caption property to "Caption." Place a Text Box control under the Label, and set its Text property to a blank string and its Name property to txtCaption. Since the control has only a single property, this is all that its property page needs.

A property page interacts with the control it is attached to by means of events. Whenever a Property page is opened it receives a SelectionChanged event. It receives the same event if and when the user changes the controls that are selected on the current form (remember, the property page will be used when the user is designing a form and has placed one of your controls on it). The task is complicated by the fact that there may be more than one control selected, since it is perfectly possible for a user to place two or more FancyCmdButton controls on a form. And, because a property page is modeless, the user can change the selected controls while the property page remains open.

There are basically two ways to deal with multiple selected controls, and which one you use will depend on the nature of the specific property. For some properties, such as ForeColor, it makes sense to permit the user to change the property setting for two or more controls at once. (I am using ForeColor as a generic example; it is not a property that the FancyCmdButton control has.) In contrast, other properties are not appropriate for such batch changes, and if multiple controls are selected you want to disable that property. The Caption property of our demonstration control falls into the latter category.

Dealing with the possibility of multiple selected controls is simplified by the SelectedControls collection, which provides a zero-based index list of the control(s) that are currently selected on the form. You can query this collection’s Count property to see if more than one control is selected, and take the appropriate action. For the single property on the FancyCmdButton’s Property page, use the code shown in Listing 2. This code is placed in the Property page’s SelectionChanged event procedure.

Listing 2: The Property page’s SelectionChanged() event procedure.

Private Sub PropertyPage_SelectionChanged()
' Enable the Text Box for the Caption
' property only if there is a single
' control selected.
If SelectedControls.Count = 1 Then
txtCaption.Enabled = True
' Display the current property value on the property page.
txtCaption.Text = SelectedControls(0).Caption
Else
txtCaption.Enabled = False
End If
End Sub

The code in this listing takes care of displaying the current property value on the property page when the page is opened. It also disables the Text Box on the property page is there are more that one FancyCmdButton controls selected. We still have to write the code that moves information in the other direction – from the property page to the control’s actual properties. There are two parts to this.

First, every property page has a Changed property. You need to write code that sets this property to True if the user makes any changes to the properties listed on the page. When its Changed property is True, the property page automatically enables its Apply button, which the user clicks to apply the new properties to the control. The ideal place to do this is in the Text Box’s Change event procedure, which will be fired whenever the user makes a change to the contents of the Text Box. To add this code, be sure that the property page is displayed (if not, double-click FCBGeneral in the Project box). Then, double-click the single Text Box on the page to display the code for its Change event procedure, and add the code shown in Listing 3.

Listing 3: The Change event procedure for the Text Box on the property page.

Private Sub txtCaption_Change()
' Set the property page's Changed
' property to True if the user
' changes the contents of the Text Box.
Changed = True
End Sub

To actually apply the change, we will make use of the property page’s ApplyChanges event. This event is fired when the user clicks either the OK or the Apply button in the property page dialog box. It is your job to place code in this event procedure that will copy property values from the controls on the property page to the actual control properties. The details of how this is done will depend on the specifics of your control, its properties, and so on. For the single property in the demonstration project the code is simple, consisting of the single line shown in Listing 4.

Listing 4: Applying the property changes to the control in the property page’s ApplyChanges event procedure.

Private Sub PropertyPage_ApplyChanges()
SelectedControls(0).Caption = txtCaption.Text
End Sub

If we had permitted changes to multiple selected controls at once, we could use code like the following (Don’t put this in the project!):

Private Sub PropertyPage_ApplyChanges()
' Declare a generic Object variable
Dim objControl As Variant
 Loop through all selected controls.
For Each objControl In SelectedControls
objControl.Caption = txtCaption.Text
Next
End Sub

Although we have created a property page for the FancyCmdButton control, we have not yet connected it to the control. Here are the steps required to do this:

  1. Open the FancyCmdButton Designer, if it is not already open.
  2. In the property list, scroll down to the PropertyPages property. The current setting of this property will be (none).
  3. Click the button with the ellipsis (...) to display the Connect Property Pages dialog box. The dialog lists the FCBGeneral page that we just designed, as well as three standard property pages that Visual Basic makes available to you (you can explore these on your own).
  4. Click the FCBGeneral property page name to display a checkmark in the box next to it, then click OK.

Now that the property page is connected to the control, you can make use of it in setting the control’s properties – or in this case, property since there is only one! To try it out, you must first close the property page designer. Just like a control, a property page must be in run mode to be available to its control. Then, double-click Form1 in the Project box to display the form for the test program. Right-click the FancyCmdButton control on the form and select Properties from the pop-up menu. The property page that we designed will be displayed. If you change the Caption property on the property page, then click either OK or Apply, you’ll see the new property reflected immediately on the control that is on the test form.

Compiling the ActiveX Control

As long as your ActiveX control is part of a Visual Basic project, it can be used within that project but that’s all. To make it available to other applications, you must compile it into an OCX file. In this section I’ll show you how to compile the demonstration ActiveX control that we created, and how to use the compiled version in your project. Here's how to compile the ActiveX control. First, make sure that all parts of the project group are in design mode. Then:

  1. In the Project window, click AXCtrlDemo to make it the active project.
  2. Open the File menu and select Make AXCtrlDemo.OCX. Visual Basic displays the Make Project dialog box. If you want the OCX file in a different folder, select it here. You can accept the default name for the OCX file, which is the same as the project name (AXCtrlDemo). Or, you can assign a different name if desired, such as FancyCmdButton.
  3. Click OK. Visual Basic will compile the project. No message is displayed upon completion, but if you look in the specified folder you will find the OCX file.
  4. On the File menu, select Remove Project to remove the ActiveX control project from the project group. Visual Basic will display a warning message because the control is referenced from another part of the project group, but you can ignore this message.

Once you have compiled the ActiveX control into an OCX file and removed the ActiveX project from the project group, Visual Basic will automatically switch to using the compiled version in the test project. You’ll see that the icon for the ActiveX control is still displayed in the Visual Basic Toolbox. You can add other instances of the control to the project’s form, access its property page, and so on. Hey, just like a "real" control!

Using the ActiveX Control in Other Projects

When you start a new Visual Basic project, you will not automatically have access to ActiveX controls that you have created. An ActiveX control that you have authored and compiled is no different from any other control on your system. To add them to Visual Basic's Toolbox, you must select Components from the Project menu to display the Components dialog box. Select the control or controls you want available in your project; controls that you created are listed by the name you assigned – in the case of the demonstration control, it will be listed as "Fancy Command Button." Then, the control will be available to your project just like any other ActiveX control.

Distributing ActiveX Controls

After you have put a lot of effort into designing an ActiveX control, you may want to distribute it to other users. Maybe you can even sell a few copies, who knows! Fortunately, the complexities of distribution are handled nicely by the Visual Basic Setup Wizard. Simply specify the ActiveX control project, and the Wizard will walk you through the steps of creating the distribution files/diskettes that are required. Remember that if your control contains any constituent controls, you must have distribution rights for those controls in order to distribute your control.

What about Internet setup? Fortunately, the Setup Wizard comes to the rescue here as well. When you start the Wizard, select Create Internet Download Setup then specify the control's project file. The Setup Wizard will create the compressed CAB file that you then upload to your web site.

Using ActiveX Controls on the Web

What exactly does it mean to "use" an ActiveX control on the web? Remember that one of the important characteristics of an ActiveX control is its ability to be contained within something. So far, you have seen Visual Basic forms used as containers, but that is not all. Specifically, an ActiveX control can be contained within a web page or, more precisely, within a Hypertext Markup Language (HTML) document. When the HTML document is viewed within a web browser, the ActiveX control and its functionality is part of the page. How is this done?

An HTML document contains not only the text that is to be displayed, but also a variety of HTML codes that control the text formatting, page layout, and other aspects of the page’s appearance. To include an ActiveX control in an HTML document, the <OBJECT> code is used. Here’s an example of the HTML code that would insert a FancyCmdButton object on an HTML page:

 

<OBJECT ID="FancyCmdButton" WIDTH=144 HEIGHT=118
CLASSID="CLSID:BDEE83E9-93B6-11D0-95E1-00A024D13692"
CODEBASE="AXCtrlDemo.CAB#version=1,0,0,0">
<PARAM NAME="Caption" VALUE="Click Me!">
</OBJECT>

Let’s dissect this code to see what its various components are.

How do you get the information required to place these codes in your HTML documents? Microsoft has provided a handy tool for this purpose. Called the ActiveX Control Pad, it lets you browse the available ActiveX controls then paste information into HTML documents, along with other HTML document creation capabilities. You can download this program from Microsoft’s web site at http://www.microsoft.com/workshop/author. Finally, when you use the SetupWizard to create a download setup for your ActiveX control, it creates a small HTML file containing the necessary HTML code.

What happens when a web browser loads an HTML document that contains a code that loads an ActiveX object? First of all, it depends on the browser – not all browsers support ActiveX controls. At this writing, only Microsoft Internet Explorer version 3 provides this support. I suspect that Netscape Navigator will soon follow. If your browser supports ActiveX controls, then upon encountering this code the browser checks to see if the ActiveX control has been installed on the system (identifying the control by means of the Class ID in the code). If so, an instance of the control is created and loaded into the page, with the browser serving as container.

What if the ActiveX control has not been installed? Here’s the beauty of using ActiveX on the web. Then, the browser will download the control from the web site itself, and install it on your system. Thus, the web developer can use ActiveX controls in his or her web pages without being concerned about whether the users have the controls installed or not. Once the control has been installed, that’s it – there is no need to install it again. It will be available for any future use.

Security

The ability to automatically download and install ActiveX controls from a remote site is indeed very powerful, but it opens several other important concerns, the main one being (you got it!) security. Unlike some other web technologies, ActiveX components are not crippled or limited in any way. An ActiveX component could erase your entire hard disk, send your financial data files to God-knows-who, or read and transmit password information. Would you want to download such potentially destructive software components from unknown sources? I know that I wouldn't!

Microsoft's solution to the security problem is called digital signing. A digital signature can be embedded within an ActiveX control's code, identifying the source of the component. An ActiveX enabled browser will check for a signature before running any ActiveX component. The user sets the browser security level as desired. For example, you could specify that components that are identified by their signature as being from Microsoft or Borland will automatically be loaded, while for all others you will be asked. In effect, this works like shrink wrapping of store-bought software - the only assurance you have that a program does not contain destructive code or viruses is the name on the package. You can find more information about this and other Internet security technologies on Microsoft's web site at www.microsoft.com/workshop/prog/security.