| Tenouk C & C++ | MFC Home | COM Part 3 | COM Part 5 | Download | Site Index |


 

 

 

 

 

The Component Object Model - COM part 4

 

 

 

 

 

 

 

Program examples compiled using Visual C++ 6.0 compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this tutorial are listed below. Don’t forget to read Tenouk’s small disclaimer. The supplementary notes for this tutorial are OLE, mfc, COleObjectFactory class and .NET.

  1. The MYMFC28B Example: An MFC COM In-Process Component

 

 

The MYMFC28B Example: An MFC COM In-Process Component

 

The MYMFC28B example is an MFC regular DLL that incorporates a true COM version of the CSpaceship class you saw in MYMFC28A. AppWizard generated the mymfc28B.cpp and mymfc28B.h files, as described previously. Listing 7 shows the Interface.h file, which declares the IMotion and IVisual interfaces. Listing 8 and 9 show the code for the CSpaceship class. Compare the code to the code in MYMFC28A. Do you see how the use of the MFC macros reduces code size? Note that the MFC CCmdTarget class takes care of the reference counting and QueryInterface() logic.

 

The steps for the MYMFC28B, MFC regular DLL program are shown below.

 

Figure 14: MYMFC28B - AppWizard new project dialog.

 

Figure 14: MYMFC28B - AppWizard new project dialog.

 

Don’t forget to tick the Automation check box.

 

 

Figure 15: MYMFC28B - AppWizard DLL step 1 of 1.

 

Figure 15: MYMFC28B - AppWizard DLL step 1 of 1.

 

Figure 16: MYMFC28B project summary.

 

Figure 16: MYMFC28B project summary.

 

Add the CSpaceship class.

 

Figure 17: Adding new class to project.

 

Figure 17: Adding new class to project.

 

Figure 18: Entering new class information.

 

Figure 18: Entering new class information.

 

Add the Interface.h header file.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Figure 19: Adding new header file to project.

 

Figure 19: Adding new header file to project.

 

Copy the Interface.h, Spaceship.h and Spaceship.cpp contents as in the following Listings into the respective files in the project.

Remove or comment out the following #include statements.

 

COM and MFC - C++ code snippet

 

Listing 6.

 

Build your program, make sure no error or warning. This will generate the mymfc28B.dll file.

 

Figure 20: MYMFC28B - the generated DLL file.

 

Figure 20: MYMFC28B - the generated DLL file.

 

Next, proceed to the client program, MYMFC28C.

 

INTERFACE.H

 

// interface.h

 

struct IMotion : public IUnknown

{

    STDMETHOD_(void, Fly) () = 0;

    STDMETHOD_(int&, GetPosition) () = 0;

};

 

struct IVisual : public IUnknown

{

    STDMETHOD_(void, Display) () = 0;

};

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Listing 7: The Interface.h file.

 

SPACESHIP.H

 

#if !defined(AFX_SPACESHIP_H__170C4C09_9012_41F7_B943_7F3B4906BA37__INCLUDED_)

#define AFX_SPACESHIP_H__170C4C09_9012_41F7_B943_7F3B4906BA37__INCLUDED_

 

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

 

void ITrace(REFIID iid, const char* str);

 

//////////////////////////////////////////////////////////////////////

// CSpaceship command target

 

class CSpaceship : public CCmdTarget

{

    DECLARE_DYNCREATE(CSpaceship)

 

private:

    int m_nPosition; // We can access this from all the interfaces

    int m_nAcceleration;

    int m_nColor;

protected:

    CSpaceship();    // protected constructor used by dynamic creation

 

// Attributes

public:

 

// Operations

public:

 

// Overrides

    // ClassWizard generated virtual function overrides

    //{{AFX_VIRTUAL(CSpaceship)

    public:

    virtual void OnFinalRelease();

    //}}AFX_VIRTUAL

 

// Implementation

protected:

    virtual ~CSpaceship();

 

