Click here to Skip to main content
Click here to Skip to main content

A Complete ActiveX Web Control Tutorial

By , 21 Jun 2006
 

Sample Image

Introduction

ActiveX is a Microsoft technology developed in the mid 90’s, that allows for the creation of applet-like applications that can be downloaded and run within Microsoft's Web browser. This article is intended for Visual C++ developers who are trying to learn how to develop their first ActiveX control for a web application but finding it difficult. While trying to learn this technology myself, I found much of the information available on ActiveX was either no longer available, out of date, or missing critical information, making it extremely difficult for me to create an ActiveX control necessary for my development project. This article is intended to help you get up to speed quickly with developing an ActiveX control. It will show you the basic concepts you need to know about ActiveX, such as methods, properties, and events, and how to communicate between an ActiveX control and a web page. You will learn how to implement the control for use with default security settings in Internet Explorer on Windows XP, without getting unsigned or unsafe control warning messages.

For this tutorial, we will create an ActiveX control that displays a progress bar animated GIF when the control is loaded as a way to indicate to users that the control is loading and processing information. The control will contain functionality to demonstrate how to pass information between the control and the web page. You will be guided step by step on creating the control using Microsoft Visual Studio 2005.

Creating an ActiveX Control

To create an ActiveX control, use Microsoft Visual Studio 2005 to perform the following steps:

  1. From File menu, select New, then Project.
  2. In the New Project dialog, as shown in Figure 1, under Project types, select Visual C++, MFC. Under Templates, select MFC ActiveX Control.
  3. Name the project MyActiveX; for Location, enter the working folder for the project's source code, and then click the OK button.

    Figure 1. New Project Dialog

  4. In the MFC ActiveX Control Wizard dialog, as shown in Figure 2, select Control Settings.
  5. Under Create control based on, select STATIC. We are using a static control, as we are just displaying the output from the control and not accepting input.
  6. Under Additional features, make sure Activates when visible and Flicker-free activation are checked and Has an About box dialog is not checked.

    Figure 2. MFC ActiveX Control Wizard Dialog

  7. Click the Finish button to enable the MFC ActiveX Control Wizard to create the project's source code. By default, the wizard creates the project to use MFC in a shared DLL. We need to change this since the ActiveX control will not run unless the required MFC DLLs are already installed on the system where the control is being downloaded and run. This is one of the causes of a red X displayed where an ActiveX control should be on a web page. From the Visual Studio menu, select Project, Properties. Navigate to Configuration Properties, General. Change the entry “Use of MFC” to “Use MFC in a Static Library”.
  8. The wizard has created the following three classes:
    • CMyActiveXApp – This is the ActiveX application class derived from COleControlModule. It is the base class to derive an OLE control module object that contains the member functions for initialization (InitInstance) and code cleanup (ExitInstance).
    • CMyActiveXCtrl – This is derived from the base class COleControl. This is where we will implement most of the functionality for our control.
    • CMyActiveXPropPage – This is derived from the base class COlePropertyPage. It is used to manage the property page dialog for the control. The ActiveX Control Wizard has created a default dialog to serve as a property page for the control.

Adding Support for Animated GIF

In order to implement support for displaying a progress bar animated GIF from the ActiveX control, we will use the CPictureEx class presented by Oleg Bykov in a CodeProject article. Refer to the References section for more details. First, add the source files pictureex.cpp and pictureex.h to your project, by selecting the Solution Explorer tab in VS 2005, then right click on the Header Files or Source Files in the source tree, and then Add, Existing Item to select the appropriate source file.

To add an animated GIF resource to the project, we have to work around a defect in Visual Studio 2005 (and VS 2003) that does not allow importing a GIF image file. If you try it, you will get an error reporting that the file is not a valid GIF file. You can work around this defect as follows:

  1. Copy the GIF file ProcessingProgressBar.gif to your project working folder, and rename the file to ProcessingProgressBar.gaf with a “gaf” file extension. In Resource View, right click on the resource file MyActiveX.rc, and select Add Resource. In the Add Resource dialog, press the Import button, and select the file ProcessingProgressBar.gaf. In the Custom Resource Type dialog, enter “GIF” for Resource type, and press OK. This will import the GIF image file into the project. You will find it listed under GIF in Resources. Navigate to this item, and change the control ID from the default of IDR_GIF1 to IDR_PROGRESSBAR.
  2. Now, we need to make things right with the image file. First, save the resource file MyActiveX.rc. Navigate to the project working folder, and edit this same resource file with Notepad. Navigate to the line item definition for IDR_PROGRESSBAR, and change the filename in quotes to “ProcessingProgressBar.gif”. Also, change the GIF image filename in the working folder to “ProcessingProgressBar.gif”. From Notepad, save the resource file MyActiveX.rc. Visual Studio will then report that the file myactivex.rc has been modified outside of Visual Studio, click Yes to reload the file. One more correction needs to be made. Select Solution Explorer, navigate to the item “ProcessingProgressBar.gaf”, and select it. In Properties, select Relative Path, and correct the filename to “ProcessingProgressBar.gif”.

Adding Dialog for Progress Bar Graphic

Now, we will add a dialog for the progress bar graphic.

  1. In Resource View, right click on the dialog item in the tree, and select Insert Dialog to create a default dialog.
  2. Delete the OK and Cancel buttons that are not needed, and adjust the size of the dialog to 230 x 40.
  3. Change some of the default properties of the dialog to: Border – None, Style – Child, System Menu – False, Visible – True.
  4. Change the control ID to IDD_MAINDIALOG.
  5. Insert a picture control into the dialog, by selecting the Toolbox tab on the right of Visual Studio, selecting a picture control, and clicking in the dialog. Adjust the size of the control to 200 x 20. Change the control ID to IDC_PROGRESSBAR and the Color property to White.
  6. Create a class for the dialog, by right clicking on the dialog and selecting Add Class. This results in the MFC Class Wizard dialog as shown in Figure 3. Name the class CMainDialog, with the base class CDialog. Click Finish for the wizard to create the default source files for the class.

