Control container supporting windowless activation

MFC has some nice Control container support embedded seamlessly into the CWnd class. ActiveX controls can be created via CreateControl just as if they were normal Windows controls. Besides, CWnd, the relevant classes are COleControlContainer, COleControlSite and COccManager (declared in mfc\src\occimpl.h)

I wanted to modify this container support so that controls supporting windowless activation are created without a window. Windowless activation (used e.g. in IE4) is a technique used to improve performance and minimize resource needs, especially when lots of controls are to be created.

The extension is implemented in principle by deriving new classes COleControlContainerEx and COleControlSiteEx providing the required OLE Interfaces and overriding some base class functions.

While most parts of this task were straightforward, there were some parts in MFC resisting simple means:

  • Some CWnd members I need to access are declared protected. MFC's container support classes are friends of CWnd and can thus access these members, but derived classes cannot.
  • None of the CreateControl functions in CWnd, COleControlContainer, and COleControlSite is virtual.
  • COleControlContainer manages the contained site in a map HWND -> COleControlSite. This required each control to have a HWND.
  • A problem with the MFC import library causes a crash when adding new interfaces to COleControlContainer and COleControlSite.

Some hacks were required to solve these problems. The classes are now working, though they should be considered experimental status and some more effort would be needed to optimize drawing, support non-rectangular controls etc. I would like to get some feedback on the implementation, especially how to get rid of those hacks. Note that creating windowless controls by dialog templates is currently not supported.

The source code (42KB) contains files OccEx.h and OccEx.cpp implementing the new classes, and a sample SDI project, where the view class creates a windowless control.