    // Generated message map functions

    //{{AFX_MSG(CSpaceship)

        // NOTE - the ClassWizard will add and remove member

        //  functions here.

    //}}AFX_MSG

 

    DECLARE_MESSAGE_MAP()

    DECLARE_OLECREATE(CSpaceship)

    BEGIN_INTERFACE_PART(Motion, IMotion)

        STDMETHOD_(void, Fly) ();

 

        STDMETHOD_(int&, GetPosition) ();

    END_INTERFACE_PART(Motion)

 

    BEGIN_INTERFACE_PART(Visual, IVisual)

        STDMETHOD_(void, Display) ();

    END_INTERFACE_PART(Visual)

 

    DECLARE_INTERFACE_MAP()

};

 

/////////////////////////////////////////////////////////////////////////////

 

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

 

#endif // !defined(AFX_SPACESHIP_H__170C4C09_9012_41F7_B943_7F3B4906BA37__INCLUDED_)

 

Listing 8:  The Spaceship.h file.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

SPACESHIP.CPP

 

// Spaceship.cpp : implementation file

//

 

#include "stdAfx.h"

#include "mymfc28B.h"

#include "Interface.h"

#include "Spaceship.h"

 

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

//////////////////////////////////////////////////////////////////////

// CSpaceship

 

// {692D03A4-C689-11CE-B337-88EA36DE9E4E}

static const IID IID_IMotion = { 0x692d03a4, 0xc689, 0x11ce, { 0xb3, 0x37, 0x88, 0xea, 0x36, 0xde, 0x9e, 0x4e } };

// {692D03A5-C689-11CE-B337-88EA36DE9E4E}

static const IID IID_IVisual = { 0x692d03a5, 0xc689, 0x11ce, { 0xb3, 0x37, 0x88, 0xea, 0x36, 0xde, 0x9e, 0x4e } };

 

IMPLEMENT_DYNCREATE(CSpaceship, CCmdTarget)

CSpaceship::CSpaceship()

{

    TRACE("CSpaceship ctor\n");

    m_nPosition = 100;

    m_nAcceleration = 101;

    m_nColor = 102;

    // To keep the application running as long as an OLE automation

    //  object is active, the constructor calls AfxOleLockApp.

 

    AfxOleLockApp();

}

 

CSpaceship::~CSpaceship()

{

    TRACE("CSpaceship dtor\n");

    // To terminate the application when all objects created with

    //  OLE automation, the destructor calls AfxOleUnlockApp.

   

    AfxOleUnlockApp();

}

 

void CSpaceship::OnFinalRelease()

{

    // When the last reference for an automation object is released

    //  OnFinalRelease() is called. This implementation deletes the

    //  object. Add additional cleanup required for your object before deleting it from memory.

 

    delete this;

}

BEGIN_MESSAGE_MAP(CSpaceship, CCmdTarget)

    //{{AFX_MSG_MAP(CSpaceship)

    // NOTE - ClassWizard will add and remove mapping macros here.

    //}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

BEGIN_INTERFACE_MAP(CSpaceship, CCmdTarget)

    INTERFACE_PART(CSpaceship, IID_IMotion, Motion)

    INTERFACE_PART(CSpaceship, IID_IVisual, Visual)

END_INTERFACE_MAP()

 

// {692D03A3-C689-11CE-B337-88EA36DE9E4E}

IMPLEMENT_OLECREATE(CSpaceship, "Spaceship", 0x692d03a3, 0xc689,

                    0x11ce, 0xb3, 0x37, 0x88, 0xea, 0x36, 0xde, 0x9e, 0x4e)

STDMETHODIMP_(ULONG) CSpaceship::XMotion::AddRef()

{

    TRACE("CSpaceship::XMotion::AddRef\n");

    METHOD_PROLOGUE(CSpaceship, Motion)

    return pThis->ExternalAddRef();

}

 

STDMETHODIMP_(ULONG) CSpaceship::XMotion::Release()