Figure 3. MFC Class Wizard – CMainDialog

Now, we add the member variables for the classes. The member variable m_MainDialog is associated with the CMainDialog class, and m_ProgressBar is associated with the progress bar control we added to the main dialog.

  1. Add the member variable m_MainDialog to the class CMyActiveXCtrl. Select Class View, right click on CMyActiveXCtrl, and select Add, Add Variable. Enter CMainDialog for Variable type and m_MainDialog for Variable name, and then press the Finish button.
  2. Similar to the above, add a member variable m_ProgressBar to the class CMainDialog. Enter CPictureEx for Variable type, m_ProgressBar for Variable name, and enable the Control variable checkbox, and make sure IDC_PROGRESSBAR is entered for Control ID. Before clicking on the Finish button, make sure that Variable type is set to CPictureEx and not changed to CStatic.

Figure 4. Add Member Variable Wizard – m_ProgressBar

Adding Support Code

Now, we get our hands dirty with adding some code to support drawing the main dialog and the progress bar control.

  1. Select the class CMyActiveXCtrl. In the Properties sheet, select the Messages icon, then WM_CREATE. Select the listbox to the right of WM_CREATE, then <Add> OnCreate to add a method for the WM_CREATE message. The wizard will add the OnCreate method to the CMyActiveXCtrl class.
  2. Edit MyActiveXCtrl.cpp, and add the following code to the OnCreate method to create the main dialog:
    m_MainDialog.Create(IDD_MAINDIALOG, this);

    Add the following code to the OnDraw method to size the main dialog window and fill the background:

    m_MainDialog.MoveWindow(rcBounds, TRUE);
    CBrush brBackGnd(TranslateColor(AmbientBackColor()));
    pdc->FillRect(rcBounds, &brBackGnd);
  3. Select the class CMainDialog. In the Properties sheet, select the Messages icon, then WM_CREATE. Select the listbox to the right of WM_CREATE, then <Add> OnCreate to add a method for the WM_CREATE message. The wizard will add the OnCreate method to the CMainDialog class.
  4. Edit MainDialog.cpp, and add the following code to the OnCreate method to load and draw the progress bar animated GIF image:
    if (m_ProgressBar.Load(MAKEINTRESOURCE(IDR_PROGRESSBAR),_T("GIF")))
        m_ProgressBar.Draw();

Make sure the build configuration is set to the Release configuration, and build the MyActiveX ActiveX application.

Creating a Web Page for an ActiveX Control

The tool of choice for quickly creating a default web page to test your control is Microsoft’s ActiveX Control Pad. It is available for download from Microsoft.

You will also find it available for download at various other sites on the Internet. Install it and run it on the same system you are using to develop the control with Microsoft Visual Studio. To make it easier for initial testing of the application, you should make sure that the Microsoft IIS web server is installed on this same system.

When you first run the ActiveX Control Pad, it will create a default HTML web page for you. To insert an ActiveX control, right click within the <BODY> tag of the HTML source, and select Insert ActiveX Control. In the Insert ActiveX Control dialog, scroll down and select MyActiveX Control that you have created with Visual Studio, and click OK.

Figure 5. ActiveX Control Pad – Insert ActiveX Control

Two dialog boxes will be displayed in the ActiveX Control Pad, enabling you to modify the control. The Properties dialog is for modifying properties of the control, the Edit ActiveX Control dialog is for manually editing the control. You can close both of these dialogs as we can make any further changes necessary by manually editing the HTML code. You should now find an OBJECT ID tag inserted in the HTML code, similar to that shown in Figure 6. Change the size parameters of the control by changing to “WIDTH=350” and “HEIGHT=50” in the OBJECT ID tag. Save the HTML file for the web page to the file myactivex.htm in the root folder wwwroot of IIS web server.

Figure 6. ActiveX Control Pad – MyActiveX ActiveX Control

To test the ActiveX control, load the web page http://localhost/myactivex.htm with Internet Explorer. If you get any warning messages, just click OK to proceed. This should result in a progress bar animated GIF displayed within the web page. If not, or if you get a red X displayed where the ActiveX control should be, then it is most likely due to the security settings of the browser which is preventing the ActiveX control from loading and running. To correct this, modify the security settings in Internet Explorer to change all the settings that have to do with ActiveX to enabled.

Figure 7. MyActiveX Control in Internet Explorer

Next, we need to build the ActiveX control so loading it from Internet Explorer browser does not result in annoying error messages complaining that it is an unsigned or unsafe control.

Building a Signed ActiveX Control

To create a signed ActiveX control, you must purchase a Code Signing Certificate from one of the certificate providers such as Thawte, Verisign, or GeoTrust. With this service, they will verify your identity and provide you certificate files you use to sign the ActiveX application. I chose Thawte for a Code Signing Certificate, who provided two files for signing the application, mycert.spc and mykey.pvk.

To sign the ActiveX application, we package the components of the application into a CAB file, which is downloaded from the web site and the ActiveX control is installed on the system. Part of installing the ActiveX control requires registering the control. To enable that to happen, the control must be built with the OLESelfRegister value defined in the VERSIONINFO structure of the ActiveX control. Versions of Microsoft Visual Studio up to VS 2003 inserted this entry, but Visual Studio 2005 does not. To add the entry, edit the resource file myactivex.rc to add the OLESelfRegister value, as shown below:

VS_VERSION_INFO VERSIONINFO
 FILEVERSION 1,0,0,1
 PRODUCTVERSION 1,0,0,1
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x4L
 FILETYPE 0x2L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904e4"
        BEGIN
            VALUE "CompanyName", "TODO: <Company name>"
            VALUE "FileDescription", "TODO: <File description>"
            VALUE "FileVersion", "1.0.0.1"
            VALUE "InternalName", "MyActiveX.ocx"
            VALUE "LegalCopyright", 
                  "TODO: (c) <Company name>. All rights reserved."
            VALUE "OLESelfRegister", "\0"
            VALUE "OriginalFilename", "MyActiveX.ocx"
            VALUE "ProductName", "TODO: <Product name>"
            VALUE "ProductVersion", "1.0.0.1"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1252
    END
