Create Your Own ActiveX Controls
With a custom control, you can add features to Visual Basic and Microsoft Office that let you control I/O cards.
Michael T. Freeman, Home Wireless Networks, Norcross, GA -- Test & Measurement World, 9/1/1998
| Microsoft Visual Basic 5.0 (VB5) lets you add custom controls that extend the language. Typical controls for engineers include charts, knobs, sliders, and temperature scales. Custom controls also give engineers access to hardware such as data-acquisition boards.
You also can add custom controls, called ActiveX controls, to any ActiveX control-compliant language such as Visual C++, Delphi, PowerBuilder, VEE, LabView, and TestPoint. (ActiveX controls were known as OLE/OCX custom controls under VB4 and were known as VBX controls under VB3.) By using ActiveX controls with Microsoft Office, you can control instruments directly from Word, Access, or Excel. ActiveX controls promote software reuse, because once you have a control, you can use it in any application. Prior to VB5, ActiveX (or OCX) control development was strictly the domain of seasoned C/C++ programmers. With VB5, you don't have to be a programmer to make use of ActiveX controls; instead, the Control Interface and Property Page wizards walk you through the steps of creating a full-featured control. Once you design the control, you simply drag it from the toolbox and drop it into your application. As you become proficient at developing controls, you'll quickly discover plenty of applications for them. Good candidates for ActiveX controls include instrument drivers, communication interfaces, unique buttons, and bit-manipulation functions. To show you the steps for creating an ActiveX control, I'll describe how you can create a control that operates a CyberResearch Model CIO-24H digital I/O card. (For details about how to program the card, see "The DIO Card," below.) The control I've developed becomes a programming shell for a driver DLL that CyberResearch supplies with the card. |
![]() |
Before you develop the ActiveX control, you'll need to create two bit-map files that serve as icons--a toolbox bit map and a design-time bit map. The toolbox bit map appears in the VB toolbox when you develop an application; the design-time bit map appears on your VB form after you add the control to that form. The design-time bit map for the DIO board appears on a VB form in the upper-left corner of Figure 1.
You can use a graphics editor such as Microsoft Paint to create your bit maps. If you'd rather not create your own bit maps, you can find a wealth of icons and graphics on the Web, many at no cost. Microsoft's ActiveX control specification restricts toolbar bit maps to 16x15 pixels and restricts design-time bit maps to 32x32 pixels.
Create the User Control
Having created the bit maps, you can start to develop your controls. To create an ActiveX control, you need either the Professional Edition or the Enterprise Edition of VB5 running on Windows 95 or NT. If you don't own a copy of VB5, you can obtain a free copy of Microsoft's VB Control Creation Edition on the Web (see "Get Information on the Web,'' below).
When you start VB5, you'll see a New Project dialog box. Select the ActiveX Control icon. VB will create a control with the name UserControl1. In the control's property window, enter the path of the design-time bit map in the Picture property field. Enter the path of your toolbar bit map in the ToolBoxBitmap property field. Set the control's InvisibleAtRunTime property to True; this will prevent VB from displaying the bit map at run-time.
Before you proceed, create a form for testing your new control as you develop it. ActiveX controls can't run by themselves; they need a form. The form becomes the control's container, which resides in a VB project. Start developing the container by creating a Standard EXE project; I called mine DIOproj.vbp (Fig. 1).
Create another new Standard EXE project called DioTest.vbp. Add a form called frmTest to the DioTest project. You can use the form to test your new control both at design time and at run time. Change the form's caption to DIO Test Form and save the project as DioTest. Then save both projects as a group project. I used the name ActiveXDIO.vbg
![]() |
| Figure 2. The ActiveX Control wizard lets you set attributes for a control's properties and methods. |
![]() |
| Figure 3. Visual Basic creates a code skeleton for each property and method |
Run Control Interface Wizard
Now that you have a form to contain your ActiveX control, you can start VB5's ActiveX Control Interface wizard from the Add-In menu. Use the wizard to add the properties and methods listed in Table 1. The wizard will generate the code you need for the variables in Table 1 and will place the code in the DIO control object. You can rerun the wizard as many times as necessary to add properties. You can add custom properties to the control and set each property's attributes. Figure 2 shows the attributes I set for the Base_Address property.
The Control Interface wizard creates a code skeleton for each control that you can use to build an application. For example, when I created the Base_Address property, VB created declarations in code. Figure 3 shows the declaration for m_Base_Address, the variable for the board's base address.
Because you can change a control's properties, VB5 needs to track those properties. VB5 tracks a control's properties through a PropertyBag. The PropertyBag contains several events, including InitProperty, ReadProperty and WriteProperty. When you place a control in a form, VB will run the code in the InitProperties routine. The event will initialize the control with default values, which you can find in the declarations section of the code.
The ReadProperties and WriteProperties events read and write property values to memory. When you save a form, WriteProperties executes, writing all properties to the form file through the PropertyBag. When the form is loaded, ReadProperties reads the controls properties from the form file through the PropertyBag.
The PropertyChanged method is also an important control attribute. You should call this method whenever a property changes to notify VB of the change. If you leave out this method, your properties neither update nor retain design-time information correctly. Run-time properties do not need to call the PropertyChanged method.
Although the wizard automatically generates a Sub, Function, and Property code shell, you still must manually set some control attributes. First, add code to the Base_Address property to handle the base address in hexadecimal form. Also, include code to prevent the user from exceeding the range value of the control property and causing a run-time error. Add the lines in Listing 1 to the Base_Address property.
| Listing 1 'Convert Base Address to hexadecimal value m_Base_Address = "&H" & Ucase (New_Base_Address) 'Set Base Address input range limits If Val (m_Base_Address) < &H200 Then m_Base_Address = "&H200" If Val (m_Base_Address) > &H3FF Then m_Base_Address = "&H3FF" |
| Listing 2 Private Sub UserControl_Resize () 'Prevent the user from resizing the control. Dim ControlWidth As Single Dim ControlHeight As Single ControlWidth = ScaleX(32, vbPixels, vbTwips) ControlHeight = ScaleY(32, vbPixels, vbTwips) Size ControlWidth, ControlHeight End Sub |
| Listing 3 Public Enum m_PortLengthEnum Half = 1 Full = 2 End Enum Public Property Let Port_Length (ByVal New_port_Length As m_PortLengthEnum) Public Property Get Port_Length () As m_PortLengthEnum |
|
|
| Figure 4. Enumerations let you define names, such as half and full, for properties. Here, half refers to the length (4 bits or 8 bits) of a port. |
Next, modify the code so all methods return a value that will tell you if a function successfully completed its tasks. Although you may not need a return value, good practice suggests you provide one. The return value is an integer that represents two possible states: 0 = Fail, and 1 = Success.
Set Design-Time Properties
At design time, you place the control on a form. Unlike user-interface controls, the DIO control is invisible at run time. When you use the DIO control at design time, you have no need to resize the control on your form. So, you should add code to the control's Resize event to prevent anyone from changing its size. The VB Size method will allow you to fix the DIO control's icon dimensions. Unfortunately, the bit map's dimensions are expressed in pixels, but the control's Size method accepts values in twips. To convert pixels to twips, add the code in Listing 2 to the control's resize event.
VB5 has a feature new to VB called enumeration, which provides a convenient way to work with sets of related constants and to associate numeric values with names. You create an enumeration by first declaring an enumeration type with the Enum statement in the Declarations section of a standard module or public class module. Next, you change the data types of the associated properties to the declared enumeration name. To see how easily you can implement enumeration, replace the integer declaration for the Port_Length property with an enumerated value. The enumeration will define 1 = Half (4-bits) and 2 =Full (8-bits).
Listing 3 shows how to use enumerations. Place this code in the declarations section. Figure 4 shows results of adding the enumerations to your project's properties. For the Port_Length property, you now have a choice between setting 1 or setting 2.
You can assign enumerations to the Port Direction (A, B, and C) properties, too. When writing your code, don't use the variables In or Input, because VB reserves those words. Instead, use InPort and OutPort.
Custom controls typically represent an About property with an ellipsis button at the top of the properties window. When you click the button, you'll see an About form that identifies the control. Creating an About form for an ActiveX control is similar to creating a typical form in VB. Start by adding a standard form that contains a command button and a text box to the DIO project. Keep your About form as simple as possible so it loads quickly and doesn't waste memory.
After creating the About form, you must develop code to display it. Add a subroutine, ShowAboutForm, to your code that displays the form. Design the form model to require a user to click on its OK button before proceeding with VB. Next, link the ShowAboutForm procedure to the control's property window by changing the control's Procedure attributes. The link will hide the ShowAboutForm method from the VB5's Property Browser or the Object Browser. You can still write code to invoke the About form, but it won't appear in the property window.
Add Run Time Code
You need to make sure the control responds properly in both the design-time and run-time modes. For example, setting the output state of a port using the control's property window in the design-time mode shouldn't cause the control to set the DIO card's output. In the run-time mode, however, the control should have access to the DIO card. The Control Interface wizard lets you set a control's properties for read/write at design time or at run time (Fig. 2), and it automatically generates code in accordance with your selection. Because the wizard doesn't know if you're at design time or at run time, you must manually enter code to tell the control when it can send commands to the DIO card.
You can use the Ambient property to tell the control if you're using it at design time or at run time. The UserMode method uses a Boolean expression that returns a True value when you're at design time and returns a False value when you're at run time. Therefore, you can add a routine to the control that lets VB5 write to the DIO card only at design time.
Add Property Page
Sometimes a property is too complex to set from the Properties window. In such cases, developers of ActiveX controls generally supply a set of tabbed property pages that give application programmers access to the control's properties. With property pages, you can change a group of related properties without having to scroll through the property window.
In my example application, you need work only with a small set of properties, and a single property page will suffice for the DIO control. If you need to group similar properties, VB5 provides the Property Page wizard, which lets you build a set of tabbed property pages from scratch.
You can reach the Property Page wizard from VB Add-In Manager. Unlike a standard form, property pages have no load event. The key event for PropertyPage objects is the SelectionChanged event. The SelectionChanged event occurs when VB5 displays a property page and when you change a control's property.
![]() |
| Figure 5. With the Property Page wizard, you can create a page that lets you more easily set attributes for properties such as address, port configuration, and I/O direction. |
The Property Page wizard creates a limited property window that is not intuitive; thus, you should modify the property sheet page to create a more useful page. Figure 5 shows how I modified the property page for use with the DIO control. I make available only those properties that any applications programmer will use.
Developing a property page is similar to developing a VB form; you place controls on the property page and add code to perform functions. Add option buttons for Port C configuration and add drop-down lists for port directions. You can add an UpDown control to change the base address, and add a text box to display the address.
While you're developing a property page, VB5 won't show you the OK, Cancel, and Apply buttons, but it will automatically provide those buttons in the PropertyPage object. You enable the Apply button by setting the Changed property to True.
Because you never know which property you or any other programmer may need to change, you must set the Changed property to True for every object on the page. Then, when you click on the OK button, click on the Apply button, or select another tab, VB5's ApplyChanges event saves your property changes.
To give the property page a professional look, you can add the DIO.bmp icon to the page. When you finish developing the page, save it and close the form. To open the properties window, click on the ellipsis button that appears on the Custom field of the properties window for the ActiveX control.
Register the Control
In the final stage of the control development, you must register the control and convert it into an OCX. Converting the control to an OCX lets multiple Windows programs share it. Simply compile the DIO project and make and register the new ActiveX control. T&MW
Michael T. Freeman is a senior test engineer at Home Wireless Networks. He holds a B.S.E.E.T. degree from DeVry Technical Institute, Woodbridge, NJ. Home Wireless, (770) 729-3000.
| Properties | |||
| Name | Description | Type | Default Value |
| Base_Address | Returns or sets the base address of the I/O card |
String | &H300 |
| Port_A_Direction | Sets the I/O direction of Port A | Integer | 1 |
| Port_B_Direction | Sets the I/O direction of Port B | Integer | 1 |
| Port_C_Direction | Sets the I/O direction of Port C | Integer | 1 |
| Port_Length | Configures Port C as either an 8-bit or 4-bit port |
Integer | 8 |
| Methods | |||
| Name | Description | Return Type | Arguments |
| Reset | Resets I/O card to power-up state | Boolean | None |
| Bit_Input | Inputs a single bit from a selected port | Integer | (ByVal Port As Integer) |
| Byte_Input | Inputs a single byte from a selected port | Integer | (ByVal Port As Integer) |
| Bit_Output | Outputs a single bit from a selected port | Integer | (ByVal Port As Integer) |
| Byte_Output | Outputs a single byte from a selected port | Integer | (ByVal Port As Integer) |
Before developing an ActiveX control for the CyberResearch Model CIO-24H digital I/O (DIO) card, you should know how the card works. The CIO-24 is compatible with the Keithley MetraByte PIO-12 I/O card.
The CIO-24 uses an Intel 82C55 programmable peripheral interface (PPI) chip, which provides the 24 digital I/O lines. The card has three separate 8-bit ports: Port A (PA), Port B (PB), and Port C (PC). You can set each port as an input port or as an output port. In addition, you can split Port C into two 4-bit ports: Port C High (PCH) and Port C Low (PCL). A control register sets the ports' directions and configurations. On power up or on reset, the DIO card sets all ports as input ports.
The card uses four sequential I/O address locations: a base address plus the next three sequential addresses. You can set the base address in the range of 200 hex to 3FF hex using an eight-position DIP switch on the card. The factory default setting is 300 hex. The locations are mapped as follows:
Base Address Port A
Base Address + 1 Port B
Base Address + 2 Port C
Base Address + 3 Control Register
To gain direct control of the card, you need the CyberResearch Universal Programming Library for Windows (CYDAS-UDR), which you can purchase from CyberResearch. The library is a DLL that work with nearly all Windows programming languages. For this application, I included the VB DLL declarations module for the I/O card as part of the ActiveX control. Remember, the control won't work without the DLL. The ActiveX control uses the following Universal Library Functions:
cbDBitIn() Input a single digital bit
cbDBitOut() Output a single digital bit
cbDConfigPort() Configure a single I/O port
cbDIn() Input a single byte
cbDOut() Output a single byte
The ActiveX control will process these low-level commands to simplify the application programming. The control won't implement any software interrupt functions. Also, the custom control operates in the background of an application and doesn't require a user interface.--Michael T. Freeman
You can download a free copy of Microsoft's Visual Basic 5.0 Control Creation Edition (VB5CCE) through the company's Visual Basic Web site: www.microsoft.com/vbasic/download/cce/.
For more information on ActiveX components, visit Microsft's ActiveX Control Web site www.microsoft.com/activex.
C/Net offers a Web site (www.activex.com) dedicated to Microsoft's ActiveX control. The site provides background information on ActiveX controls, updates for installed ActiveX components, and a library for use in Web sites or container applications.
Other ActiveX control Web sites worth visiting include:
www.activex.org
home.sprynet.com/
sprynet/rasanen/vbnet/default.htm
www.WidgetWare.com
--Michael T. Freeman





