{

    TRACE("CSpaceship::XMotion::Release\n");

    METHOD_PROLOGUE(CSpaceship, Motion)

    return pThis->ExternalRelease();

}

 

STDMETHODIMP CSpaceship::XMotion::QueryInterface(REFIID iid, LPVOID* ppvObj)

{

    ITrace(iid, "CSpaceship::XMotion::QueryInterface");

    METHOD_PROLOGUE(CSpaceship, Motion)

    return pThis->ExternalQueryInterface(&iid, ppvObj);

}

 

STDMETHODIMP_(void) CSpaceship::XMotion::Fly()

{

    TRACE("CSpaceship::XMotion::Fly\n");

    METHOD_PROLOGUE(CSpaceship, Motion)

    TRACE("m_nPosition = %d\n", pThis->m_nPosition);

    TRACE("m_nAcceleration = %d\n", pThis->m_nAcceleration);

    return;

}

 

STDMETHODIMP_(int&) CSpaceship::XMotion::GetPosition()

{

    TRACE("CSpaceship::XMotion::GetPosition\n");

    METHOD_PROLOGUE(CSpaceship, Motion)

    TRACE("m_nPosition = %d\n", pThis->m_nPosition);

    TRACE("m_nAcceleration = %d\n", pThis->m_nAcceleration);

    return pThis->m_nPosition;

}

 

//////////////////////////////////////////////////////////////////////

STDMETHODIMP_(ULONG) CSpaceship::XVisual::AddRef()

{

    TRACE("CSpaceship::XVisual::AddRef\n");

    METHOD_PROLOGUE(CSpaceship, Visual)

    return pThis->ExternalAddRef();

}

 

STDMETHODIMP_(ULONG) CSpaceship::XVisual::Release()

{

    TRACE("CSpaceship::XVisual::Release\n");

    METHOD_PROLOGUE(CSpaceship, Visual)

    return pThis->ExternalRelease();

}

 

STDMETHODIMP CSpaceship::XVisual::QueryInterface(REFIID iid, LPVOID* ppvObj)

{

    ITrace(iid, "CSpaceship::XVisual::QueryInterface");

 

    METHOD_PROLOGUE(CSpaceship, Visual)

    return pThis->ExternalQueryInterface(&iid, ppvObj);

}

 

STDMETHODIMP_(void) CSpaceship::XVisual::Display()

{

    TRACE("CSpaceship::XVisual::Display\n");

    METHOD_PROLOGUE(CSpaceship, Visual)

    TRACE("m_nPosition = %d\n", pThis->m_nPosition);

    TRACE("m_nColor = %d\n", pThis->m_nColor);

}

 

//////////////////////////////////////////////////////////////////////

void ITrace(REFIID iid, const char* str)

{

    OLECHAR* lpszIID;

    ::StringFromIID(iid, &lpszIID);

    CString strTemp = (LPCWSTR) lpszIID;

    TRACE("%s - %s\n", (const char*) strTemp, (const char*) str);

    AfxFreeTaskMem(lpszIID);

}

 

//////////////////////////////////////////////////////////////////////

// CSpaceship message handlers

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Listing 9:  The Spaceship.cpp file.

 

 

Continue on next module.....

 

 

 

 

 

 

Further reading and digging:

  1. DCOM at MSDN.

  2. COM+ at MSDN.

  3. COM at MSDN.

  4. Win32 process, thread and synchronization story can be found starting from Module R.

  5. MSDN MFC 7.0 class library online documentation.

  6. MSDN MFC 9.0 class library online documentation - latest version.

  7. MSDN Library

  8. Windows data type.

  9. Win32 programming Tutorial.

  10. The best of C/C++, MFC, Windows and other related books.

  11. Unicode and Multibyte character set: Story and program examples.

 

 


 

| Tenouk C & C++ | MFC Home | COM Part 3 | COM Part 5 | Download | Site Index |