Export (0) Print
Expand All

Hosting ActiveX Controls Using ATL AXHost 

The sample in this topic shows how to create AXHost and how to host an ActiveX control using various ATL functions. It also shows how to access the control and sink events (using IDispEventImpl) from the control that is hosted. The sample hosts the Calendar control in a main window or in a child window.

Notice the definition of the USE_METHOD symbol. You can change the value of this symbol to vary between 1 and 8. The value of the symbol determines how the control will be created:

  • For even-numbered values of USE_METHOD, the call to create the host subclasses a window and converts it into a control host. For odd-numbered values, the code creates a child window that acts as a host.

  • For values of USE_METHOD between 1 and 4, access to the control and sinking of events are accomplished in the call that also creates the host. Values between 5 and 8 query the host for interfaces and hook the sink.

Here's a summary:

USE_METHOD Host Control access and event sinking Function demonstrated

1

Child window

One step

CreateControlLicEx

2

Main window

One step

AtlAxCreateControlLicEx

3

Child window

One step

CreateControlEx

4

Main window

One step

AtlAxCreateControlEx

5

Child window

Multiple steps

CreateControlLic

6

Main window

Multiple steps

AtlAxCreateControlLic

7

Child window

Multiple steps

CreateControl

8

Main window

Multiple steps

AtlAxCreateControl

// save this code in a .cpp file, test.cpp, then compile with 
// cl test.cpp gdi32.lib
#include <atlbase.h>
#include <atlwin.h>
#include <atlhost.h>

// Value of USE_METHOD determines the function used to create the control.
#define USE_METHOD   1 // 1 to 8 are valid values

#import "PROGID:MSCAL.Calendar.7" no_namespace, raw_interfaces_only

// Child window class that will be subclassed for hosting Active X control
class CChildWindow : public CWindowImpl<CChildWindow>
{
public:
   BEGIN_MSG_MAP(CChildWindow)
   END_MSG_MAP()
};

// Helper Macro for Main Frame window class
#define DECLARE_MAINFRAME_WND_CLASS(WndClassName, style, bkgnd, menuid) \
static ATL::CWndClassInfo& GetWndClassInfo() \
{ \
   static ATL::CWndClassInfo wc = \
   { \
      { sizeof(WNDCLASSEX), style, StartWindowProc, \
        0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), menuid, WndClassName, NULL }, \
      NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
   }; \
   return wc; \
}

