Use MFC for COM programming in VC ++ 6.0

Source: Internet
Author: User
Tags ole
First, it should be clear that in MFC, the COM interface is implemented through nested classes instead of multiple inheritance, and the interface and the nested class implementing this interface are associated through the interface ing mechanism; MFC provides a set of concise macros to implement the definition of Nested classes. secondly, MFC implements the iunknown interface through the csf-target class.

This article first describes the steps and core code for creating a COM server, and then describes the key code of the customer program.

This COM server implements a timelogserver component. For the sake of conciseness, this component has only one interface, itimelog. The outputlog method of itimelog can output the log text to the log file.

Create an mfc dll project and select to support automation (of course, this program is not necessarily an Automation server. Here, we do this by automatically implementing several necessary output functions, such as dllgetclassobject and dllregisterserver, otherwise, write it by yourself)

  Section 1 COM Server

  I. Declare components and interfaces

1. Write a guids. h file and declare the guid of the component and interface in guids. h.

// Declare component guid {A433E701-E45E-11d3-97B5-52544CBA7F28}
// Define_guid (clsid_timelogserver,
// 0xa433e701, 0xe45e, 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 }};
// Declare an interface guid {A433E702-E45E-11d3-97B5-52544CBA7F28}
// Define_guid (iid_itimelog,
// 0xa433e702, 0xe45e, 0x11d3, 0x97, 0xb5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28 );
Static const IID iid_itimelog =
{0xa433e702, 0xe45e, 0x11d3, {0x97, 0xb5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28 }};

2. Write an itimelogserver. h and declare the components and interfaces in the itimelogserver. h file.

// Itimelogserver. h
# Include "; guids. H ";
// Interface itimelog Declaration
Declare_interface _ (itimelog, iunknown)
{
Stdmethod (outputlog) (BSTR * varlogtext) pure;
};

Note:

1.macro define_guidcan be associated with progidof the group and interface. It can be generated using the guidgen.exe tool.

2. Macro declare_interface _ declares the interface. The first parameter of the macro is the interface name, and the second parameter is the base class of the interface. The declare_interface macro is used to declare interfaces without the base class.

3. the macro stdmethod declares the methods in the interface. the return value of this method is hresult. pure is interpreted as "; = 0";, that is, this method is a pure virtual function. when the return value of a method is not hresult, use the macro stdmethod _ (return type, function name) (parameter) pure;

Ii. Declare component class ctimelogserver and implement interface nesting class

Add the ctimelogserver class to classwizard, and set the base class to csf-target. Modify the header file timelogserver1.h, and add # include "; itimelogserver. H";. Add the class declaration

// Declare the nested class that implements the itimelog Interface
Begin_interface_part (timelog, itimelog) // automatically declare three methods of the iunknown Interface
Stdmethod (outputlog) (BSTR * varlogtext );
End_interface_part (timelog)
// Declare interface ing
Declare_interface_map ()
// Declaration Factory
Declare_olecreate (ctimelogserver)

  3. Implement class factory and interface ing

Write in the ctimelogserver implementation file:

// Implementation Factory
Implement_olecreate (ctimelogserver, "; timelogserver ";,
0xa433e701, 0xe45e, 0x11d3, 0x97, 0xb5, 0x52, 0x54, 0x4c, 0xba, 0x7f, 0x28 );
// Map the interface to the corresponding nested class
Begin_interface_map (ctimelogserver, c1_target)
Interface_part (ctimelogserver, iid_itimelog, timelog)
End_interface_map ()

  4. Global Object count in Component Construction and destructor

Ctimelogserver: ctimelogserver ()
{
: Afxolelockapp ();
}

Ctimelogserver ::~ Ctimelogserver ()
{
: Afxoleunlockapp ();
}

  5. Implement the iunknown interface for nested classes

// Implement the 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 );
}

Note: although the cshorttarget class has implemented the iunknown interface, the iunknown interface of the nested class must be mapped to the iunknown interface supported by cshorttarget. the two parameters of the method_prologueh macro are the classes that implement component objects and the nested classes that implement interfaces.

6. Methods for implementing the itimelog interface outputlog

Note that the function of this component is to input logs into the log file.

1. Add a file pointer to the component class:

// Attributes
Public:
Protected:
File * m_logfile;

2. initialize and exit

First, perform some initialization in the melogserver constructor:

Ctimelogserver: ctimelogserver ()
{
: Afxolelockapp ();
Ctime timestamp = ctime: getcurrenttime ();
Cstring filename;
Filename. Format (_ T ("; % S. log";), timestamp. Format ("; % Y % m % d ";));
M_logfile = fopen (filename, _ T ("; ";));
If (m_logfile)
{
Fprintf (m_logfile, _ T (";##################/N ";));
Fprintf (m_logfile, _ T ("; started at: % s";), (lpctstr) timestamp. format ("; % Y % m month % d % H: % m % s ";));
Fprintf (m_logfile, _ T (";/N ";));
}
}
// 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 ("; ended at: % s";), (lpctstr) timestamp. format ("; % Y % m month % d % H: % m % s ";));
Fprintf (m_logfile, _ T (";/N ";));
Fprintf (m_logfile, _ T (";##################/N ";));
Fclose (m_logfile );
}
}

3. Implement the interface itimelog Method

// Implement the 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 % m month % d % H: % m: % s ";);
Cstring logtext (lpcwstr) * varlogtext );
Fprintf (pthis->; m_logfile, ";/n % s/n %";, nowtime, logtext );
Return noerror;
}
Else
{
Afxmessagebox ("; no log file! ";);
Return s_false;
}
}

  7. Complete component servers

Process instance () and exitinstance () in the Implementation file of ctimelogserverapp ()

Bool ctimelogserverapp: initinstance ()
{
: Afxolelockapp ();
// Register all OLE server (factories) as running. This enables
// 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 customer Program

Key steps for using the COM component Server Client program are: Initialize the com library, create a component object, obtain the iunknown interface pointer, query the interface, use it, and release the component.

# Include "; itimelogserver. H ";
// Initialize the com library and instantiate the component
Hresult;
Iunknown * piunknown;
Hresult =: coinitialize (null );
If (failed (hresult ))
{
: Afxmessagebox ("; com library cannot be initialized! ";);
Return false;
}

// Create a component instance
Piunknown = NULL;
Hresult =: cocreateinstance (clsid_timelogserver, null,
Clsctx_inproc_server, iid_iunknown, (void **) &; piunknown );
If (failed (hresult ))
{
Piunknown = NULL;
: Afxmessagebox ("; timelog object cannot be created! ";);
Return false;
}
// Query the interface and use
If (piunknown! = NULL)
{
Itimelog * pitimelog;
Hresult = piunknown->; QueryInterface (iid_itimelog, (void **) &; pitimelog );
If (failed (hresult ))
{
: Afxmessagebox ("; the interface itimelog cannot be obtained! ";);
Piunknown->; release ();
Return;
}
BSTR bstrlogtext;
Bstrlogtext = m_logtext.allocsysstring ();
Cstring text (lpcwstr) bstrlogtext );
: Afxmessagebox (text );

If (failed (pitimelog->; outputlog (&; bstrlogtext )))
{
: Afxmessagebox ("; log output error! ";);
Pitimelog->; release ();
Return;
}
Pitimelog->; release ();
: Afxmessagebox ("; the log has been written! ";);
}
// Release the component
Piunknown->; release ();
Piunknown = NULL;
: Couninitialize ();

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.