END

Before signing the application, the ActiveX control should be packaged into a CAB file. This CAB file will also contain an INF file that is used for installing your ActiveX control. To build a CAB file, you need the cabarc.exe tool available in the Microsoft Cabinet Software Development Kit. The following is an example of a simple INF file that can be used for packaging the MyActiveX control into a CAB file. For the CLSID line item, you should change the value to the same value as that in the OBJECT ID tag in the HTML web page you created earlier with the ActiveX Control Pad.

[Add.Code]
myactivex.ocx=myactivex.ocx
myactivex.inf=myactivex.inf
 
[myactivex.ocx]
file=thiscab
clsid={36299202-09EF-4ABF-ADB9-47C599DBE778}
RegisterServer=yes
FileVersion=1,0,0,0
 
[myactivex.inf]
file=thiscab

To create a CAB file, run cabarc as shown below. Important: Make sure the OCX and INF files are in same directory where you are running cabarc.exe, otherwise the CAB will not be extracted correctly after downloading from the web server. This is one of the problems that will cause a red X on the web page where the ActiveX control should be.

cabarc -s 6144 N myactivex.cab myactivex.ocx myactivex.inf

To sign the CAB file you created, you need the signcode.exe tool from Microsoft MSDN. Refer to the “Signing and Checking with Authenticode” reference at the end of this article. You use the signcode tool with the certificate files you obtained from purchasing a Coding Signing Certificate to sign the CAB file. The following is an example use of signcode to sign myactivex.cab:

signcode -n "myactivex" -i 
   http://www.myactivex.com -spc mycert.spc -v mykey.pvk -t 
   <A href="http://timestamp.verisign.com/scripts/timstamp.dll%20myactivex.cab" target=_blank>http://timestamp.verisign.com/scripts/timstamp.dll myactivex.cab</A>

In the above example, http://www.myactivex.com should be replaced with a web page that provides users further information about your signed ActiveX control.

To use the signed CAB file in your web page, first copy the myactivex.cab to a folder on your web site, then you must modify the OBJECT ID tag on your web page with a CODEBASE parameter to reference this CAB file. Refer to Figure 8 for an example. If you load this page in Internet Explorer, it should download the CAB file and install your ActiveX control with no warning about an unsigned ActiveX control.

Figure 8. ActiveX Control Pad – MyActiveX with CODEBASE

Building a Safe ActiveX Control

To make a control that will load in Internet Explorer with no unsafe control warning or error messages, you must implement code that ensures safe initialization and safe scripting for an ActiveX control. Detailed information for doing that can be found in the article “Safe Initialization and Scripting for ActiveX Controls” on Microsoft MSDN. Refer to References at the end of this article for details. I found omissions and mistakes in this article that I have corrected for presentation in this article. Basically, all that needs to be done is to add code to the DllRegisterServer and DllUnregisterServer methods. The following is a step-by-step guide for making your ActiveX control safe:

  1. Edit MyActiveX.cpp and add the following code. The value of CLSID_SafeItem should be taken from IMPLEMENT_OLECREATE_EX in the MyActiveXCtrl.cpp source file or the equivalent for your ActiveX control. It will also be the same value as the CLSID in the OBJECT ID tag on the HTML page with your ActiveX control.
    #include "comcat.h"
    #include "strsafe.h"
    #include "objsafe.h"
     
    // CLSID_SafeItem - Necessary for safe ActiveX control
    // Id taken from IMPLEMENT_OLECREATE_EX function in xxxCtrl.cpp
     
    const CATID CLSID_SafeItem =
    { 0x36299202, 0x9ef, 0x4abf,{ 0xad, 0xb9, 0x47, 0xc5, 0x99, 0xdb, 0xe7, 0x78}};
     
    // HRESULT CreateComponentCategory - Used to register ActiveX control as safe
     
    HRESULT CreateComponentCategory(CATID catid, WCHAR *catDescription)
    {
        ICatRegister *pcr = NULL ;
        HRESULT hr = S_OK ;
     
        hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
                NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
        if (FAILED(hr))
            return hr;
     
        // Make sure the HKCR\Component Categories\{..catid...}
        // key is registered.
        CATEGORYINFO catinfo;
        catinfo.catid = catid;
        catinfo.lcid = 0x0409 ; // english
        size_t len;
        // Make sure the provided description is not too long.
        // Only copy the first 127 characters if it is.
        // The second parameter of StringCchLength is the maximum
        // number of characters that may be read into catDescription.
        // There must be room for a NULL-terminator. The third parameter
        // contains the number of characters excluding the NULL-terminator.
        hr = StringCchLength(catDescription, STRSAFE_MAX_CCH, &len);
        if (SUCCEEDED(hr))
            {
            if (len>127)
              {
                len = 127;
              }
            }   
        else
            {
              // TODO: Write an error handler;
            }
        // The second parameter of StringCchCopy is 128 because you need 
        // room for a NULL-terminator.
        hr = StringCchCopy(catinfo.szDescription, len + 1, catDescription);
        // Make sure the description is null terminated.
        catinfo.szDescription[len + 1] = '\0';
     
        hr = pcr->RegisterCategories(1, &catinfo);
        pcr->Release();
     
        return hr;
    }
     
    // HRESULT RegisterCLSIDInCategory -
    //      Register your component categories information
     
    HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
    {
    // Register your component categories information.
        ICatRegister *pcr = NULL ;
        HRESULT hr = S_OK ;
        hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
                    NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
        if (SUCCEEDED(hr))
        {
           // Register this category as being "implemented" by the class.
           CATID rgcatid[1] ;
           rgcatid[0] = catid;
           hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
        }
     
        if (pcr != NULL)
            pcr->Release();
                
        return hr;
    }
     
    // HRESULT UnRegisterCLSIDInCategory - Remove entries from the registry
     
    HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
    {
        ICatRegister *pcr = NULL ;
        HRESULT hr = S_OK ;
     
        hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
                NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
        if (SUCCEEDED(hr))
        {
           // Unregister this category as being "implemented" by the class.
           CATID rgcatid[1] ;
           rgcatid[0] = catid;
           hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);
        }
     
        if (pcr != NULL)
            pcr->Release();
     
        return hr;
    }
  2. Modify the DllRegisterServer method to add the highlighted code as shown:
    STDAPI DllRegisterServer(void)
    {
        HRESULT hr;    // HResult used by Safety Functions
     
        AFX_MANAGE_STATE(_afxModuleAddrThis);
     
        if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
          return ResultFromScode(SELFREG_E_TYPELIB);
     
        if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
          return ResultFromScode(SELFREG_E_CLASS);
     
        // Mark the control as safe for initializing.
                                                 
        hr = CreateComponentCategory(CATID_SafeForInitializing, 
             L"Controls safely initializable from persistent data!");
        if (FAILED(hr))
          return hr;
     
        hr = RegisterCLSIDInCategory(CLSID_SafeItem, 
             CATID_SafeForInitializing);
        if (FAILED(hr))
            return hr;
     
        // Mark the control as safe for scripting.
     
        hr = CreateComponentCategory(CATID_SafeForScripting, 
                                     L"Controls safely  scriptable!");
        if (FAILED(hr))
            return hr;
     
        hr = RegisterCLSIDInCategory(CLSID_SafeItem, 
                            CATID_SafeForScripting);
        if (FAILED(hr))
            return hr;
     
        return NOERROR;
    }
  3. Modify the DllUnregisterServer method to add the highlighted code as shown:
    STDAPI DllUnregisterServer(void)
    {
        HRESULT hr;    // HResult used by Safety Functions
     
        AFX_MANAGE_STATE(_afxModuleAddrThis);
     
        if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
          return ResultFromScode(SELFREG_E_TYPELIB);
     
        if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
          return ResultFromScode(SELFREG_E_CLASS);
     
        // Remove entries from the registry.
     
        hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, 
                         CATID_SafeForInitializing);
        if (FAILED(hr))
          return hr;
     
        hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, 
                            CATID_SafeForScripting);
        if (FAILED(hr))
          return hr;
     
        return NOERROR;
    }

