Contents

Introduction

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 compared 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 Windowless controls. It is developed especially for ATL/WTL projects 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.

Description

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 it be great if you could integrate Silverlight and Flash contents seamlessly 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.

Windowless

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 determines 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.

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.

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 for 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.

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.

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.

Hosting Adobe Flash Player

You can also host Flash content. Flash animations can be loaded for external file resources or retrieved from the internet. For example, you can add support for YouTube video provided that you correctly specify the URL of the resources. The example below shows how to initialize Adobe Flash player to host an animation or video.

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.

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.

Conclusion

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 package (*.xap,*.xaml) within your solution with little effort. I hope you will consider the features that it offers and put them to use in your own program.

Comments and Discussions

Hi,
It's very interesting, but i want to render Silverlight files to a texture for a 3D application in order to use it as a GUI (in 3D). Something like Hikari:
http://www.ogre3d.org/tikiwiki/Hikari&structure=Libraries

I have tried to modify your code, but i can't succed. I have no knowledge about COM and ActiveX. I think i need to be able to render silverlight in memory instead of a window using OleDraw, but i don't know how.