ActiveX Fundamentals
ActiveX Control Fundamentals
Visual Basic 5 and 6 give you all the
tools you need to create powerful ActiveX controls, which you can then reuse
in all your projects. More precisely, you can create two different types of ActiveX
controls:
-
Private ActiveX controls that can be
included in any type of Visual Basic project. They're saved in files with the
.ctl extension, and you can reuse them in any other Visual Basic project
merely by adding the file to the project. (This is reuse at the source-code
level.)
-
Public ActiveX controls that can be included only in ActiveX
control projects; you have to compile them into OCX files, and then you can
use them in any other Microsoft Windows application written in Visual Basic,
Microsoft Visual C++, or any other development environment that supports ActiveX
controls. (This is reuse at the binary level.)
Visual Basic 5 was the first language
that permitted programmers to create ActiveX controls using a visual approach.
As you'll see in a moment, you can create powerful controls by simply grouping
simpler controls together: These controls are known as constituent controls.
By putting together a PictureBox and two scroll bar controls, for example, you
can create an ActiveX control that can scroll its contents. Visual Basic also
allows you to create an ActiveX control without using any constituent controls.
These are the so-called owner-drawn ActiveX controls.
You should also keep this in mind when
working with ActiveX controls: You're used to distinguishing between two distinct
types of people interacting with your program-the developer and the user. To
better understand how ActiveX controls behave, you need to take another role
into account, the author of the control itself. The author's job is to
prepare a control that will be used by the developer to deliver an application
to the user. As you'll see, the author's and developer's perspectives are sometimes
different, even though the two roles might be occupied by the same person. (That
is, you might act as the author of the control and then as the developer who
uses it.)
Creating the UserControl
Module
In this section, I'll show you how to
create a sort of super-TextBox control that adds extra capabilities to the regular
TextBox control, such as filtering out invalid characters. The steps that you
have to take any time you create a new Public ActiveX control are the following
ones:
-
Add a new ActiveX control project to
the environment. This new project already includes a UserControl module. (Alternatively,
manually add a UserControl module from the Project menu if you're creating
a Private ActiveX control.)
-
Give the project a meaningful name and a description. The
former becomes the name of the control's library, and the latter is the string
that appears in the Components dialog box for all the projects that use this
control. In this example, we'll use the project's name SuperTB and the
description An enhanced TextBox control.
-
Click on the UserControl designer's window to give it the
focus, and then enter a value for the Name property of the control in
the Properties window. In this example, you can enter SuperTextBox.
- Place one or more constituent controls on the surface of the UserControl
designer. In this example, you need to add a Label control and a TextBox control,
as shown in Figure 17-1.
Figure 17-1.
The SuperTextBox control at design time.
You can use any intrinsic
control as a constituent control of an ActiveX control except the OLE Container
control (whose Toolbox icon is disabled when an ActiveX control designer has
the focus). You can also use external ActiveX controls as constituent controls,
but if you use one you should ascertain that you have the legal right to encapsulate
it in your own control. All the ActiveX controls in the Visual Basic package
except DBGrid can be freely reused in your own ActiveX control. Always carefully
read the license agreements for third-party controls before encapsulating any
in your own controls. You'll find more advice about these matters in the "Licensing"
section near the end of this chapter. Finally, you can create ActiveX controls
that don't use constituent controls, such as the SuperLabel control that you
can find on the companion CD in the same directory as the SuperText project.
Now you can close the UserControl
designer's window and switch to the Standard EXE project that you are using as
a test client program. You'll notice that a new icon is now active in the Toolbox.
Select it, and drop an instance of your brand new control on the form, as shown
in Figure 17-2.
Congratulations! You've
just created your first ActiveX control.
I want to draw your attention
to one specific point in the previous description. You need to explicitly close
the ActiveX control designer window before using the control on the test container
form. If you omit this step, the icon in the Toolbox stays inactive. In fact,
Visual Basic activates the ActiveX control and prepares it for siting only
when you close the designer window. Siting refers to the instant an ActiveX
control is placed on its container's surface.
You need to keep in mind
that you have to deal with two different instances of the control, the design-time
instance and the run-time instance. Unlike other Visual Basic modules, a UserControl
module must be active even when the test project is in design mode. This is necessary
because the control must react to the programmer's actions, such as entering
the value of a property in the Properties window or resizing the control on the
parent form. When you're working with the ActiveX control designer open, however,
the control itself is in design mode and therefore can't be used in a form. To
run an ActiveX control, you need to close its designer window, as I explained
earlier.
Figure 17-2.
An instance of the SuperTextBox control on a testform. The Properties window
includes a number of properties that have been defined for you by Visual Basic.
Running the
ActiveX Control Interface Wizard
Our first version of the
SuperTextBox control doesn't do anything useful yet, but you can run the client
application and ensure that everything is working and that no error is raised.
To turn this first prototype into a useful control, you need to add properties
and methods and write the code that correctly implements the new features.
To complete the SuperTextBox
control, you need to add all the properties that the user of this control expects
to find, such as ForeColor, Text, and SelStart. A few of
these properties must appear in the Properties window; others are run time_only
properties. You also need to add other properties and methods that expand the
basic TextBox functionality-for example the FormatMask property (which
affects how the control's contents is formatted) or the Copy method (which
copies the control's contents to the Clipboard).
In most cases, these properties
and methods map directly to properties and methods of constituent controls: for
example, the ForeColor and the Text properties map directly to
the Text1 constituent control's properties with the same names, whereas the Caption
property corresponds to the Caption property of the Label1 constituent
control. This is similar to the concept of inheritance by delegation that you
saw in Chapter 7.
To facilitate the task of
creating the public interface of an ActiveX control and writing all the delegation
code, Visual Basic includes the ActiveX Control Interface Wizard. This add-in
is installed with the Visual Basic package, but you might need to explicitly
load it from within the Add-In Manager dialog box.
In the first step of the
wizard, you select the interface members, as shown in Figure 17-3. The wizard
lists the properties, methods, and events that are exposed by the constituent
controls and lets you select which ones should be made available to the outside.
In this case, accept all those that are already in the rightmost list except
BackStyle, and then add the following items: Alignment, Caption,
Change, hWnd, Locked, MaxLength, MouseIcon,
MousePointer, PasswordChar, SelLength, SelStart,
SelText, Text, plus all the OLExxxx properties, methods,
and events. These members ensure that the SuperTextBox control matches nearly
all the capabilities of a regular TextBox control. A few properties have been
left out-namely, MultiLine and ScrollBars. The reason for these
exclusions will be clear later.
Figure 17-3.
The first step of the ActiveX Control Interface Wizard. You
can also highlight multiple items and add all of them in one operation.
|
Note
Unfortunately, the ActiveX Control Interface Wizard lets you include many
properties, methods, and events that you should never add to the public interface
of your controls-for example, the ToolTipText, CausesValidation,
WhatsThisHelpID,and Validate event. As a matter of fact,
Visual Basic automatically adds these members to any ActiveX control that
you create, so you don't need to specify them unless you plan to use the control
in environments other than Visual Basic. More on this later.
|
In the next step, you define all the custom properties, methods,
and events that your ActiveX control exposes. You should add the FormatMask,
FormattedText, CaptionFont, CaptionForeColor,and
CaptionBackColor properties; the Copy, Clear, Cut,
and Paste methods; and the SelChange event.
In the third step, you define
how the public members of the ActiveX control are mapped to the members of its
constituent controls. For example, the Alignment public property should
be mapped to the Text1constituent control's Alignment property.
The same holds true for the majority of the members in the list, and you can
speed up mapping operations by selecting all of members and assigning them to
the Text1control, as shown in Figure 17-4.
Figure 17-4.
In the third step in the ActiveX Control Interface Wizard,
you canmap multiple members by highlighting them in the leftmost list and then
selectinga constituent control in the Control combo box on the right.
A few members-for example,
the Caption property-map to the Label1 constituent control. You must specify
the name of the original member in the constituent control when the two names
differ, as in the case of the CaptionForeColor, CaptionBackColor,
and CaptionFont properties that correspond to the Label1's ForeColor,
BackColor,and Font properties, respectively. At other times,
you have to map a public member to the UserControl itself-for example, the Refresh
method.
There might be members that
can't be directly mapped to any constituent control, and in the fourth step of
the wizard you define how such members behave. For example, you declare that
the Copy, Cut, Clear, and Paste methods are Subs
by setting their return type to Empty. Similarly, you specify that FormatMask
is a String property that can be read and modified either at design time
or run time, whereas the FormattedText isn't available at design time
and is read-only at run time. You should also specify an empty string as the
default value for these three properties because even if you change the property
type to String, the Wizard doesn't automatically change the value 0 that
it initially set as the default. You must enter the argument list for all methods
and events, as well as a brief description for each member, as shown in Figure
17-5.
The otherwise excellent ActiveX Control Interface Wizard has
some limitations, though. For example, you can neither define properties with
arguments, nor can you enter a description for all the custom properties-the
CaptionFont and CaptionForeColor properties in this case-that are
mapped to constituent controls.
|
Caution
Beware, international programmers! Being written in Visual Basic, the ActiveX
Control Interface Wizard inherits a curious bug from the language if the Regional
Setting established in the Control Panel isn't English. When Boolean constants
True and False are concatenated in a string, the value you obtain is the localized
string corresponding to that value. (For example, in Italian you get the strings
"Vero" and "Falso", respectively.) Thus, in these circumstances
the Wizard doesn't produce correct Visual Basic code, and you might have to
edit it manually to run it. Or, if you prefer, you can set the Regional Setting
to English if you plan to run the Wizard often in a programming session.
|
Figure 17-5.
In the fourth step
in the ActiveX Control Interface Wizard, you decide the syntax of methods and
events and whether properties are read/write or read-only at run time.
You're finally ready to
click on the Finish button and generate all the code for the SuperTextBox control.
If you go back to the instance of the control on the test form, you'll notice
that the control has been grayed. This happens each time you change the public
interface of the control. You can make the ActiveX control active again by right-clicking
on its parent form and selecting the Update UserControls menu command.