ActiveX Control Properties, Methods, and Events

Communication between an ActiveX control and a web page is done through ActiveX control properties, methods, and events. In order to demonstrate these concepts, we will create a simple web page with a form entry to enter a text string. When a Submit button is pressed, the text entered is passed to the ActiveX control through an input parameter custom property. A method of the control is called which copies this text to an output parameter custom property, and then fires an event for this text to be displayed on the web page. Simply follow these steps in Visual Studio to implement this:

  1. First, we will create the custom properties for passing text to and from the ActiveX control. In Class View, expand the element MyActiveXLib to select _DMyActiveX. Right click on _DMyActiveX, then Add, Add Property. In the Add Property Wizard dialog as shown in Figure 9, select BSTR for Property type, and enter “InputParameter” for Property name. The wizard will fill other fields automatically for you with “m_InputParameter” for Variable name and “OnInputParameterChanged” for Notification function. Click the Finish button where the wizard will automatically create the code to support this property. Do the same for Property nameOutputParameter” with the same Property type BSTR.

    Figure 9. Add Property Wizard

  2. Next, we will create a method to enable the web page to notify the control to transfer the text string input parameter to the output parameter. In Class View, expand the element MyActiveXLib to select _DMyActiveX. Right click on _DMyActiveX, then Add, Add Method. In the Add Property Wizard dialog, as shown in Figure 9, select void for Return type and enter “LoadParameter” for Method name. The wizard will automatically enter “LoadParameter” for Internal name. Click Finish where the wizard will automatically create the code to support this method.

    Figure 10. Add Method Wizard

  3. Now, we will create an event that enables the ActiveX control to notify the web page that it is completed transferring the text from the input parameter to the output parameter. Code in the web page will react to this event and respond by displaying the text in the output parameter to verify that this transfer has occurred by the ActiveX control. In Class View, right click on CMyActiveXCtrl, select Add, Add Event. In the Add Event Wizard, as shown in Figure 11, enter “ParameterLoaded” for Event name and change Internal name to “FireParameterLoaded”. Click Finish for the wizard to create the default code to support this event.

    Figure 11. Add Event Wizard

With the above, the wizard has created a majority of the code for you. We only need to add two lines of code to implement the functionality for the ActiveX control to copy the text and notify the web page code through an event. Edit the source file MyActiveXCtrl.cpp, and add the following code to the LoadParameter method.

// Copy text from the input parameter to the output parameter
m_OutputParameter = m_InputParameter;
// Fire an event to notify web page
FireParameterLoaded();

To test, use the ActiveX Control Pad to create the following HTML code:

<HTML>
<HEAD>
<TITLE>MyActiveX - Methods, Properties, and Events</TITLE>
 
<SCRIPT LANGUAGE="JavaScript">
 
function PassParameter()
{
    if (StringInput.value != " ")
    {
        MyActiveX1.InputParameter = StringInput.value;
        MyActiveX1.LoadParameter();
    }
}
</SCRIPT>
 
</HEAD>
<BODY>
<center>
MyActiveX - Methods, Properties, and Events Example
<p></p>
 
<OBJECT ID="MyActiveX1" WIDTH=350 HEIGHT=50
 CLASSID="CLSID:36299202-09EF-4ABF-ADB9-47C599DBE778">
    <PARAM NAME="_Version" VALUE="65536">
    <PARAM NAME="_ExtentX" VALUE="2646">
    <PARAM NAME="_ExtentY" VALUE="1323">
    <PARAM NAME="_StockProps" VALUE="0">
</OBJECT>
<p></p>
 
