DOCUMENT:Q218442 26-JUN-2001 [visualc] TITLE :HOWTO: Dynamically Add ActiveX Controls to ATL Composite Control PRODUCT :Microsoft C Compiler PROD/VER:WINDOWS:3.0 OPER/SYS: KEYWORDS:kbActiveX kbCOMt kbCtrlCreate kbDlg kbVC600 kbATL300 kbGrpDSMFCATL ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - The Microsoft Active Template Library (ATL) 3.0, included with: - Microsoft Visual C++, 32-bit Enterprise Edition, version 6.0 - Microsoft Visual C++, 32-bit Professional Edition, version 6.0 - Microsoft Visual C++, 32-bit Learning Edition, version 6.0 ------------------------------------------------------------------------------- SUMMARY ======= This article shows you how to add ActiveX controls to an ATL composite control programmatically. These techniques can also be used to dynamically create ActiveX controls on any window. MORE INFORMATION ================ A good place to programmatically add ActiveX controls to an ATL composite control is in the WM_INITDIALOG handler. Add the following message map entry and handler function to your CComCompositeControl derived class. MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return 0; } You can now use one of the following methods to add controls programmatically in the WM_INITDIALOG message handler. The CAxWindow class is just a wrapper class. When it goes out of scope, it does not destroy the corresponding ActiveX control, so it can be declared on the stack. By having it as a member of the composite control class you can use the convenient wrapper functions of CWindow (CAxWindow derives from CWindow). Also, in the following ATL creation the functions of the ProgID can be replaced by a CLSID or URL. Refer to the CAxWindow::CreateControl() online documentation for more information. To obtain the control or container interfaces, use the CAxWindow members QueryControl() and QueryHost() or the global functions AtlAxGetControl() and AtlAxGetHost(). // // WIN32 API CreateWindow() method // //register AtlAxWin class which implements ATL containment //this is not needed for an ATL composite control AtlAxWinInit(); //m_hWnd is the composite control handle
//IDC_MYCTL is an ID that was added through the "View/Resource Symbols" //menu option. HWND hWnd = ::CreateWindow(_T("AtlAxWin"), _T("MSCAL.Calendar"), WS_CHILD|WS_VISIBLE, 10, 10, 400, 300, m_hWnd, (HMENU)IDC_MYCTL, _Module.GetModuleInstance(), NULL); // make sure module handle corresponds to module in which 'AtlAxWin' // class is registered. - OR - // // CAxWindow::Create() method // //register the AtlAxWin class which implements ATL containment //this is not needed for an ATL composite control AtlAxWinInit(); CAxWindow wnd; RECT rect = {10,10,400,300}; //m_hWnd is the composite control handle //rect is the size of ActiveX control in client coordinates wnd.Create(m_hWnd, rect, _T("MSCAL.Calendar"), WS_CHILD|WS_VISIBLE, 0, IDC_MYCTL); The following 2 methods can be used if the ActiveX control's properties need to be initialized: // // CAxWindow::CreateControl() method // // m_hWnd is usually the HWND of the activex controls' parent CAxWindow wnd; wnd.Attach(m_hWnd); // Since CreateControl does not take a RECT param, the ActiveX // control occupies the full area of the window. m_pStream is an IStream // pointer containing the control's persisted properties wnd.CreateControl(OLESTR("MSCAL.Calendar"), m_pStream); // CreateControl[Ex] in turn just calls AtlAxCreateControl[Ex]. // So AltCreateControl[Ex]() could also be called directly. // For example the above call would be // AtlAxCreateControl(OLESTR("MSCAL.Calendar"), m_hwnd, m_pStream, NULL) - OR - // // CAxWindow::CreateControlEx() method // // CreateControlEx in addition to initializing properties, also // allows you to specify a sink interface for events. // m_hWnd is usually the HWND of the ActiveX control's parent. CAxWindow wnd; wnd.Attach(m_hWnd); // control & container IUnknown interface pointers LPUNKNOWN pUnkCtrl, pUnkCont; // Since CreateControl does not take a RECT param, the ActiveX // control occupies the full area of the window. DIID_DCalendarEvents is // the soruce interface ID of the calendar control and m_pSink is a // pointer to the sink object. For information on creating sinks // please refer to knowledge base article Q194179 wnd.CreateControlEx(OLESTR("MSCAL.Calendar"), m_pStream, &pUnkCtrl, &pUnkCont, DIID_DCalendarEvents, (IUnknown*)m_pSink); - OR - // // CAxWindow::AttachControl method // // This method is used to create the ActiveX control and activate // it in 2 separate steps. m_hWnd is usually the HWND of the // ActiveX control's parent. CAxWindow wnd; CLSID clsid; LPUNKNOWN pUnkCtrl, pUnkCont; HRESULT hr = CLSIDFromProgID(OLESTR("MSCAL.Calendar"), &clsid); hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pUnkCtrl); CComQIPtr spPerStm(pUnkCtrl); spPerStm->InitNew(); wnd.Attach(m_hWnd); wnd.AttachControl(pUnkCtrl, &pUnkCont); - OR - // // IAxWinHostWindow method // // CAxWindow methods CreateControl[Ex] & AttachControl eventually call // methods of IAxWinHostWindow. These methods can be called directly. CAxWindow wnd; RECT rect = {10,10,400,300}; // create the container window wnd.Create(m_hWnd, rect, 0, WS_CHILD|WS_VISIBLE, 0, IDC_MYCTL); CComPtr spHostWnd; wnd.QueryHost(&spHostWnd); // create the activex control spHostWnd->CreateControl(OLESTR("MSCAL.Calendar"), wnd, NULL); // Alternatively you could call CreateControlEx() or AttachControl() // methods of IAxWinHostWindow as in previous examples. REFERENCES ========== VC++ Online documentation Q192560 HOWTO: Adding ATL Control Containment Support to Any Window Q194179 SAMPLE: AtlEvnt.exe Creates ATL Sinks Using IDispEventImpl Additional query words: ====================================================================== Keywords : kbActiveX kbCOMt kbCtrlCreate kbDlg kbVC600 kbATL300 kbGrpDSMFCATL Technology : kbAudDeveloper kbATLsearch Version : WINDOWS:3.0 Issue type : kbhowto ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 2001.