class CMainWindow : public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>,
   public IDispEventImpl<1, CMainWindow, &__uuidof(DCalendarEvents), &__uuidof(__MSACAL), 7, 0>
{
public :

   CChildWindow m_wndChild;

   DECLARE_MAINFRAME_WND_CLASS("MainWindow", CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, COLOR_WINDOW, 0)
   
   BEGIN_MSG_MAP(CMainWindow)
      MESSAGE_HANDLER(WM_CREATE, OnCreate)
      MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
   END_MSG_MAP()

   BEGIN_SINK_MAP(CMainWindow)
      SINK_ENTRY_EX(1, __uuidof(DCalendarEvents), 1, OnClick)
   END_SINK_MAP()

   // Helper to display events
   void DisplayNotification(TCHAR* pszMessage)
   {
      CWindow wnd;
      wnd.Attach(GetDlgItem(2));
      
      wnd.SendMessage(EM_SETSEL, (WPARAM)-1, -1);
      wnd.SendMessage(EM_REPLACESEL, 0, (LPARAM)pszMessage);
   }
   
   // Event Handler for Click
   STDMETHOD(OnClick)()
   {
      DisplayNotification(_T("OnClick\r\n"));
      return S_OK;
   }

   LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&)
   {
      _pAtlModule->Lock();

      RECT rect;
      GetClientRect(&rect);
      
      RECT rect2;
      rect2 = rect;
      
      rect2.bottom -=200;
      
      CAxWindow2 axwnd;

#if USE_METHOD | 0x2 // if USE_METHOD is a multiple of 2 then the AtlAx 
                     // version is invoked.

      // Create a child window.
      // AtlAx functions will subclass this window.
      m_wndChild.Create(m_hWnd, rect2, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 1);
      // Attach the child window to the CAxWindow so we can access the 
      // host that subclasses the child window.
      axwnd.Attach(m_wndChild);

#else

      // Create a Axhost directly as the child of the main window
      axwnd.Create(m_hWnd, rect2, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 1);

#endif

      if (axwnd.m_hWnd != NULL)
      {
         CComPtr<IUnknown> spControl;

         // The calls to (AtlAx)CreateControl(Lic)(Ex) do the following:
         // Create Calendar control. (Passing in NULL for license key. 
         //   Pass in valid license key to the Lic functions if the 
         //   control requires one.)
         // Get the IUnknown pointer for the control.
         // Sink events from the control.
         
         // The AtlAx versions subclass the hWnd that is passed in to them 
         //   to implement the host functionality.

         // The first 4 calls accomplish it in one call.
         // The last 4 calls accomplish it using multiple steps.

#if USE_METHOD == 1
         HRESULT hr = axwnd.CreateControlLicEx(
            OLESTR("MSCAL.Calendar.7"), 
            NULL, 
            NULL, 
            &spControl, 
            __uuidof(DCalendarEvents), 
            (IUnknown*)(IDispEventImpl<1, CMainWindow, &__uuidof(DCalendarEvents), &__uuidof(__MSACAL), 7, 0>*)this
         );
#endif

#if USE_METHOD == 2
         HRESULT hr = AtlAxCreateControlLicEx(
            OLESTR("MSCAL.Calendar.7"), 
            m_wndChild.m_hWnd, 
            NULL, 
            NULL, 
            &spControl, 
            __uuidof(DCalendarEvents), 
            (IUnknown*)(IDispEventImpl<1, CMainWindow, &__uuidof(DCalendarEvents), &__uuidof(__MSACAL), 7, 0>*)this, 
            NULL
         );
#endif         

#if USE_METHOD == 3
         HRESULT hr = axwnd.CreateControlEx(
            OLESTR("MSCAL.Calendar.7"), 
            NULL, 
            NULL, 
            &spControl, 
            __uuidof(DCalendarEvents), 
            (IUnknown*)(IDispEventImpl<1, CMainWindow, &__uuidof(DCalendarEvents), &__uuidof(__MSACAL), 7, 0>*)this
         );
#endif         

#if USE_METHOD == 4
         HRESULT hr = AtlAxCreateControlEx(
            OLESTR("MSCAL.Calendar.7"), 
            m_wndChild.m_hWnd, 
            NULL, 
            NULL, 
            &spControl, 
            __uuidof(DCalendarEvents), 
            (IUnknown*)(IDispEventImpl<1, CMainWindow, &__uuidof(DCalendarEvents), &__uuidof(__MSACAL), 7, 0>*)this
         );
#endif
         
      // The following calls create the control, obtain an interface to 
      // the control, and set up the sink in multiple steps.
#if USE_METHOD == 5
         HRESULT hr = axwnd.CreateControlLic(
            OLESTR("MSCAL.Calendar.7")
         );
#endif

#if USE_METHOD == 6
         HRESULT hr = AtlAxCreateControlLic(
            OLESTR("MSCAL.Calendar.7"), 
            m_wndChild.m_hWnd, 
            NULL, 
            NULL
         );
#endif         

#if USE_METHOD == 7
         HRESULT hr = axwnd.CreateControl(
            OLESTR("MSCAL.Calendar.7")
         );
#endif         

#if USE_METHOD == 8
         HRESULT hr = AtlAxCreateControl(
            OLESTR("MSCAL.Calendar.7"), 
            m_wndChild.m_hWnd , 
            NULL, 
            NULL
         );
#endif         

#if USE_METHOD > 4 // have to obtain an interface to the control and set 
                   // up the sink
         if (SUCCEEDED(hr))
         {
            hr = axwnd.QueryControl(&spControl);
            if (SUCCEEDED(hr))
            {
               // Sink events form the control
               DispEventAdvise(spControl, &__uuidof(DCalendarEvents));
            }
         }
#endif

         if (SUCCEEDED(hr))
         {
            // Use the returned IUnknown pointer.
            CComPtr<ICalendar> spCalendar;
            hr = spControl.QueryInterface(&spCalendar);
            if (SUCCEEDED(hr))
            {
               spCalendar->put_ShowDateSelectors(VARIANT_FALSE);
            }
         }
      }

      rect2 = rect;
      rect2.top = rect.bottom - 200 + 1;
      CWindow wnd;
      wnd.Create(_T("Edit"), m_hWnd, rect2, NULL, WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0, 2);
      return 0;
   }

   LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL&)
   {
      _pAtlModule->Unlock();
      return 0;
   }
};

class CHostActiveXModule : public CAtlExeModuleT<CHostActiveXModule>
{
public :

   CMainWindow m_wndMain;

   // Create the Main window
   HRESULT PreMessageLoop(int nCmdShow)
   {
      HRESULT hr = CAtlExeModuleT<CHostActiveXModule>::PreMessageLoop(nCmdShow);
      if (SUCCEEDED(hr))
      {
         AtlAxWinInit();
         hr = S_OK;
         RECT rc;
         rc.top = rc.left = 100;
         rc.bottom = rc.right = 500;
         m_wndMain.Create(NULL, rc, _T("Host Calendar") );
         m_wndMain.ShowWindow(nCmdShow);         
      }
      return hr;
   }

   // Clean up. App is exiting.
   HRESULT PostMessageLoop()
   {
      AtlAxWinTerm();
      return CAtlExeModuleT<CHostActiveXModule>::PostMessageLoop();
   }
};

CHostActiveXModule _AtlModule;

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int nShowCmd)
{
   return _AtlModule.WinMain(nShowCmd);
}

Community Additions

ADD
Show:
© 2014 Microsoft