Input Parameter: <INPUT TYPE ="text" NAME="StringInput" VALUE=" ">
<p></p>
<INPUT TYPE="button" NAME="Submit" 
       VALUE="Submit" ONCLICK=PassParameter()>
 
<SCRIPT FOR=MyActiveX1 EVENT=ParameterLoaded()>
<!-- {
   window.document.write("The parameter you entered is:<br> " 
                         + MyActiveX1.OutputParameter + "  ")
-->
</SCRIPT>

</center>
</BODY>

Save this HTML code to your web server, and run it. You should see a web page with a progress bar displayed and a form entry to enter the Input Parameter text. Enter text in the field, and press Submit. This should result in a new page with “The parameter you entered is: ”, followed by the text you entered on the next line. A brief explanation of the HTML code follows.

When you press the Submit button, the JavaScript function PassParameter is invoked. This function copies text from the StringInput form field to the InputParameter property of the ActiveX control. It then calls the LoadParameter method of the control which copies the text from InputParameter to OutputParameter and calls FireParameterLoaded() to cause an ActiveX event. The following HTML code then responds to this event:

<SCRIPT FOR=MyActiveX1 EVENT=ParameterLoaded()>
<!-- {
  window.document.write("The parameter you entered is:<br> " + 
                        MyActiveX1.OutputParameter + "  ")
-->
</SCRIPT>

References:

  1. Add GIF-animation to your MFC and ATL projects with the help of CPictureEx and CPictureExWnd by Oleg Bykov, CodeProject.
  2. Packaging ActiveX Controls, Microsoft.
  3. Signing and Checking with Authenticode, Microsoft.
  4. Safe Initialization and Scripting for ActiveX Controls, Microsoft.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

David Marcionek
Web Developer
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: CAB File creationmemberabaumhof28 Apr '08 - 15:17 
Hi Martos,
 
you rock and you made my day Smile | :)
 
I had exactly the same error and was looking for a solution for days, days and days.
 
Thanks for your post.
 
Cheers
Andreas
QuestionI have a problem with ActiveX Control Pad!!membergREyaSH29 Oct '07 - 20:44 
I've refered this article.
When "MyActive X Control" inserts at ActiveX Control Pad, errors occur at PED.EXE file.
And then ActiveX Control Pad program dies.
 
And ActiveX Control Pad downloaded from this article's link.
 

 
---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!
 
Program: C:\Program Files\ActiveX Control Pad\PED.EXE
File: f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\winocc.cpp
Line: 318
 
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
 

AnswerRe: I have a problem with ActiveX Control Pad!!memberpku20091 Aug '08 - 17:41 
I have the same problem with ActiveX Control Pad!!
 
How Can I do with it?
 
今天没有时间,以后再写吧。

AnswerRe: I have a problem with ActiveX Control Pad!!memberjustdan237 Jan '09 - 6:03 
Confused | :confused: Have you tried building the Release version of the ActiveX control?
 
I've read that debug versions tend to throw this exception and require removing the assertions from the winocc.cpp file and recompiling to work around it.
 
Confused | :confused: What operating system are you using?
 
Windows Vista has problems installing the ActiveX Control Pad. Sigh | :sigh:
Windows XP works great though. Big Grin | :-D
Generalworking dir issuemembere200730 Sep '07 - 0:13 
Hi all,
 
I have an activeX project including some configuration files and license files. These files are included in the inf file and inside the cab. Whenever I call this cab from an HTML page, it looks for the config and license files on my desktop folder. Is there a working directory setting for activeX cab files?
 
Thanks in advance
QuestionProperty values get forgotten...membernanaky198227 Sep '07 - 0:48 
I put the activex control in the dialog (in vc++ 2005).
 
Everytime I set a new value to either InputParameter or OutputParameter, close the dialog, and open the dialog again, the value I introduced dissapears.
 
Basically, how can i make these properties to behave as the stock properties? (Meaning they remember when i change the values even if i close the solution and open it again)
QuestionVersionInfo and Unregister questionmembermarianguru7 Sep '07 - 20:39 
Hi,
very nice article, thanks for it. I would like to ask:
1. Is there any relation between FILEVERSION in resource file and FileVersion in .inf file. These values are different in this article.
2. I tried selfregistration as described in the article with success. But if I unregister ActiveX control manualy I found that .ocx and .inf files were not deleted from C:\windows\Downloaded Program Files. Reregistration of the control from .cab causes creation C:\windows\Downloaded Program Files\CONFLICT.1 directory with previous registration. How can I prevent this? My Idea is to remove previously installed .ocx and .inf in DllUnregisterServer. But how can I do It?
Thanks
-Marian
 

GeneralCompatibility problem with Vistamemberasdl98721 Aug '07 - 0:29 
Hi,
I tried to build the ActiveX on a XP machine and then register it on Vista
The registration is ok, but when I access it I get an "unspecified error"
Do you have any idea avout it? I even tried to build MFC statically inside my ActiveX but this didn't help
 
thanks in advance
bye
GeneralRe: Compatibility problem with VistamemberAlvin Tee15 Apr '08 - 22:27 
try to run cmd.exe as administrator, then run regsvr32 /s myactivex.ocx
GeneralOutput ParametersmemberEuthebiu16 Aug '07 - 5:01 
Hello... and let me say thank you for a great tutorial!
I have one question:
I want to return a BYTE* pointer from the ActiveX Control, how can I do that?
 
I've made this modifications:
 
//in idl file
[id(1) , helpstring("property OutputParameter1")] BYTE* OutputParameter1;
[id(2) , helpstring("property OutputParameter2")] size_t OutputParameter2;
 
//in MainDialog.cpp
void CMainDialog::GetVectors(BYTE* &array, size_t &size)
{
array = new BYTE[10];
memset(array, 1, 10);
 
size = 10;
}
 
//in MyActiveXCtrl.cpp
// Dispatch map
 
BEGIN_DISPATCH_MAP(CMyActiveXCtrl, COleControl)
DISP_PROPERTY_NOTIFY_ID(CMyActiveXCtrl, "OutputParameter1", dispidOutputParameter1, pSignatures, OnOutputParameterChanged1, VT_LPSTR)
DISP_PROPERTY_NOTIFY_ID(CMyActiveXCtrl, "OutputParameter2", dispidOutputParameter2, signaturesSize, OnOutputParameterChanged2, VT_INT)
DISP_FUNCTION_ID(CMyActiveXCtrl, "LoadParameter", dispidLoadParameter, LoadParameter, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()
 
void CMyActiveXCtrl::LoadParameter(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
m_MainDialog.GetVectors(this->array, this->size);
 
// Fire an event to notify web page
FireParameterLoaded();
}
//in MyActiveXCtrl.h
protected:
void OnOutputParameterChanged1(void);
void OnOutputParameterChanged2(void);
void LoadParameter(void);
 
BYTE* array;
size_t size;
 
When I debug in JavaScript, I get this errpr when I want to see OutputParameter1:
MyActiveX1.OutputParameter1 Variable uses an Automation type not supported in JScript and when I want to see OutputParameter2 even if the size=10, in Javascript I get 0.
 
Can you help me please? Thanks

 

 
Eusebiu

GeneralRe: Output ParametersmemberEuthebiu17 Aug '07 - 5:36 
I used the same settings for OutputParameters as in tutorial(
DISP_PROPERTY_NOTIFY_ID(CMyActiveXCtrl, "OutputParameter1", dispidOutputParameter1, pSignatures, OnOutputParameterChanged1, VT_BSTR)
 
[id(1) , helpstring("property OutputParameter1")] BYTE* OutputParameter1;
 
).
The only thing I did is that I've build the CString variabile after the BYTE* variabile:
 
//in MainDialog.cpp
void CMainDialog::GetVectors(BYTE* &array, size_t &size)
{
size = 10;
 
array = new BYTE[10];
memset(array, 65, 10);
array[size + 1] = 0;//add 0 at the end
 
}
 
void CMyActiveXCtrl::LoadParameter(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
m_MainDialog.GetVectors(this->array, this->size);
 
this->pSignatures = CString(this->array);
 
// Fire an event to notify web page
FireParameterLoaded();
}
 
In JS I get a string "AAAAAAAAAA" and this is OK!
 
Eusebiu

GeneralUrgent:: Error while accessing ActiveX control on Webmembermaheshsaru25 Jul '07 - 22:19 
Hi,
 
I am facing some problem with COM objects.
 
Let me explain you the application arch in brief:
 
My Web based application is using ActiveX control (developed in VB) that are built in a CAB file. While accessing this application all the controls downloads into C:\windows\Downloaded Program files\ folder.
This application is working fine on some computers but it is giving odd results into others computers like
1) In some computers I am not able to see controls, only white screen is appearing (“Click to activate and use this control” is appearing into popup).
2) In some computers it is giving ActiveX control can not create object.
 
