No Comments


Silverlight ActiveX Control


COM/ActiveX control has been around for more than a decade. In spite of all, it is very difficult to get a complete Windowless container. MFC dialog has its own Windowless container that is truly windowless compare to ATL but if your project can't afford to depend on MFC, you are on your own. The container I am presenting in this article offers complete support to Windowsless controls. It is developed especially for ATL/WTL project and can be used to create composite controls. That means, you can combine multiple Windowless Controls to create your own component.
Imagine being able to encapsulate Adobe Flash, Windows Media Player and Silverlight into your own component. Another advantage you will find with these classes is that the learning curve is quasi zero if you have any previous experiences with ATL. You simply derive your dialog from the new dialog class to get the full power of this container.


Having a full-blown windowless container can be very useful. I hope that you will find some great uses for it. I will describe the process necessary to integrate the container in your own project. Later, in other articles, we'll explore how we can take some of this to a new level.

Think about this, wouldn't be great if you could integrate Silverlight and Flash contents seamslessly and interact with them within your C++ application?
The more you think about it, this is quite possible after all that's what a web browser does in a large part. But before we go too deep, let's do a quick refresh about ActiveX control container and see how powerful the whole concept was and is, even today. If you are already comfortable with ActiveX and Windowless or don't need a memory refresh, you can jump directly to Using ActiveXContainerImpl Class

ActiveX Control Container

If you want to be proficient at developing Windowless controls and their container, you have to rely on the OC96 Specification. Basically, you need to know and understand several things.

Apartment-Model Awareness
ActiveX Controls should be developed to conform to apartment-model rules to ensure they behave correctly. That is, you have to think in term of UI thread and make sure that your object is thread safe. If your object uses global variables, it should synchronize access to them.

By supporting the windowless control specification, a control can make efficient use of its container's window rather than having a window of its own. This results in using fewer system resources and improves performance through faster activation/deactivation. Providing windowless support not only provides transparency for interesting visual effects, but also further improves the performance of the control.

Hit Detection
Hit detection is provided so that a windowless control can have an irregular shape and to complete the visual benefits of transparency. The container calls IViewObjectEx::QueryHitPoint of the control. In return, the control detemines if it has been hit and returns an indication to the container.

Control Persistent Data
A control can use any of IPersistStreamInit, IPersistStorage, IPersistMemory, and IPersistPropertyBag as a Persistent Embedding mechanism. A control may implement more than one of these interfaces if it wants to. The container being presented with this article supports only IPersistStreamInit but IPersistPropertyBag may be added in the future in order to support a wider range of controls.

Interacting with Container
Because the container interface is passed to the control, the entire object model of the container is available and can be manipulated by the control. Consider for example this same scenario with Internet Explorer, a control access the entire DOM tree (IHTMLDocument) and change background color of the document.
    CComPtr<IOleContainer> spContainer; 
    CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> spDoc(spContainer); 
    if (spDoc)
What this means is if you develop a custom container or composite control, any control that is hosted into your dialog surface can get access to the methods and properties that your object model supports.
The following diagram shows the main interfaces that come into play.
ActiveX Container Object Model
Basically, to host an ActiveX component the container must:
  • Call the object SetClientSite to inform the object of its display location, called a "Client Site";
  • Initialize the object properties; It uses IPersistStreamInit, IPersistPropertyBag for this purpose;
  • Call the object SetAdvise method in order to be notified of compound document events;
  • Then, call the object DoVerb method with OLEIVERB_INPLACEACTIVATE to activate the object;
The object then proceeds by:
  • Negotiating its activation by calling CanWindowlessActivate to find out if it can be activated "windowlessly"; if not possible, the control creates its own window;
  • Then, it calls OnInPlaceActivateEx but uses the activate flag to indicate whether it wants windowless activation;
  • Windowless object also calls GetWindowContext to find its position within the container;
  • Finally, the control calls the container ShowObject; This indicates to the container that the control is ready to be shown;
The container is also responsible to managing input focus, mouse capture and associating moniker for the object. The container dispatches mouse and keyboard messages to the windowless control by calling the OnWindowMessage method of the IOleInPlaceObjectWindowless interface. That way, the control may respond to regular inputs when it has focus. This is about all there is to it but the ActiveXContainerImpl class makes this process really transparent. Now, let's see some of it in action.

Using ActiveXContainerImpl Class

