COM programming with MFC in VC ++ 6.0

zhaozj2021-02-11  194

First, it should be clear that the MFC is to implement the COM interface through the nested category rather than multiple inheritance, and the interface and implementation of the interface are associated with the nested classes that implement the interface; the MFC is provided with a simple macro to achieve nested Class definition. Second, the MFC implements the iUnknown interface through the CCMDTARGET class.

This article first describes the steps and core code for creating a COM server. Then explain the critical code of the client program.

This COM server implements a TimelogServer component. For your concise, this component has only one interface ITIMELOG, and the log text can be output to the log file with the method OutputLog through ItimeLog.

Create an MFC DLL project, select Support Automation (Of course this program is not necessarily an automation server, this is here to automatically implement several necessary output functions such as DllgetClassObject, DllRegisterServer, etc., otherwise write yourself)

Section 1 COM server

I. Disclaimer Components and Interfaces

1. Write a guids.h, declare the components and interfaces in Guids.h.

// Declaration Components Guid {A433E701-E45E-11D3-97B5-52544CBA7F28}

// define_guid (CLSID_TIMELOGSERVER,

// 0xA433E701, 0XA45E, 0X11D3, 0x97, 0xB5, 0x52, 0x54, 0x4c, 0xBa, 0x7f, 0x28);

Static const Iid CLSID_TIMELOGSERVER =

{0xA433E701, 0xE45E, 0x11D3, {0x97, 0xB5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28}};

// Declaration interface guid {a433e702-E45E-11D3-97B5-52544CBA7F28}

// define_guid (IID_ITIMELOG,

// 0xA433E702, 0xA433E702, 0xE45E, 0X11D3, 0x97, 0xB5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28);

Static const same IID_ITIMELOG =

{0xA433E702, 0xE45E, 0x11D3, {0x97, 0xB5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28}};

2. Write a ITIMELOGSERVER.H, declare components and interfaces in the ITIMELOGSERVER.H file

//Itimelogserver.h

#include "guids.h"

// Interface ITIMELOG declaration

Declare_Interface_ (ITIMELOG, IUNKNOWN)

{

STDMETHOD (OUTPUTLOG) PURE;

}

Description: 1. Macro Define_GUID associates the PROGID of the components and interfaces. You can use the Guidgen.exe tool.

2. Macro Declare_interface_ declare the interface; the macro first parameter is the interface name, the second parameter is the base class for the interface. Declare the interface without the base class with the DECLARE_INTERFACE macro.

3. Macro STDMethod declare the method in the interface. The return value of this method is explained as "= 0", that is, this method is a pure virtual function. When the return value of the method is not HRESULT, macro stdmethod_ (return type , Function name) (parameter) PURE;

II. Declaration Components CTIMELOGSERVER and nested classes to implement interface

Add a new class CTimelogServer in ClassWizard, the base class is selected as ccmdtarget. Modify its header file TimelogServer1.h, plus #include "itimelogserver.h"; while plus in class declaration

// Declare the nested class to realize the ITIMELOG interface

Begin_Interface_part (Timelog, Itimelog) // three methods for automatically declaring the iUnknown interface

STDMETHOD (OUTPUTLOG); End_Interface_part (Timelog)

// Declaration Interface Map

Declare_interface_map ()

// Disclaimer

Declare_olecreate (CTimelogServer)

Third. Implementation of class and interface mappings

Write in the implementation file of CTimelogServer:

/ / Implementation

Implement_olecreate (CTimelogServer, "TimelogServer",

0xA433E701, 0XE45E, 0x11D3, 0x97, 0xB5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28);

// Mapping the interface to the corresponding nested class

Begin_Interface_map (ctimelogserver, ccmdtarget)

Interface_part (CTimelogServer, IID_ITIMELOG, TIMELOG)

END_INTERFACE_MAP ()

Four. Counting the overall object count in the constructor and destructive function

CTimelogServer :: ctimelogserver ()

{

:: AfxoLockApp ();

}

CTimelogServer :: ~ ctimelogserver ()

{

:: AfxoleunlockApp ();

}

5. Realize the IUNKNOWN interface for nested classes

/ / Realize IUNKNOWN interface for nested classes

STDMETHODIMP_ (ULONG)

CTimelogServer :: Xtimelog :: AddRef ()

{

Method_Prologue (CTimelogServer, Timelog)

Return PTHIS-> EXTERNALADDREF ();

}

STDMETHODIMP_ (ULONG)

CTimelogServer :: Xtimelog :: release ()

{

Method_Prologue (CTimelogServer, Timelog)

Return PTHIS-> EXTERNALRELEASE ();

}

StdMethodimp

CTimelogServer :: Xtimelog :: queryinterface (refiid riid, void ** ppvobj)

{

Method_Prologue (CTimelogServer, Timelog)

Return PTHIS-> ExternalQueryInterface (& RiID, PPVObj);

}

