A Complete Scriptable ActiveX Web Control Tutorial Using ATL

Introduction

ActiveX control is a term used to denote reusable software components that are based on the Microsoft Component Object Model (COM) that allows the developer to create objects or controls that can be used to “activate” content on the World Wide Web.

I have read lots of stuff over the Internet, but I have not found any complete guideline or example through which process I can build an ActiveX Control for the web using ATL with VC++ 6.0. I wrote this article because I couldn’t find a unified description of this process anywhere on the web and also from my own hurdles. I am going to present you a complete example with the necessary details. I hope this will help you to understand how you can build a scriptable ActiveX control for the web, using ATL. Also, you will get a clear vision about ActiveX security details. It’s written with as much detail as possible, but with the assumption that the reader basically knows his stuff.

In this article, I have tried to present an example of a Scriptable ActiveX Web Control using ATL; it will display a Label Control with the current Date and time on your Internet Explorer browser window. Also, you will be guided step by step through creating the control using Microsoft VC++ 6.0 as safe for the web.

Safety and Security

The security concerns associated with an ActiveX control are mainly due to the fact that ActiveX controls can do almost anything that a normal application can do. Therefore, both malware and useful ActiveX controls exist; thus, the threat level of an ActiveX control can be associated with how trusted its author is.

However, there is one famous case of an ActiveX control’s safety concern: Internet Explorer. Internet Explorer has the ability to run ActiveX controls within a web page. This is both a blessing and a pain.

ActiveX controls, such as Adobe Reader, Adobe Flash Player, Apple QuickTime Player, Microsoft Windows Media Player, Real Networks RealPlayer, and Sun Java Virtual Machine are routinely used by Internet surfers every hour of the day all across the globe.

However, opening a web page that contains a harmful ActiveX control, and then allowing Internet Explorer to run that harmful control, would be same as running malware on the computer. Fortunately, Internet Explorer 6 and Windows Vista have taken actions to reduce such risks.

Requirements for Scriptable ActiveX Controls

Microsoft has published a document that describes all aspects of component object safety with regard to scripting ActiveX controls.

Before registering your control as safe for scripting, you must ensure that your control does not take any actions that may be unsafe when used by a scripting client. Unsafe actions include exposing information normally kept private, such as passwords and other sensitive information, executing files, and making dangerous system calls.

Another type of object safety concerns the use of parameters and properties with the control. When used with a scripting client, a safe control must ensure that the control can continue to function with any possible combination of properties defined by the user.

Designing a Scriptable ActiveX Control

A scriptable ActiveX control is a control that is constructed so that it is appropriate for use by scripting clients. Scriptable controls are designed to be safe when used in a Web browser, such as Internet Explorer, or by scripts written for the Windows Scripting Host (WSH). Scriptable controls also support mechanisms to simplify passing parameters to the control via a scripting language.

By default, ActiveX controls are not considered safe for scriptable clients. If you have an ActiveX control that could be useful to scripting clients, taking a few simple steps can expand the usefulness of your control. If you’re using ATL, these changes typically take just a few minutes.

To be scriptable, an ActiveX control must meet the following requirements:

  • Be safe when executed by an arbitrary scripting client.
  • Be registered as “Safe for Scripting.”
  • Support the IPersistPropertyBag interface. This is technically not a requirement, but it simplifies the task of passing parameters to the control.

Creating a Scriptable ActiveX Control

To create a Scriptable ActiveX control, use Microsoft Visual C++ 6.0 to perform the following steps:

  1. File->New->Projects.
  2. In the New Project dialog, as shown in Figure 1, select “ATL COM AppWizard”.
  3. Figure 1: New Project Dialog

  4. Name the project ScriptableActiveX; for Location, enter the working folder for the project’s source code, and then click the OK button.
  5. You will see a screen, as shown in Figure 2, that gives you several choices. The first choice is “Server Type.” You are building a Server DLL, so make sure that the Server Type is set to “Dynamic Link Library.”
  6. Figure 2: ATL COM AppWizard

  7. The other three checkboxes below do not concern you for this particular project, so you can ignore them. Press the finish button to have the Wizard generate the appropriate files for you.
  8. A “New Project Information” window, as shown in Figure 3, will appear to tell you what files are going to be created. Press the Ok button to accept this.
  9. Figure 3: New Project Information

Creating a New ATL Object

  1. From the Insert menu, select “New ATL Object” menu item. The “ATL Object Wizard” window, as shown in Figure 4, will appear.
  2. Figure 4: ATL Object Wizard

  3. Select Controls from the wizard’s Category list box, and then select Full Control as the control type. Click Next to begin adding a ScriptableLabel control to the project.
  4. The “ATL Object Wizard Properties” dialog, as shown in Figure 5, will appear so that you can define your control’s properties. For full controls, such as ScriptableLabel, the dialog box offers four tabs.
  5. Figure 5: ATL Object Wizard Properties

  6. All component types present a Names property page that contains naming attributes for ATL components. You only need to fill in the Short Name property for ScriptableLabel and the other fields are filled in automatically.
  7. The second tab, as shown in Figure 6, for most component types is the Attributes property page, which is used to collect information about the component. All these values are the default options, except “Support Connection Points” properties for the component. Connection points are used to supply events to a control’s container.
  8. Figure 6: ATL Object Wizard Properties (Attributes)

  9. The third tab, as shown in Figure 7, is the Miscellaneous tab. It contains attributes specific to ActiveX controls.
  10. Figure 7: ATL Object Wizard Properties (Miscellaneous)

  11. The final tab, as shown in Figure 8, in the dialog box is Stock Properties. It contains a list of all stock properties that can be implemented by an ActiveX control.
  12. Figure 8: ATL Object Wizard Properties (Stock Properties)

  13. The ScriptableLabel control uses the following stock properties:
    • Background Color
    • Caption
    • Font
    • Foreground Color

