What is ActiveX?
Description 1: A loosely defined set of technologies developed by Microsoft for sharing information among different applications. ActiveX is an outgrowth of two other Microsoft technologies called OLE (Object Linking and Embedding) and COM (Component Object Model). ActiveX can be very confusing because it applies to a whole set of COM-based technologies. Most people, however, think only of ActiveX controls, which represent a specific way of implementing ActiveX technologies.
ActiveX controls are among the many types of components that use COM technologies to provide inter-operability with other types of COM components and services. ActiveX controls are the third version of OLE controls (OCX), providing a number of enhancements specifically designed to facilitate distribution of components over high-latency networks and to provide integration of controls into Web browsers. These enhancements include features such as incremental rendering and code signing, to allow users to identify the authors of controls before allowing them to execute.
Description 2: ActiveX are the small software components which can interact with each other or with a main software. Dll files (file with .dll extension) extensions can be considered as ActiveX. If you install a software, say for example MS Office, this would also install many ActiveX objects each serves some kind of function to the main MS Office software. The one advantage is, by employing ActiveX objects, the functionality can be shared among multiple software applications. In our example, both Word and Excel applications in MS Office can use a ActiveX which helps to check Spelling and Grammar.
These types of dll files are called ActiveX dll. Also there is ActiveX exe, and the difference is ActiveX exe can run stand alone, while ActiveX dll requires a host to run. ActiveX dll would run inside a main application process, in our example MS office application. Without starting MS Office application, the related ActiveX dll cannot be started stand alone. Where as in ActiveX exe, it can be started separately, and can wait for other applications to interact.
COM and COM+ applications are good example for ActiveX objects.
If we uninstall an ActiveX (either by deleting directly or some other way - usually there won't be any direct uninstall option for an ActiveX if it is a part of another main application), the software which uses this ActiveX either will not work or a particular functionality of that software will not work.
Capturing KeyPress event
It is often a desired feature within your application to capture KeyPress within a control such as a text or combo box. The event procedure to look out for is the KeyPress event where KeyASCII is passed as an integer value. By performing a check, say a case statement, on this value you can alter the behavior of certain keys. To find out which key equates to which KeyASCII value, search the help index under ANSI to view the character set.
Changing List View column titles
It is often useful to be able to change the titles in a List View. The most inefficient way is to load up another List View. The best way is simply to access Column Headers property of the control and use the Clear Method. Add new Column Headers using the Add method. There may also be times that you wish to hide some columns. One way to do this is of course to clear the current lot of headers and reload a new set. This can be time-consuming and therefore a better method is simply to set the width of the column to 0.
It is often the case that there seems to be a bewildering array of properties for each control. It can often be very useful to click on the Custom button and go through a mini wizard setting a whole selection of properties easily. The only downside to this is that I have on one occasion lost my controls from a VB project as I was pleased to have coded Column headings but conversely highly irritated at having to go through the tiresome process of setting up my custom toolbar. You win some, you lose some.
Controlling the combo box
One of the useful features with the combo box control is the ability to limit selections to a list. In order to do this the Style property needs to be set to which is Drop down List rather than the default 0, Drop down List. This limits the possible selections to the list but if using the control and clicking outside the control the List Index value returned is -1, which results in an error. Therefore have your Click method make sure that the code is only executed if the List Index is greater than -1.
How to Subclass an ActiveX control using a Window class
A way suggested by Tom Armstrong in his FAQ is to embed an instance of the desired class within the control class. Then, assign the control's member variable
m_hWnd to the
m_hWnd variable of the embedded class. All the operations done to the embedded class will act on the control.
It is important to notice that the embedded class member
m_hWnd must be set back to NULL before the control's destruction. Otherwise, an error will be produced if the application tries to destroy the same window twice.
How do I define global objects
To create a global object, you define a class module in an ActiveX code component and set the Instancing property to be Global Multi use or Global Single Use. To use the global object, any client application can set a reference to the ActiveX code component using the Project Properties option. The properties and methods of the class are then added to the global namespace of the client application.
Standalone Debugging ActiveX Server Components
An ActiveX DLL exports a COM object and the associated methods for use by Active Server Page scripts. To debug an object, attach the Visual Studio Debugger to the Internet Information Service process (inetinfo) and access the web page with a browser to invoke the script that calls your object. (Some MFC Extension DLLs, such as the network element modules, can be called indirectly from web pages. Use the techniques in this section to debug these modules, even though they are not ActiveX DLLs).
How to develop OLE Controls
Currently, the best tool to develop OLE Controls is Visual C++ and the MFC libraries. I would imagine that other development environments (e.g., Borland's C++ compiler) would soon allow development of OLE controls. All of my experience is with VC++ and the MFC libraries and so the questions and answers are based on these tools.
Recently, as part of the ActiveX SDK, Microsoft has made available an OLE Control framework that should work with any Windows-based C++ compiler. If you don't want to use MFC or if MFC is overkill for your control, you should check this out. Eventually the ActiveX portion of this FAQ will contain details on this particular topic.
How are OLE Controls (OCXs) different from VBXs?
So, from a functionality standpoint VBXs and OLE Controls were engineered to be equivalent, but in the process the underlying architecture was drastically changed. To effectively develop OLE Controls you need to be pretty familiar with COM and OLE, although MFC can hide much of OLE's complexity. If you don't use MFC and do all of the work yourself, you’re in for quite a bit of work. At least until someone produces a tool better than MFC (which I think is just fine) for their development.
Another important difference between VBXs and OLE controls is that the OLE Control standard is an open one. The internal VBX architecture was not documented by Microsoft and so it was difficult for vendors to provide VBX support in their development tools. This is not the case with the (more open) OLE Control standard. There are quite a few tools that support the USE of OLE Controls, and this is a major benefit both to control developers and control users.
What is an extended control?
A good example of this is the actual position of a control within its container. A control is contained and has no (inherent) knowledge of where it is located on a form.
To present a consistent interface to a control user and to provide a way for a control container to modify the functionality of an embedded control, the OLE control standard describes an extended control. The container creates this extended control and then uses COM containment and aggregation to encapsulate the functionality of the original OLE control. Containment and Aggregation are COM techniques that are similar to the C++ concept of class composition. This allows a container to augment the original code by adding new properties such as Visible, Top and Name. Also, the container may choose to hide existing properties that it deems unnecessary or wishes to re-implement. Currently, the OLE control standard defines five extended properties: Name, Visible, Parent, Cancel and Default. A container may also add, remove or change methods and events using the extended control.
What are Ambient properties
The definition of ambient is "surrounding or encircling" and this precisely describes the purpose of a container's ambient properties. The OLE Control standard defines a set of ambient properties that are read-only characteristics of a control container. Ambient properties typically provide default values for properties of a control. A good example is a container's ambient font. To provide a uniform and aesthetically pleasing interface, a control should initially use the ambient font provided by the container. If the control user specifically wants a different font for a specific control it is easily changed via a property browser. BackColor, Font and DisplayName are some examples of ambient properties described by the OLE Control standard.
How do I make a property only available at run-time?
It's easy to disallow modification of your control properties when in design mode. COleControl provides two methods that are useful in this situation: AmbientUserMode and GetNotSupported. The AmbientUserMode property indicates whether the container is in design mode or run mode, and the GetNotSupported method is a shorthand way to throw and OLE Automation exception with the CTL_E_GETNOTSUPPORTED error.
Can I build a base control class and use C++ inheritance to derive other controls?
Yes, it can be done and is fairly easy. The tricky part involves setting up the MFC-based macros that are used by AppWizard and Class Wizard. When deriving from the base class you have to cut-and-paste to build the ODL file properly, use specific base-class DISPIDs, etc. All of this is explained in detail in Microsoft Knowledge Base article Q138411. An example is also provided (SHAPES2.EXE) that illustrates the techniques.
How can I provide an Align property for my control?
The container provides the Align property (and functionality). All you have to do to enable this property for your control is to set the OLEMISC_ALIGNABLE status bit and re-register the control.
How do I return an array of items from my control?
To return an array of items, you can use an OLE Automation Safe Array. There isn't room to discuss all of the features of SafeArrays here, so I'll just briefly cover how to use them in an Automation method. There is a tremendous amount of documentation that comes with VC++ that covers the various SafeArray APIs, etc.
Add a method to your control that takes a VARIANT pointer as a parameter. A variant is a generic data type that can hold values or pointers to other more specific OLE automation types. One of the data types that can be contained within a variant is a SafeArray. You can have an array of shorts, longs, BSTRs, Dates, etc. In the method you need to allocate a SAFEARRAY, allocate space for the items, and then populate the array with these values. You then need to initialize the VARIANT structure.
How do I change the actual Name value of my control (i.e., VB's Name property)?
The Name property that Visual Basic uses is the control's actual coclass name. To quickly change this exposed name, just modify your control's coclass interface name.
Why does AmbientUserMode always return TRUE?
You are probably checking its value in your control's constructor, destructor or OnSetClientSite method. The value of AmbientUserMode is always TRUE if the control hasn't yet set up an ambient IDispatch connection to its container. You won't get a valid return from the UserMode ambient in either the constructor or destructor of your control, but you can in OnSetClientSite, if you first ensure that the ambient IDispatch has been set up.
I'm a straight C-SDK programmer.
How can I trap system level messages from within my control?
I'm not sure why the WM_DEVICECHANGE message isn't getting to your control. It's probable that system messages only go to top-level application windows and so you will need to subclass a higher level window and trap the message.
First, I'm assuming that you want to do this at runtime and so this is not a design time issue because controls don't typically have HWNDs at design time. To solve your problem I would suggest that you get the HWND of your control's parent and subclass it with a CWnd-derived class that traps the WM_DEVICECHANGE message. This class will also contain a reference to your control class so that it can fire the e vent. You can easily subclass the parent with MFC's SubclassWindow method. Retrieving the HWND of your control's parent also isn't hard.
Can I create an instance of my control with Visual Basic's CreateObject function?
Visual Basic's CreateObject function creates an instance of an OLE automation server. It uses the standard COM APIs to create the instance and then query for the server's IDispatch. OLE controls are automation servers, however, they also implement a number of other OLE interfaces, and really expect to be active within a container. The primary difference between a standard automation server and an OLE control is that the control natively supports events and provides a persistence mechanism for its properties (through its container).
So, by default a control expects to have a control site containing various interfaces, but CreateObject cannot provide these. COleControl does, however, provide a way for a control to behave just as an automation controller. All you have to do is override COleControl::IsInvokeAllowed and return TRUE. This will allow you to CreateObject on your control, although you must be sure that everything will still work without any persistence support. You can check for this condition by testing the state of the m_bInitialized flag, if FALSE the control has not been initialized via the standard container persistence mechanism.
Will it hurt anything if I register a control that is already registered?
Re-registering a control shouldn't cause any problems at all. By registering a control, all you are doing is writing some keys to the system registry. Re-registering the control either initially adds, or just updates these entries.
As to your question about how to detect whether the control is already registered, yes you can. You can use the standard system registry API calls to query the registry for the specific entries that your control will write.
I want to use another OCX within an OCX I'm developing. Is it possible?
Yes. It isn't that difficult to do. First, you have to make your control a control container by enabling the ISimpleFrame interface. This is just an option in the Control Wizard. Second, you create a MFC wrapper class for the control that you want to embed. Third, if the embedded control will fire events, you will have to use a workaround described in Q147740 that allows a CWnd- derived class to handle OLE control events. Fourth, you dynamically create an instance of the control, and you're finished.
If you're serious about doing these, you should download the source for two controls developed by Bob Wilkins. He has a wonderful example, a crossword-style grid control that demonstrates all of the techniques necessary to successfully do this.
The most common problem encountered when attempting to register a control, is the absence of DLLs that the control depends on (e.g., MFC40.DLL). If you're still having problems after ensuring the right DLLs are installed.
Though ActiveX/ADO programming knowledge is not required, a core understanding of ADO is helpful when creating agendas.
As with any object-oriented language, WebLOAD only has access to the Public interfaces and properties, hence you will need know what has been made available for each object and method.
We recommend that all object instantiations are done in the InitClientfunction to have WebLOAD work optimally. However, you can create objects anywhere in an agenda except for the InitAgendafunction.
The ActiveX object must find its way to the client machine running the agenda, either via web pages with the object embedded and downloaded over HTTP, or already residing on the client.
Creating Custom Templates
Often, developers will want to build common templates for starting application development. These templates make it easy to share a common theme across applications within a corporation. Sometimes the template can pre-define the visual elements of a user interface. Other times the template may set the data access mechanism for a variety of applications.
As a starting point for application development, templates help to standardize on consistent appearance and functionality in software projects. You simply plug and play components into existing applications, while templates are the starting points for all development.
Building a template in Visual J++ is very easy. First, create a simple Form with pre-set visual attributes and pre-set data access controls. Then, save the project and exit the Visual J++ 6.0 environment.
Once the project is saved, it is almost trivial to turn it into a reusable template. In the Windows Explorer, we must simply copy the entire project directory to the Visual J++ directory in the Visual Studio installation directory. Specifically, the directory is the \VJ98\VJProjects directory. You can even build your own nested folders. For example, we can copy the entire project directory into the VJProjects\FitchAndMatherTemplates directory.
Reusing an ActiveX Control
As part of the emphasis on component-based development, Visual J++ allows developers to incorporate business logic built with other languages and tools. Developers who had previously built ActiveX or COM controls in Visual Basic, Visual C++, Delphi, or any COM aware application can easily import the components directly onto a WFC form. Visual J++ will then generate any necessary code that ties the ActiveX interfaces with the WFC interfaces, allowing seamless integration between the two. ActiveX controls can then call WFC controls, and WFC controls can then talk to the ActiveX controls.
Importing an ActiveX control involves first placing the control on the Visual J++ Toolbox. When right-clicking on the Toolbox and selecting "Customize Toolbox", a list of all ActiveX and WFC controls on the system will appear. Select the ActiveX control of choice (in the example below, we’ve selected the ActiveMovie control) and click "OK". The ActiveX control will now appear on the Toolbox.
Using Extender Classes to Enhance Components
The Windows Foundation Classes introduce the concept of Extender controls. Extender controls are used to extend the functionality of all controls on a Form to include more features. In WFC, a normal Edit control does not include support for F1 help, for example. However, an Extender control for the help system would add that functionality to the component.
In fact, one of the WFC controls available on the Toolbox is the "F1HelpProvider". This non-visual control can be dragged and dropped onto an existing WFC Form and instantly provide developers with the ability to assign help text to any other visual control on the Form. In the example below, the F1HelpProvider control is placed on the Form, and the Properties window for the Button control is changed to include two separate forms of help text.
In the same manner, developers can add tool tips using the ToolTip Extender control. Once the ToolTip non-visual control is placed on the Form, developers can enter the property sheet for any control on the Form and add support for tool tips.
How can I develop controls without MFC?
Check out the Lightweight Control Framework that is part of the ActiveX SDK. It provides MFC-like support, but without the entire overhead. It's rather sparse, so you get to work at a lower level and you *must* basically understand more of what's going on. It's rather buggy in places, but hey, it's alpha code. As to your question about how to load an OCX, the "windo w" has to support about 15 OLE interfaces. It has to be an OLE control container. Not an unsignificant implementation.