Description: Although the CCMDTARGET class has implemented the IUnknown interface, it is also necessary to map the nested class's IUNKNOWN to the iUnknown interface supported by the ccmdTarget. The two parameters of the Method_Prologueh macro are the classes of the component object and implement the interface. Set.

6. Method for realizing itiMelog interface Outputlog

Note The functionality of this component is to enter the log file into the log file.

1. Add a file pointer to the component class:

// attributes

PUBLIC:

protected:

FILE * M_LOGFILE;

2. Initialization and exit

First, some initialization is performed in the constructor of CTimelogServer:

CTimelogServer :: ctimelogserver ()

{

:: AfxoLockApp ();

CTIME TIMESTAMP = CTime :: getcurrenttime ();

CSTRING FILENAME;

Filename.Format (_T ("% s.log"), timestamp.format ("% y% m% D"));

m_logfile = fopen (filename, _t ("a"));

IF (m_logfile)

{

FPRINTF (M_Logfile, _T ("# # # # # # # # # # # # # # # # # # # # # # # # #tf (m_logfile, _t (" Start:% s "), (LPCTSTR) TimeStamp. Format ("% y year% M month% D day% h:% m% s"));

FPRINTF (m_logfile, _t ("/ n"));

}

}

/ / Then close the file in the destructor

CTimelogServer :: ~ ctimelogserver ()

{

:: AfxoleunlockApp ();

IF (m_logfile)

{

CTIME TIMESTAMP = CTime :: getcurrenttime ();

FPRINTF (m_logfile, _t ("/ n"));

FPRINTF (M_Logfile, _T ("end:% s"), (lpctstr) timestamp.format ("% y year% M month% D day% h:% m% s"));

FPRINTF (m_logfile, _t ("/ n"));

FPRINTF (M_Logfile, _T ("# # # # # # # # # # # / n"));

Fclose (m_logfile);

}

}

3. Implement the interface ITIMELOG method

/ / Implement the interface ITIMELOG method

StdMethodimp

CtimelogServer :: Xtimelog :: OutputLog (BSTR * VARLOGTEXT)

{

Method_Prologue (CTimelogServer, Timelog)

IF (PTHIS-> M_LOGFILE)

{

CTIME TIMESTAMP = CTime :: getcurrenttime ();

CString nowTime = timestamp.format ("% y year% M month% D day% h:% m:% s");

CString logtext (lpcwstr) * varLogtext);

FPrintf (pTHIS-> M_LogFile, "/ N% S / N% S / N%", NOWTIME, LOGTEXT

Return noerror;

}

Else

{

AfxMessageBox ("No log file!");

Return S_FALSE;

}

}

Seven. Improve component server

Process instance () and exitInstance () in the implementation file of the application object CTIMELOGSERVERAPP

Bool ctimelogserVerapp :: initInstance ()

{

:: AfxoLockApp ();

// Register All Ole Server (Factories) As Running. This Enables the

// Ole Libraries to create Objects from Other Applications.

ColeObjectFactory :: registerall ();

Return True;

}

Int ctimelogserVerapp :: exitInstance ()

{

// Todo: Add Your Specialized Code Here and / or Call The Base Class

:: AfxoleunlockApp ();

Return CWINAPP :: EXITINSTANCE ();

}

Section 2 client program

The key steps of using the COM component server are: Initialize the COM library, create component objects, and get the iUnknown interface pointer, query the interface and use, release the component.

#include "itiMelogserver.h"

// Initialize the COM library, instantiate the components

HRESULT HRESULT;

IUNKNOWN * PIUNKNOWN; HRESULT = :: Coinitialize (NULL);

Failed (HRESULT))

{

:: AfxMessageBox ("You can't initialize the COM library!");

Return False;

}

// Create a component instance

Piunknown = null;

HRESULT = :: COCREATEINSTANCE (CLSID_TIMELOGSERVER, NULL,

CLSCTX_INPROC_SERVER, IID_IUNKNOWN, (VOID **) & PIUNKNOWN;

Failed (HRESULT))

{

Piunknown = null;

:: AfxMessageBox ("You can't create Timelog Objects!");

Return False;

}

/ / Query the interface and use

IF (PiunkNown! = NULL)

{

ITIMELOG * PITIMELOG;

HRESULT = Piunknown-> queryinterface (iid_itimelog, (void **) & pitimelog);

Failed (HRESULT))

{

:: AfxMessageBox ("You cannot get interface itimelog!");

Piunknown-> Release ();

Return;

}

BSTR BSTRLOGTEXT;

Bstrlogtext = m_logtext.allocsystring ();

CString text ((lpcwstr) BSTRLogText);

:: AfxMessageBox (Text);

IF (Failed (PitiMelog-> Outputlog (& Bstrlogtext))))

{

:: AfxMessageBox ("Log Output Error!");

PitiMelog-> Release ();

Return;

}

PitiMelog-> Release ();

:: AfxMessageBox ("Log already writes!");

}

// Release component

Piunknown-> Release ();

Piunknown = null;

:: Couninitialize ();

转载请注明原文地址:https://www.9cbs.com/read-3953.html

New Post(0)