Receive COM events in the VC ++ program

zhaozj2021-02-17  34

Receive COM events in the VC program

Keywords: connection point COM event idispeventImpl

Receiving event is a very important function in the COM client. However, in addition to the events issued by the control [1] in the MFC, VC cannot automatically generate the code for receiving events. In order to receive an event of a general COM, you must write the code for receiving events yourself. This article explains how to write a code to receive COM events through ATL in a VC program. Of course, the program itself does not have to be an ATL project.

1 COM event principle

The COM object enables the function of sending events through the connection point. Each connection point specifies an interface for receiving events, while the client receives an event by implementing this interface.

As shown in the figure below, assume that the connection point of the COM object A requires the event receiving object to implement the IEventSink interface, the entire event receiving process is this: First, the client creates a COM object A and an event for receiving COM object A event receiving object B. Next, the client program receives the event receiving interface IEventsink for the event receiving interface of the COM object B. Then, COM object A can send events to the client via this interface.

Currently, most of the connection points require sending events through the IDispatch interface, ATL automatically generated connection points and controls created by MFC and VB are passed through the IdisPatch interface. Although consistent event receiving interfaces can be generated via IDispatch, it is more complicated due to the difficulties of the IDispatch interface.

The example in this article simplifies the encoding of the event receiving object via the IdispeventIMPL template of the ATL. At the same time, the examples in this article also illustrate how the functions of using ATL in non-ATL projects.

2 use ATL to implement the connection point

Receiving events must implement a dedicated COM object, which is also the most difficult place. Moreover, many connection points require passage through the IdisPatch interface, which has caused greater difficulties.

In accordance with the steps, explain how to write code to receive events sent through the IDispatch interface in a normal application.

2.1 Add ATL header file

Before using ATL, you must include the following file: atlbase.h and atlcom.h, and define _module variables [2]. Add the following code to stdafx.h is the most convenient:

#include

EXTERN CCOMMODULE _MODULE;

#include

The _module is defined in the CPP file. as follows:

CCOMMODULE _MODULE;

After adding these two lines, we can use ATL's features. Don't create an ATL project.

Of course, if the project is generated by the ATL project wizard, you don't have to add a header file again.

2.2 ATL initialization

Before using the ATL, you must initialize it, and then terminate the ATL after use.

For console programs, the method of initializing the ATL is:

Int Main (int Argc, char * argv [], char ** ENV)

{

_Module.init (NULL, (Hinstance) getModuleHandle (NULL));

...

If it is a Windows program or a dynamic connection library, use the incoming Instance handle to initialize.

Int Winmain (Hinstance Hinstance,

Hinstance Hprevinstance,

LPSTR LPCMDLINE,

INT ncmdshow)

{

_Module.init (NULL, HINSTANCE);

...

Terminate ATL Use the following methods:

_Module.Term ();

Initializing ATL must be performed before any ATL operation, and termination must be done after all ATL operations. 2.3 Event Receiver

2.3.1 Introducing a COM object

For convenience, this example uses #import to introduce COM classes, or other ways to introduce COM objects, but other code should be modified.

#import "[COM or TLB path]" named_guids, no_namespace

Note that a named_guids property must be added. Otherwise, # import will not generate the GUID definition of the TLB class.

2.3.2 Event Acceptor Class

A. Class definition

The event receiver is a class that inherits from IdispeventImpl. IDispeventimpl is a template in ATL, dedicated to events for receiving the IDispatch interface. Idispeventimpl's definition is:

Class IDispeventimpl

{

}

NID can be set to 0, T is the name of the event receiver class, and PDIID is the GUID of the event interface. Plibid is the pointer of the type library GUID, and Majorver and Minorver are the primary, secondary version number, TIHClass is a class for handling TLB. TIHCLASS can use the default value.

The code for the event receiver class is as follows:

Class EventReceiver:

Public IdispeventImpl <0,

EventReceiver,

& DIID__ConnectPointInterface,

& Libid_xxxlib, 1, 0>

{

...

}

B. Event response function

For each event to be responded, you should add a corresponding event response function in the event response class. The name of the event response function can be selected by himself, but the parameters and return values ​​must be consistent with the definition of the COM object.

The event response function is a standard interface method, and StdMethod and STDMETHODIMP declarations should be used.

In this example, we receive an event with a plastic parameter. First, add a function definition in the event response class:

Class EventReceiver: Public ...

{

...

PUBLIC:

StdMethod (EventNotify) (INT i);

...

}

Then add the specific event response code:

STDMETHODIMP EventReceiver :: EventNotify (INT i)

{

Printf ("EventReceiver:% D / N", I);

Return S_OK;

}

C. Event correspondence table

The event response class To define the event corresponding table, indicating which function responds to which event. The event correspondence table is implemented by three macros, which is: begin_sink_map, sink_entry_ex, end_sink_map.

Begin_sink_map has a parameter and is the name of the event reception class. SINK_ENTRY_EX has four parameters, named NID, DIID, EventID, and FuncName. NID is 0, DIID is the GUID of the event interface, EventID is the event number, and FuncName is the name of the response function.

The event response table in the following code declares that the event number is 1 event responded through the EventNotify function. You can write multiple Sink_Entry_ex to respond to multiple events.

Class EventReceiver: Public ...

{

...

PUBLIC:

Begin_SINK_MAP (EventReceiver)

SINK_ENTRY_EX (0, DIID__ICONNECTIONPOINTTESTOBJEVENTS, 1, EventNotify) end_sink_map ()

...

}

2.4 Connection objects and close connections

After the event connection class is complete, it is accessible to the specific COM object to receive events. IDispeventIMPL is connected to the COM object via the DispeventAdvise method. DispeventAdvise uses the COM object pointer to which you want to connect as a parameter. Before connecting, you must be a instance of the event reception class, the code is as follows:

EventReceiver * Preceiver = New EventReceiver;

Preceiver-> Dispeventadvise (POBJ);

If you don't need to receive an event, you should use the Dispeventunadvise function to close the connection, the code is as follows:

Preceiver-> Dispeventunadvise (POBJ);

3 instance

The instance of this article can send an email to Nelsonc@Online.sh.cn. The example contains a console program that sends event COM objects and reception events. And compile operations in Virtual Studio 6.0 SP5 Platform SDK.

[1] The control is a special COM object.

[2] Variable name must be _Module

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

New Post(0)