Since I am opening up this application from the same source then why I am getting different results into different computers.
 
Kindly help me in this regards
 
Thanks in advance
 
Mahesh P

GeneralJava Script to host and register activeX component in internet explorermemberCommercial_ActiveX_Use13 Jul '07 - 21:38 
I have made a ActiveX control for commericial application.
I need to host the component in Internet Explorer using Java Script.
 
When the page loads for the first time, the user should be prompted with the drop down menu, when he clicks 'Install ActiveX Control' a A Security Warning dialog box should pop up with controls name on it. When he clicks to install, the component should get registered in the registry.
 
OS supported are Windows 2000, XP and Vista
IE supported are IE 6 (SP1/2) and IE7
 
Please suggest Java Script which will do this.
GeneralAccess the activeX from an external .jsmemberphilippemartin29 May '07 - 8:41 
Hi,
 
I have the following in the head section of index.html
 
*****
<OBJECT ID="MyActiveX1" CLASSID="CLSID:2E18D95D-E6A9-491B-A4A4-E043B16C6FBC"></OBJECT>
<script type="text/javascript" src="myexternal.js"> </script>
******
 

I have no problem accessing MyActiveX1 from index.html, but get an underfined error if I try to do that from myexternal.js
 
Is there a way out (ex: passing MyActiveX1 as a parameter) ?
 
Thanks,
 


 
Philippe
GeneralRe: Access the activeX from an external .jsmemberphilippemartin29 May '07 - 9:26 
Found it: had to force the load of the activeX first
 
Philippe

QuestionHow to execute a file with activeX Controlmembergoncode18 May '07 - 8:21 
Hi:
 
I'm trying to to find a way to make an online installer. I have created a setup.exe, and now what I want is to execute it through ie. Someone hinted to use an activexControl to do this, is this possible? how? how can I execute my setup.exe through an activex? Thanks.
AnswerRe: How to execute a file with activeX Controlmemberskape2123 May '07 - 13:18 
I would like to know also...don't be a jerk...someone please reply to this thread?
GeneralRunning Active Control from Flash dishmemberkinglaws16 May '07 - 6:52 
Hi,
 
Thanx for putting you article on the internet. I am newbee in programming. After following the instruction (partially) in you article my activeX control could work. By partially I mean, I did not implement the section "Building a signed ActiveX Control". But I set the OLESelfRegister value to "\0".
 
What I am trying to do now is to be able to run the "Webpage with the embbeded ActiveX control" from a flash disk on another computer. The IE browser displays "the red X".
 
My question now is how could I run the Webpage in my flash disk on any computer?
How is the will the Control register itself on a new computer?
Must I package the control in a cab file? If so, how do I access the cab file when using CODEBASE?
 
Thanks in advance
 
Lawrence

