Chapter 26 - Getting Started with ActiveX Controls
Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
Copyright 1998 The McGraw-Hill Companies
ActiveX Controls
ActiveX controls can be placed alongside standard controls such as radio buttons, push buttons, checkboxes, and so on. Therefore, you might find a dialog box containing a few radio buttons, checkboxes, and an ActiveX control. ActiveX controls, however, are inherently more difficult to implement.
Unless a commercial vendor has supplied an ActiveX control, you, the programmer, will be responsible for the design and complete implementation of the control and its properties. The problem is now twofold. First, during the design phase you must create, write, and compile the code that draws the control and implements all of the control’s, methods, and so on. This code eventually becomes a tiny dynamic link library (see Appendix C for more information on DLLs) with an .OCX file extension. Second, the application that is to use the ActiveX control must now interface with the control’s methods, data, and so on. You also must properly design this interface.
A properly designed ActiveX control must be independent from the application in which it is used. In other words, it must be completely reentrant. Remember that an ActiveX control is really a separate dynamic link library that is not linked to any particular application. A separate instance for data for each use of the control is required for reentrance in a DLL. The only communications allowed between an application and an ActiveX control are via messages. Hence, an ActiveX control must be defined in a dynamic link library.
Control Design Criteria
When entering the design phase for an ActiveX control, several decisions must be made to create an ActiveX control as appealing and functional as possible.
First, you must decide how the ActiveX control will be drawn and displayed. Here, some talent will be required to produce ActiveX controls that are both functional and attractive.
Next, the ActiveX control should be designed to take advantage of changes in control properties resulting from the automation interface of the control. Note that for ActiveX controls, so designed, property pages will allow the user to change properties at run time. Arguments should be assigned ActiveX controls in order to control events, set their names, and determine when they should be fired. A control’s methods should be defined in terms of arguments and return types.
Finally, the persistence of a control’s various property states must be determined and implemented.
The COleControl Class
ActiveX controls are derived from MFC’s COleControl class. Examine the code in the next listing. This listing contains an edited portion of the AFXCTL.H header file. If you are interested in examining the full header file, you should be able to locate it in the MFC’s INCLUDE subdirectory. Be warned, however, that this file is approximately 30 pages in length.
// This is part of the MFC C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product.
////////////////////////////////////////////////////////////// // AFXCTL.H - MFC OLE Control support . . . ////////////////////////////////////////////////////////////// // Stock events
Our intention in showing this partial listing was not to explain each section of the listing in detail, but to provide you with a reference as we introduce some new terms used with ActiveX controls. You’ll find several of the captions for those sections set in a bold font.
Events
Events are actions or responses that are triggered by the control’s reaction to an action on the control—for example, a keypress or mouse button click. KeyUp and KeyDown are examples of stock events.
Since your class will be derived from Microsoft’s COleControl class, it will be able to use a new map that enables messages. These messages or events are sent to the application using the control. This application is called the control container. The application or container will receive information about an event when something happens to the control. This event could be as simple as clicking the mouse within the control. Using event parameters can provide additional information. Examine the message map area of the previous listing.
A control communicates with its application (container) by firing events. ActiveX provides stock and custom events to be used by your control. See the sections marked stock events in the previous listing. Stock events are handled by the COleControl as a default. Custom events might be used to signal the application (container) when a control event occurs, such as receiving a message.
Methods and Properties
The control must expose a set of methods (functions) and properties (interface) to the application using the control in order to make an ActiveX control interactive. Methods are control functions that permit external code to alter characteristics of the control. Typical characteristics include appearance, properties, or behavior. Control properties, on the other hand, include the color, text, font, and other elements used in the control. Methods and properties form the basic mechanism whereby the application (container) communicates with the control. This communication allows the appearance and values of the control to be changed. The developer, while using Microsoft’s ClassWizard, defines methods and properties. Find the section defining stock methods in the previous listing. Stock methods are implemented automatically by the COleControl class. The programmer can add custom methods if additional custom features are needed by the control.
A primary interface to the control allows early bound access to the control’s methods and properties. Here, object methods are exposed as methods, and properties as get/set method pairs. IDispatch is used for late bound access. The application using the control (container) decides which type of binding is provided the user. IProvideClassInfo returns a CoClassTypeInfo, which describes the control.
ActiveX controls also provide extended properties, methods, and events. Usually this is control-specific information needed only by the application (container).
Persistence
Controls support persistence to streams through IPersistStream and persistence to storage through IPersistStorage. Both implementations can be found in the interface maps section of the previous listing. IPersistStorage is necessary for continued support of compound document applications (containers). IPersistStream allows embedded controls to be saved to streams, where feasible.
Persistence permits the ActiveX control to read or write property values to and from a file or stream. An application (container) can use persistence to store property values for the control. These values can then be retrieved if a new instance of the control is created.
An example, not shown in the previous listing, is the parameter PX_Blob that is used to exchange a control property that stores Binary Large Object (BLOB) data. In a similar manner, PX_Bool is used to exchanges a control property of type BOOL.