After you select the stock properties listed here, click OK to close the dialog box. The ATL New Object Wizard then generates the necessary code and adds it to your project.

Modify Control Attributes

The default handler for OnCreate will superclass a default instance of the Windows CStatic class. Apply the following window styles changes to the OnCreate() member function to the ScriptableLabel control:

m_ctlStatic.Create( m_hWnd,
                    rc,
                    _T("Static"),
                    WS_CHILD|WM_PAINT);

Retrieving Ambient Properties

When the control is loaded initially, it collects the current foreground color, background color, and font from its container. A good time to collect ambient properties is when the control and its container negotiate the client site. Add the following source code to the ScriptableLabel.cpp source file. This function overrides the base class implementation of SetClientSite() and stores the ambient values of these three properties.

STDMETHODIMP CScriptableLabel::SetClientSite(LPOLECLIENTSITE pSite)
{
   HRESULT hr = CComControlBase::IOleObject_SetClientSite(pSite);
   if(!m_pFont && pSite)
   {
      hr = GetAmbientFontDisp(&m_pFont);
   }
   GetAmbientBackColor(m_clrBackColor);
   GetAmbientForeColor(m_clrForeColor);
   return hr;
}

Add the following member function declaration to the CScriptableLabel class:

STDMETHOD(SetClientSite)(LPOLECLIENTSITE pSite);

Drawing the Control

The OnDraw() function is called by the ATL framework, passing in a structure that contains various bits of information needed to actually paint information on the screen. This implementation isn’t much more complicated than it would be if you were simply displaying the current date and time. Add the following drawing code for the control to the ScriptableLabel.h header file.

void DrawString( HDC hdc, RECT* rc, BSTR caption )
{
   USES_CONVERSION;
   TCHAR* pCaption = OLE2T(caption);

   DrawText( hdc,
             pCaption,
             lstrlen( pCaption ),
             rc,
             DT_WORDBREAK );
}

HRESULT OnDraw(ATL_DRAWINFO& di)
{
   RECT& rc  = *(RECT*)di.prcBounds;
   HDC   hdc = di.hdcDraw;

   COLORREF clrFore, clrBack;
   OleTranslateColor(m_clrForeColor, NULL, &clrFore);
   OleTranslateColor(m_clrBackColor, NULL, &clrBack);
   SetTextColor(hdc, m_clrForeColor);
   HBRUSH hbrBtn = CreateSolidBrush(m_clrBackColor);

   FillRect(hdc, &rc, hbrBtn);
   DrawString(hdc, &rc, m_bstrCaption);

   DeleteObject(hbrBtn);
   return 0;
}

Implementing IPersistPropertyBag

To simplify the use of ScriptableLabel in a scripting client, such as Internet Explorer, the control must support the IPersistPropertyBag interface. The ATL class library includes a class, IPersistPropertyBagImpl, that provides a default implementation of IPersistPropertyBag that is sufficient in most cases.

  1. Add the following line to your class derivation list:
  2. public IPersistPropertyBagImpl<CScriptableLabel>
  3. Add the following line to your COM_MAP:
  4. COM_INTERFACE_ENTRY(IPersistPropertyBag)

Marking the Control as Safe for Scriptable Clients

You easily can add support for marking the Control as Safe for Scriptable Clients by implementing the IObjectSafety interfaces. This is done by deriving your control from the default ATL implementation, IObjectSafetyImpl.

You can use two methods to mark a control as safe for scripting clients:

  • Make appropriate entries directly in the System Registry.
  • Implement the IObjectSafety interface.

Microsoft recommends that you use new controls to implement the IObjectSafety interface instead of making Registry entries. IObjectSafety enables the control to apply much finer-grained safety policies than possible when using the Registry.

ATL provides a default implementation of IObjectSafety that you easily can take advantage of by deriving your class from the IObjectSafetyImpl class.

  1. Add the following line to your class derivation list:
  2. public IObjectSafetyImpl<CScriptableLabel,
                            INTERFACESAFE_FOR_UNTRUSTED_CALLER |
                            INTERFACESAFE_FOR_UNTRUSTED_DATA>
    
  3. Two template arguments are passed to IObjectSafetyImpl:
    • The name of the class deriving from IObjectSafetyImpl.
    • The type of safety to be applied to the control.

    Two values may be passed for the safety options:

    • INTERFACESAFE_FOR_UNTRUSTED_CALLER specifies that your control can be used safely by a scripting client and does not violate any of Microsoft’s security or safety guidelines.
    • INTERFACESAFE_FOR_UNTRUSTED_DATA specifies that your control will work (or at least degrade gracefully) in the presence of any possible set of par
  4. Add the following lines to your COM_MAP:
  5. COM_INTERFACE_ENTRY(IObjectSafety)

Compiling the Scriptable ActiveX Control

Compile the ScriptableActiveX project. The compiler will register your new DLL in the Registry so that other programs can use it. You can test the control in a variety of control containers, including Visual Basic and Visual C++. You will find lots of examples using Visual Basic and Visual C++. Even better, consider a web control.

Because the ScriptableLabel control is scriptable, you also can use the control on an HTML page with Internet Explorer. Try it out.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read