Questionhow to embed animated gif into winCE application(not MFC)?membergoolie8317 Apr '07 - 20:15 
help me pls..i wan to make sure that it can really support animated gif so that i can doing more animation on my appliaction...
QuestionHow to update the ActiveX controlmembersinesis17 Apr '07 - 5:04 
Hi,
first of all thanks for the article!
Then I have a question: I have mine activex control and, thanks to this tutorial, it works good. But what happens if, for example, after some months I find a bug and i want to update it?
I tried on my pc and I saw that, unless I explicitly delete my control from the Windows "Downloaded Program Files" folder, even if on my server the control has changed (I change the version of the control), the client still load the old control.
Any idea?
Thankx in advance!
AnswerRe: How to update the ActiveX controlmemberDavid Marcionek17 Apr '07 - 5:38 
You must update version number not only in ActiveX control built with Visual Studio, but also in INF file component of CAB file.
GeneralRe: How to update the ActiveX controlmembersinesis17 Apr '07 - 23:43 
Thank you very much for your reply.
I have updated the version number in the INF file too.
But the update it's not automatic: to update the activex control I have to right clic on the control in the "Downloaded Program Files" folder and then select "Update".
Is there a way to do this in an automatic way?
Thanks in advance!
GeneralRe: How to update the ActiveX controlmembersinesis10 Jul '07 - 6:35 
Anyone knows how to automatically update an activex control? I still have that problem.
Thanks in advance.
AnswerRe: How to update the ActiveX controlmemberM.Thay30 Jul '07 - 21:48 
Add version to the codebase of the object in the html file.
 
codebase="http://localhost/myactivex.cab#version=1,0,0,0"
 
Update the version when there is an update ie:
 
