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.
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.
Don’t forget to tick the Automation check box.
|
Figure 15: MYMFC28B - AppWizard DLL step 1 of 1.
Figure 16: MYMFC28B project summary. |
Add the CSpaceship class.
Figure 17: Adding new class to project.
Figure 18: Entering new class information.
Add the Interface.h header file.
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.
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.
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:
Win32 process, thread and synchronization story can be found starting from Module R.
MSDN What's New (MFC Feature Pack) - feature pack.
DCOM at MSDN.
COM+ at MSDN.
COM at MSDN.
Unicode and Multi-byte character set: Story and program examples.