To use the extension, you will first have to register the new OCC manager in InitInstance:

	COccManagerEx g_occManager;

	BOOL CTestApp::InitInstance()
	{
		AfxEnableControlContainer(&g_occManager);
		// ...

You must also prepare the container window to contains windowless controls. Forwarding keyboard and mouse messages is done automatically by COleContainerEx (by subclassing the WNDPROC of the container window), but you will have to call COleContainerEx::OnDraw from your windows drawing code, i.e. from OnDraw in CView derived classes and OnPaint in other CWnd derived classes (does someone have an idea to handle this automatically, too?):


	void CTestView::OnDraw(CDC* pDC)
	{
		CTestDoc* pDoc = GetDocument();
		ASSERT_VALID(pDoc);
		// ...

		if (m_pCtrlCont)
			STATIC_DOWNCAST(COleControlContainerEx, m_pCtrlCont)->OnDraw(pDC);
	}

The simplest method to create a control, is to create an instance of my CWindowlessControl and call its CreateControl function. You can also use ClassWizard generated wrapper classes if you change all occurrences of CWnd to CWindowlessControl in the generated H and CPP files.



Comments

  • Doesn't work with MFC 7.0 - plz help

    Posted by Legacy on 12/13/2002 12:00am

    Originally posted by: Ren� Greiner

    "COleControlContainer/COleControlSite now supports windowless controls in MFC 7.0" *lol*
    No it doesn't !!!.

    I found this article, but it also doesn't work.

    Do you have an update version?

    Reply
  • Windowless activex controls

    Posted by Legacy on 06/20/2002 12:00am

    Originally posted by: Henry Park

    I have created an ActiveX control which adds bitmapped buttons with associated flyby( i.e. tooltips) text for the buttons. The flyby text works great in the ActiveX test container, but they do not work in IExplorer or a special dialog test container that I use. Using "Spy" to look at Window messages, etc., I see that no Tooltip messages are being processed. How do I make sure the the Window's message pump is started?

    thanks...

    p.s. I can supply code if someone is willing to look at it.

    Reply
  • Hmmmm

    Posted by Legacy on 05/18/2001 12:00am

    Originally posted by: Johannes Svensson

    It works fine, thanx for tip...
    

    Reply
  • Hack2 Removal

    Posted by Legacy on 09/09/1999 12:00am

    Originally posted by: Robert Adamson

    Regarding Hack 2
    
    

    I don't believe the BEGIN_INTERFACE_MACRO is the problem.
    Your just creating a GUID interface table here to COM class's nested classes. Since your implementing the
    earlier interfaces anyway, you should be able to use
    CCmdTarget for the second paramater.

    BEGIN_INTERFACE_MAP COleControlSiteEx,CCmdTarget /*COleControlSite*/)

    The following is some reference material.

    See TN038: MFC/OLE IUnknown Implementation.

    Note It is generally not possible to reuse the implementation of MFC's built-in implementations of the OLE interfaces by inheriting the
    embedded specialization of that interface from the MFC version. This is not possible because the use of the METHOD_PROLOGUE macro to get
    access to the containing CCmdTarget-derived object implies a fixed offset of the embedded object from the CCmdTarget-derived object. This
    means, for example, you cannot derive an embedded XMyAdviseSink from MFC's implementation in COleClientItem::XAdviseSink, because
    XAdviseSink relies on being at a specific offset from the top of the COleClientItem object.

    You can, however, delegate to the MFC implementation for all of the functions that you want MFC's default behavior. This is done in the MFC
    implementation of IOleInPlaceFrame (XOleInPlaceFrame) in the COleFrameHook class (it delegates to m_xOleInPlaceUIWindow for many
    functions). This design was chosen to reduce the runtime size of objects which implement many interfaces; it eliminates the need for a
    back-pointer (such as the way m_pParent was used in the previous section).

    Reply
  • Can't make this work with my Windowless ATL Control

    Posted by Legacy on 03/29/1999 12:00am

    Originally posted by: kokhoor

    Please help. I had written a Windowless ATL Controls and hit upon an Assertion error when I use your container.

    The Assertion occurs in your COleControlSiteEx::CreateControl function.

    This is where it occurs.
    if (dwStyle & WS_VISIBLE)
    {
    // control is visible: just activate it
    -> hr = DoVerb(OLEIVERB_INPLACEACTIVATE);
    }

    Somehow, it fails in an ASSERTION somewhere after that.

    Reply
  • Microsoft Forms2.0 Text Block failed to show caret

    Posted by Legacy on 02/25/1999 12:00am

    Originally posted by: Max Zaitsev

    Hi Klaus,

    I've already left another comment on your page.

    This one is not a bug description or tip. I had a problem in my container. MS Forms text field being windowless activated failed to show caret, while text is typed correctly. It shows the same behaviour both in your container and test container from dev studio 6, BUT IT WORKS JUST FINE in the IE4. Do you have any ideas or just any other public domain text field control, supporting windowless activation.

    Regards,
    Max Zaitsev.

    Reply
  • Good work

    Posted by Legacy on 02/18/1999 12:00am

    Originally posted by: Max Zaitsev

    Hi.

    When I had to start implementatiom of windowless activation support in the program I'm developing for my company, I was wondering why there is no any samples of container provided by Microsoft. It was impossible for me to find something anywhere, so I had to start making it from scratch.

    I liked your container. There are some interesting ideas, say to fake HWND for control container's map. Also it is good WORKING sample! Anyway, accessing protected data members by offset is not good solution. I think it would be better to create derived class and declare it to be friend of yours. Than you can cast pointer to this derived class and get access to what ever you need (not too correct, but absolutely safe about versions, alignment, etc).
    ...
    // define "access" class
    class CAccessWnd: public CWnd{
    friend class COleControlSiteEx;
    friend class COleControlContainerEx;
    };

    regards,
    Max Zaitsev

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • In support of their business continuity and disaster recovery plans, many midsized companies endeavor to avoid putting all their eggs in one basket. Understanding the critical role of last-mile connectivity and always available Internet access for their enterprises, savvy firms utilize redundant connections from multiple service providers. Despite the good intentions, their Internet connectivity risk may still be in a single basket. That is because internet service providers (ISPs) and competitive local …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds