electronics.ozhiker.com

Converting a MFC CWnd derived class to a ActiveX control.



Creating the project

  1. Create a new ATL project with the ATL COM AppWizard,
  2. Enter a name for the project and hit enter
  3. Select Dynamic Link Library (DLL), as well as Support MFC and hit Finish
  4. Hit OK to create the project.

Adding your Source to the project

  1. Add your source files to the project
  2. Copy any resources needed by these source files into the new project's resource file

Modify the automatically generated files

  1. Add the following lines to the stdafx.h file immediately above the "#include <atlbase.h>" line
  2. #include <afxcmn.h>
    #include <afxext.h>
    
    #define m_dwRef m_dwRefAtl
    #define m_pOuterUnknown m_pOuterUnknownAtl
    #define InternalQueryInterface InternalQueryInterfaceAtl
    #define InternalAddRef InternalAddRefAtl
    #define InternalRelease InternalReleaseAtl
    			

Creating the control

  1. Add an ATL control by selecting <Insert - New ATL Object>
  2. Select category "Controls", select the Full Control object and hit next.
  3. Enter a name for your control.
  4. Change the other attibutes and stock properties if you wish.
  5. Hit ok to create control.

Customising the Control header file code

  1. Include the header file for your CWnd derived class in the control header file.
  2. At the top of the header for the new control, add the following code: (Replace YOURWNDCLASS with the name of the CWnd derived class to be turned into a control (Replace YOURCOMPONENTCLASS with the name of your component class
  3. class YOURCOMPONENTCLASS; // Forward Decl
    typedef CWindowImpl < YOURCOMPONENTCLASS, YOURCLASS > MFCWndImpl;
    typedef CComControl < YOURCOMPONENTCLASS, MFCWndImpl > MFCComCtrl;
    			
  4. Replace the line:
    public CComControl<CGraph2D>,
    with
    public MFCComCtrl,
  5. Replace the following line in the message map :
    CHAIN_MSG_MAP(CComControl<CGraph2D>)
    with
    CHAIN_MSG_MAP( MFCComCtrl );
  6. Comment out or delete the OnDraw method
  7. Since the window for the control is created within the ATL code, any overridden Create method in your base CWnd derived class will not be used. Hence to perform any initialisation needed during the creation, add an OnCreate handler to the Control header:
    LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
    {
        // Place your initialisation code here
        return 0;
    }
    			
    And add the corresponing line at the top of message map :
    MESSAGE_HANDLER(WM_CREATE, OnCreate)
  8. ActiveX controls can work in either windowed or windowless mode. The method described here will not work with the windowless mode, so add the following line to he constructor for the control class:
    m_bWindowOnly = TRUE;
  9. To allow the control to handle being sized properly, add the following method to the control class
    STDMETHOD(SetObjectRects)(LPCRECT prcPos,LPCRECT prcClip)
    {
        IOleInPlaceObjectWindowlessImpl< YOURCOMPONENTCLASS >::SetObjectRects(prcPos, prcClip);
        YOURWNDCLASS::OnMove( prcPos->left, prcPos->top );
        YOURWNDCLASS::OnSize( SIZE_RESTORED,
        prcPos->right - prcPos->left,
        prcPos->bottom - prcPos->top );
        return S_OK;
    }
    			

Modifying your CWnd derived class

  1. To make ATL think your CWnd derived class is a CWindow derived class, add the following method:
    static LPCTSTR GetWndClassName()
    {
        return NULL;
    }
    			

Initial Testing

  1. At this stage you should now be able to compile the Control
  2. You can check if it works by starting the ActiveX test container and inserting an instance of your component. The control should be fully functional, however it will be useless to clients as it has no properties or methods.

Adding Methods and Properties to the Control.

  1. Add a method or property for each of the methods and member variables in your CWnd derived class that you wish to export. To do this, select the interface for your control in the class view and right click it, and choose "Add method" or "Add property".

    Remember you should only use the data types which are part of the VARIANT structure:

    BYTE, USHORT, UINT, ULONG, CHAR, SHORT, INT, LONG, FLOAT, DOUBLE, VARIANT_BOOL, SCODE, CY, DATE, BSTR, IUnknown*, IDispatch*, SAFEARRAY*, VARIANT*, DECIMAL*, _tagBRECORD.

    (Other data types which evaluate to one of these are also valid)


electronics.ozhiker.com

www.ozhiker.com