Step 2: Creating an ActiveX Control with MFC

This step shows how to create an ActiveX control with the Ctrl class defined in Step 1: Preparing the Program. The ActiveX control you will obtain once this step is completed has a minimal interface.

You are going to:

Create a new project.

  1. In Visual C++, choose New > Project from the File menu and select MFC ActiveX Control to start creating a new project.

  2. Type DemoMFC in the Project name text field and leave the proposed options as they are.

  3. Click OK.

  4. The MFC ActiveX Control Wizard is displayed.

  5. Open the Control Settings tab.

  6. Check the following options: Activates when visible and Available in “Insert Object” dialog.

  7. You might also check Has an “About” box, but this is optional.

  8. Leave the other properties unchecked. The window must not be a subclass of any control. Also be sure that Windowless activation is unchecked.

  9. Click Finish.

Add files to the project.

  1. Add the file ctrl.cpp to the project.

  2. Create the DemoCtrl.h file and add it to the project.

    This file should contain the declaration of the DemoCtrl class that follows. This class initializes the control. It also provides an interface between the code generated by the wizard and the Views code and/or the Ctrl class.

    class DemoCtrl : public Ctrl

    {

    public:

    DemoCtrl(HWND parent);

    ~DemoCtrl();

    static IlvDisplay* getDisplay()throw() { return _Display; }

    static bool InitDisplay(HINSTANCE hInstance) throw();

    static void CleanDisplay();

     

    private:

    DemoCtrl(const DemoCtrl&); // Not defined to avoid

    // default copy constructor.

    static IlvDisplay* _display;

    };

  3. Create the DemoCtrl.cpp file and add it to the project.

    This file defines the member functions of the DemoCtrl class that are not declared inline and the static class variable _Display .

    • The constructor DemoCtrl(HWND parent) calls the corresponding constructor of the Ctrl class:

      DemoCtrl::DemoCtrl(HWND hWnd)

      : Ctrl(_Display, reinterpret_cast<IlvSystemView>(hWnd))

      {

      }

    • The static member function InitDisplay creates an instance of IlvDisplay and stores it into _Display.

      bool

      DemoCtrl::InitDisplay(HINSTANCE hInstance) throw ()

      {

      try {

      _Display = new IlvDisplay(hInstance, "MFC Views Sample");

      if (!_Display || _Display->isBad()) {

      IlvFatalError("Can’t initialize IlvDisplay.");

      if (_Display) {

      delete _Display;

      _Display = 0;

      }

      }

      }

      catch(...) {

      CleanDisplay();

      }

      return _Display ? true : false;

      }

    • The static function CleanDisplay releases the instance of IlvDisplay stored in _Display.

      void

      DemoCtrl::CleanDisplay()

      {

      if (_Display) {

      delete _Display;

      _Display = 0;

      }

      }

Modify the file generated by the wizard.

Modify the file DemoMFC.cpp generated by the wizard to create and then delete an instance of the IlvDisplay class. Use the static member functions of the DemoCtrl class as follows:

  1. Include the header file DemoCtrl.h.

  2. In the CDemoMFCApp::InitInstance member function, add the following line to the bInit test.

    bInit = DemoCtrl::InitDisplay(AfxGetInstanceHandle());

  3. Add the following line at the beginning of the CDemoMFCApp::ExitInstance member function:

    DemoCtrl::CleanDisplay();

Add a private member variable for CDemoMFCCtrl.

  1. Expand DemoMFC classes and select CDemoMFCCtrl.

  2. Press the right mouse button and choose Add > Variable .

  3. Enter DemoCtrl* in the Variable Type field.

  4. Enter m_Ctrl in the Variable Name field and click OK.

  5. Include DemoCtrl.h in DemoMFCCtrl.h.

Add a new windows message handler to the CDemoMFCCtrl class.

  1. Locate the BEGIN_MSG_MAP declaration in DemoMFCCtrl.h.

  2. In the BEGIN_MSG_MAP declarations, add the following code:

    //{{AFX_MSG_MAP(CDemoMFCCtrl)

    ON_WM_CREATE()

    //}}AFX_MSG_MAP

  3. Locate DECLARE_MESSAGE_MAP() in DemoMFCCtrl.h.

  4. Prepend the following code to it:

    //{{AFX_MSG(CDemoMFCCtrl)

    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

    //}}AFX_MSG

  5. Open DemoMFCCtrl.cpp and add the OnCreate method implementation:

    int CDemoMFCCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)

    {

    if (COleControl::OnCreate(lpCreateStruct) == -1)

    return -1;

    // TODO: Add your specialized creation code here

    // Added for Views.

    try {

    m_Ctrl = new DemoCtrl(m_hWnd);

    } catch (...) {

    if (m_Ctrl) {

    delete m_Ctrl;

    m_Ctrl = 0;

    }

    }

    // End Added for Views.

    return 0;

    }

Modify the DemoMFC.rc file.

Add the following line at the end of the file DemoMFC.rc.

#include "viewsdata.rc"

Modify the project settings

  1. Open the project property pages.

  2. In the Project Settings dialog box, select the Debug configuration and click the C/C++ tab.

  3. Select the General or Preprocessor option in the Category drop-down list and replace the preprocessor definition _DEBUG by NDEBUG.

  4. Select All Configurations and click the General tab.

  5. Choose “Use MFC in a Static Library” from the Microsoft Foundation Classes drop-down list.

  6. Activate the C++ tab, select the General or Preprocessor option in the Category drop-down list, and add ILVSTD to the “Preprocessor definitions” text field.

  7. Select Code Generation in the C/C++ category and select Yes (/EHSC) for Enable C++ Exceptions and select Multi-threaded (/MT) for Runtime Library.

  8. Select Language in the C/C++ category drop-down list Enable Run-Time Type Information (RTTI).

  9. Select General in the C/C++ category and type the following line in the Additional include directories text field:

    ".;c:\Perforce\views\include"

    Here we assume that Views is installed in C:\Perforce\views\.

  10. Select “Precompiled headers” in the Category drop-down list and select the option “Not using precompiled headers” for the files ctrl.cpp and DemoCtrl.cpp.

    Because of the initialization mechanism of Views, most of the Views headers cannot be precompiled.

  11. In the Linker category, select General in the category and add the path to the Views stat_mta libraries to the “Additional library path” text field.

    Ex: c:\Perforce\views\lib\x86_.net2010_10.0\stat_mta

  12. Select Input in the Linker category and add the Views libraries (that is, winviews.lib, views.lib, and ilvgadgt.lib) and also the wsock32.lib and imm32.lib libraries in additional dependencies.

Now you can build the ActiveX control and test it.

Create an html test file, like this:

<HTML>

<HEAD>

<TITLE>Test page for object DemoMFCCtrl</TITLE>

</HEAD>

 

<BODY>

 

<OBJECT WIDTH=400 HEIGHT=400 ID="DemoMFCCtrl"CLASSID="CLSID:3D31E7B8-400B-11D3-B74F-00C04F68A89D"></OBJECT>

 

</BODY>

 

</HTML>

Note

Since the class id is generated, the class id in your file may be different from the one in this example.