ActiveXContainerImpl class supports the following features:
  • Hosting both Windowless and window controls
  • Hosting multiple ActiveX controls in one container
  • Restrict mouse or keyboard input for individual controls (window or windowless)
  • Change control Z-Order (controls can be sent to: back, top, top-most)
  • Supports data moniker (controls are allowed to load data via the http://, file:///, res://)
  • Transparency Support (governed by Z-order position)
  • Rendering Windowless controls to memory DC or printer (not screen screen)
Hosting ActiveX controls inside of a dialog is basically the same as you did with ATL. You can safely rename your base class from CAxDialogImpl to CAxWindowlessHost. This class inherits from CDialogImplBaseT, thus, will have the same capabilities as any Windows dialog.
    class CMainDlg : public CAxWindowlessHost<CMainDlg>
        enum { IDD = IDD_MAINDLG };


        LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
        LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
        LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
        LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
Let's get this started with some examples. The examples below assume that the controls are inserted using 'Insert ActiveX Control' from the dialog editor. You still have the flexibility to create everything manually at runtime.

Hosting Microsoft Windows Media Player

Windows Media Player supports windowless activation. Assuming you inserted a media player onto your dialog. The example below shows how you can turn it to windowless mode. Note that in the case of Windows Media Player, a custom property dialog is also available so you can configure your control at design time.
        HRESULT hr;
        ActiveXSite* pSite;
        pSite = CAxWindowlessHost<CMainDlg>::GetControlSite(IDC_WMP11);
        if ( pSite != NULL )
            pSite->SetAllowResize(false); // turn-off resize or media will resize itself to match its content
            CComQIPtr<IWMPCore> wmp = pSite->ActiveXControl();
            CComQIPtr<IWMPPlayer4> wmp4 = pSite->ActiveXControl();
            if ( wmp4 ) {
                hr = wmp4->put_windowlessVideo( VARIANT_TRUE );
                hr = wmp4->put_uiMode( CComBSTR("Full") );
            hr = wmp->put_URL( CComBSTR("enter resource URL") );
Windows Media Control

Hosting Adobe Flash Player

You can also host Flash content. Flash animations can be loaded for external file resources or retreived from the internet. For example, you can add support for YouTube video provided that you specify correctly the URL of the resources. The example below shows how to initialize Adobe Flash player to host an animation or video.
        HRESULT hr;
        ActiveXSite* pSite;
        pSite = CAxWindowlessHost<CMainDlg>::GetControlSite(IDC_SHOCKWAVEFLASH);
        if ( pSite != NULL )
            CComQIPtr<IShockwaveFlash> spFlash = pSite->ActiveXControl();
            hr = spFlash->put_WMode( CComBSTR("Transparent") );
            hr = spFlash->put_Movie( CComBSTR("enter resource URL") );
Flash Control
Setting Transparent mode is necessary to turn Adobe Flash to Windowless mode.

Hosting Microsoft Silverlight

XAML and Silverlight application package (.xap) can be hosted using Microsoft Silverlight ActiveX control. For security reasons, you can only load data from file:/// or http:// moniker. It would have been nice to support the resource protocol (res://). The example below shows how to configure Silverlight to load external resources.
        HRESULT hr;
        ActiveXSite* pSite;
        pSite = CAxWindowlessHost<CMainDlg>::GetControlSite(IDC_AGCONTROL1);
        if ( pSite != NULL )
            CComBSTR bstrUrl("enter resource URL");
            CComQIPtr<IXcpControl2> slight = pSite->ActiveXControl();
            hr = slight->put_Source(bstrUrl);
In this example, the control is prevented from receiving right clicks so the context menu is never shown. The demo shows how to use Silverlight in Windowless mode.
A huge number of demos would have to be presented if I had to consider all the ActiveX controls that we have at our disposal. Windows Form ActiveX controls can be hosted by your application as well. A demo is provided here as well.


This article presents a complete and real solution for the ATL windowless ActiveX container issue. I've described the steps necessary to integrate three popular controls in your own dialog. It is quite easy to use other ActiveX controls as well. The container may be used to develop custom composite control. Probably the most interesting part was to show how you can integrate Silverlight Application packgage (.xap,.xaml) within your solution without little effort. I hope you will consider the features that it offers and put them in use in your own program.


Introduction to ActiveX Control Containers
Silverlight COM reference
Browser Interoperability with Silverlight


02/18/2009: Initial Release
03/05/2009: Support for Silverlight in Windowless and Viewer mode
06/29/2009: Updated for Silverlight keyboard handling
05/20/2010: Updated samples and library