codebase="http://localhost/myactivex.cab#version=1,0,0,1"
QuestionActivex control with lib filemembersedo-talal4 Apr '07 - 9:09 
hi
how can i use Activex control call a lib file or dll file,
and how can i add this lib file to the cab file
Generalcorrect one error in you articlememberMember #189934517 Mar '07 - 0:06 
when I complie you source code in vs.2003, it works good.
but when i embed it into the web page, errors occur. The Internet Explorer shut down when it open.
Now , I corrent the code and it works well.
the original code fragement is :
 
  • Edit MainDialog.cpp, and add the following code to the
    OnCreate method to load and draw the progress bar animated GIF
    image:
    if (m_ProgressBar.Load(MAKEINTRESOURCE(IDR_PROGRESSBAR),_T("GIF")))
        m_ProgressBar.Draw();
  •  
    now , you must replace the previous code to OnInitialDialog Message.

     
    cocainy from China
    QuestionRe: correct one error in you articlememberrenwofei95125 Mar '07 - 17:34 
    When I complie the codes,I meet the same error.But I dont know how to correct it.thanks! Please send me correct codes.My email is renwofei951@hotmail.com
     
    renwofei951 from China
    GeneralRe: correct one error in you articlememberinfomaniak19 Jun '07 - 23:03 
    Thanks!!
     
    I had the same problem (on VS 2003) and I found your suggestion which solved it.
     

    GeneralCan't display the ActiveX imagemembercherylwpy22 Jan '07 - 23:35 
    Hi! It seems that I cannot display the ActiveX image successfully. The ActiveX turns grey in the color. The functions seems ok though...
    GeneralRe: Can't display the ActiveX imagememberTaeyoung Jin14 Feb '07 - 16:16 
    1. copy to c:\windows\system32 folder
    2. regsvr32 myrecording.ocx
     
    only testing. that's all.
    GeneralRe: Can't display the ActiveX imagememberterryc00717 Jul '07 - 17:05 
    hi, at the beginning , i have the same error, at last i found that i didn't make the Dailog 's visible property to TRUE ....so , the browser hid the Dialog!!!!
    haha~~~ good luck~~~Smile | :)
    QuestionHow to deploy this application to a clean PC?memberf-jyliu21 Jan '07 - 16:42 
    Hi, could anyone tell me how to make this ActiveX object run on a machine that does not have VS2005 installed? I have tried to copy some VS2005 related dlls to C:\Windows\system32, but I still cannot register server...
     
    Thanks a lot!!!
    QuestionBuild Error: Error spawning 'cmd.exe'memberYossi Malka28 Nov '06 - 3:08 
    Hi,
     
    I have a problem building MyActiveX project:
    (Just before "Creating a Web Page for an ActiveX control")
     
    After the build messages:
    - Finished generating code
    - Embedding manifest...
     
    I get an error message:
    - Project : error PRJ0003 : Error spawning 'cmd.exe'.
     
    It also happens when I compile the full demo project I downloaded.
    How can I fix the problem?

     
    Yossi Malka

    AnswerRe: Build Error: Error spawning 'cmd.exe'memberYossi Malka28 Nov '06 - 3:48 
    I found the solution in the web:
     
    Start/Programs/Microsoft Visual Studio 2005/Tools/Visual Studio Command Prompt
    type "path > C:\path.txt"
    and copy the path from the created file (C:\path.txt) to the user environment variables.
     

     
    Yossi Malka

    QuestionHow to catch events from ocx if they are fired in another thread?memberCojocaru Sergiu25 Nov '06 - 5:35 
    I have something like this in ocx code:
    void CFullTestCtrl::StartHDDScan(void)
    {
    AFX.....
    hHDDTestThread = CreateThread(NULL, 0, HDDScanThreadFunc, this, 0, NULL);
    }
     
    DWORD WINAPI HDDScanThreadFunc(LPVOID lpParam)
    {
    CFullTestCtrl *ptr2Class = (CFullTestCtrl *)lpParam;
    for(int i=0; i<10; i++)
    {
    ptr2Class -> m_HDDTestStatus = i;
    ptr2Class -> FireHDDTestStatusChanged();
    }
    return 0;
    }
     
    and in HTML:
    ...
    FullTest.StartHDDScan();
    ...
    <script FOR= FullTest EVENT=HDDTestStatusChanged()>
    {
        
         var txt=FullTest.HDDTestStatus;
        
         cell = document.getElementById("status");
         .....
    }
    </script>
     
    And explorer don't catch HDDTestStatusChanged event, ( I tried to move thread function into CFullTestCtrl as a static memmber function , the result was the same). If I move all code from thread function directly to StartHDDScan method IExplorer start to catch it... Can somebody to explain how to do it to catch events from thread function???Sniff | :^)
    AnswerRe: How to catch events from ocx if they are fired in another thread?memberse0400521 Feb '07 - 1:56 
    Hey there!
     
    I just had the same problem. There's an article where exactly that situation is being explained:
    http://support.microsoft.com/kb/157437
     
    hth!
     
    Andreas Doppelbauer, B.Sc.
    QuestionPass custom properties to HTML pagememberphazzy17 Oct '06 - 5:56 
    Hi!
    I read this article and I'm using your ideas. I want to pass to html page, not only some strings(BSTR), but some objects of my own.
    I kind of want to pass some pointers if I am allowed, but I searched and not discovered how.
    For exampe, user gives an input, based on that the activex communicates with some servers etc and want to give the user the info requested, in some kind of structure or class or something.
    Thank you!
     
    Beyond any sound, beyond any dream...lies the mistery of trance music..

    GeneralGet Post UrlmemberShutaro12 Sep '06 - 14:07 
    Hi,
    is there a method or function to use GET/POST HTTP method from activex?
    Thanks again
    Carlo
    GeneralMap Event queue not cleared after FireEvent callmemberShutaro12 Sep '06 - 14:04 
    Hi all,
    I've a problem with Event Queue in my ActiveX Control. I'have generated some method to fire events to javascript. When I call MFC FireEvent (with same eventid) several time javascript function is not called only one time per call but for the number of foregoing calls + 1. I suppose that I must clear the event queue manually but I don't have found any documentation in MSDN...
    Thanks for all suggestion
    Carlo
    QuestionMozilla Browser?memberLorenz27 Sep '06 - 0:33 

    Hi,
     
    does this ActiveX plugin approach work with Mozilla?
     
    Greetings,
     
    Lorenz
    AnswerRe: Mozilla Browser?memberArtchi12 Sep '06 - 2:32 
    It's not the right question. It should be "Does Mozilla Browser support ActiveX controls?"
    AnswerRe: Mozilla Browser?memberShutaro12 Sep '06 - 13:51 
    Hi Lorenz2,
    mozilla can support activex by "Mozilla ActiveX Project" (now is part of mozilla source tree). This is an extension/plugin for mozilla but is strongly dependent from gecko version. Otherwise to activex, Mozilla support own plugin. You can find all information that you need at:
     
    http://www.iol.ie/~locka/mozilla/mozilla.htm
    or
    http://www.mozilla.org/projects/plugins/
     
    There are some example to make simple plugins in mozilla/firefox source code at directory:
    mozilla/modules/plugin/samples
     
    Cheers Carlo
    Questioncannot convert parameter 1 from 'WCHAR *' to 'const char *'memberatik_khan30 Aug '06 - 7:30 
    Hello
     
    i am getting the folloing error with VC2003....do i miss anything?
     
    error C2664: 'StringCchLengthA' : cannot convert parameter 1 from 'WCHAR *' to 'const char *'
     
    error C2664: 'StringCchCopyA' : cannot convert parameter 1 from 'OLECHAR [128]' to 'char *'
     

     
    atik
    AnswerRe: cannot convert parameter 1 from 'WCHAR *' to 'const char *'membercodeproject66667 Sep '06 - 13:16 
    Change StringCchLength to StringCchLengthW, and StringCchCopy to StringCchCopyW. It will then compile.
    GeneralRe: cannot convert parameter 1 from 'WCHAR *' to 'const char *'memberMaruf Maniruzzaman27 May '07 - 20:15 
    Converting method name from generic to unicode is not a good idea. Setup the project to select unicode method using preprocessor is bettr.
     
    Maruf Maniruzzaman
    From Bangladesh
    Tomorrow is a blank page

    AnswerRe: cannot convert parameter 1 from 'WCHAR *' to 'const char *'memberf-jyliu21 Jan '07 - 16:48 
    Build the project with Unicode
    Generalparam values without published set methodsmemberboon31320 Aug '06 - 2:02 
    Hello! I have been scratching my head trying to figure out how to set a number of param values which have no published set methods for a third-party ActiveX control. I am trying to host this ActiveX control within my own application. I wonder if you could help.
     
    The following is part of the object tag from the web page where the third-party ActiveX control is hosted.
     
    <object style="DISPLAY:inline-block" ID="svweb" classid="clsid:B9B2EE1A-E314-4338-A305-BE845EACB112" codebase="control/cswx.cab#version=2,51,2005,715" width="100%" height="350" onreadystatechange="activeXCtrl();">
     
    <param name="size" value="0">
     
    <param name="theme" value="0">
     
    <param name="addr" value="202.9.104.201">
     
    <param name="httpaddr" value="202.9.104.201">
     
    <param name="port" value="81">
     
    <param name="session" value="3b056bb05b7fcf7d3eaeb9ecfcfdbddd59817b838a1bcb4f8f0b5d7a4be71d9c">
     
    ...
     
    </object>
    Generalthanks a lotmembervikram19798 Aug '06 - 20:05 
    the article is very well compiled. really helpful...
     
    cheers
    vikram
     
    vikram sareen

    Generalcoolmembertechno_adi3 Aug '06 - 1:45 
    Hi,
    Thats a nice explaination for activex control in .net
     
    Could you please arrange the same in c# /Vb .net and post an article..
    I am unable to find the same kind of example in other .net languages.. (specially the event handling parts etc.. which are not available on other lang.)
     
    Thanks
    GeneralThanks a lot!memberLuHuiwei27 Jul '06 - 20:28 
    It helps me a lot to create an ActiveX control and release it.
    Thank you for your work!Smile | :)

     
    LuHuiwei

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Permalink | Advertise | Privacy | Mobile
    Web03 | 2.6.130516.1 | Last Updated 21 Jun 2006
    Article Copyright 2006 by David Marcionek
    Everything else Copyright © CodeProject, 1999-2013
    Terms of Use
    Layout: fixed | fluid