Analysis and introduction of COM connection point events based on VC _c language

Source: Internet
Author: User

A typical scenario in COM is to have the client object instantiate the server object and then invoke the objects. However, without a special mechanism, these server objects will be difficult to turn to and callback to client objects. COM Connection points provide this special mechanism to achieve two-way communication between the server and the client. With connection points, the server can invoke clients when certain events occur on the server.

The principle of the following diagram:

With a connection point, the server can specify the event that it can raise by defining an interface. When an event is raised on the server, the client to take action registers itself with the server. The client then provides an implementation of the interface defined by the server.

Clients can register themselves with the server through a number of standard mechanisms. COM provides a iconnectionpointcontainer and IConnectionPoint interface for this purpose.

The client of a COM connection point server can be written in C + + and C # managed code. The C + + client registers an instance of a class that provides an implementation of the sink interface. A managed client registers a delegate for a single event, thus creating a single sink per event notification method, referring to the interop portions of C #.

One, the connection point program writes
1, use ATL to establish component programs.
2, add ATL simple OBJECT, support connection point events.
Note: If there is no current connection point event, you can add it manually in the. idl file. Like what

Copy Code code as follows:

[
UUID (57CCB7A5-F3B6-4990-91CD-33A82E1AAA46),
helpstring ("Ifunevent dispinterface")
]
dispinterface _ifunevent
{
Properties
Event interface does not have any properties
Methods
[ID (1), helpstring ("Method Onresult")] HRESULT Onresult ([out,retval] long* retval);
[ID (2), helpstring ("Method Ontype")] HRESULT Ontype ([in] LONG ntype);
}

3, because the connection point event is supported, this will automatically generate a _xxxevent source interface. We add the method that we want to trigger.
4, select the event object under the Component, Pop-up dialog box select Add Method. You can continue to add multiple methods ...
5, the implementation method (in fact, the component is only to make the declaration of methods, the customer calls to implement these methods). When implemented, select the component/class, press the right button, and select Implement Connection in the pop-up menu ....
will produce cproxy_xxxevent classes, which have the implementation of the fire function, are automatically generated.
6. Complete the other interface functions of the component.
The component's connection point writing is relatively simple, the key is how to realize the event listening and receiving in the client. It is easy to implement under. Net. But in VC more cumbersome.
Second, the connection point client implementation (VC)
1, including the "Project _i.h" header file, the introduction of the "project. tlb" Ole library file. Like what:
#include "atldemo_i.h"
#import "Atldemo.tlb" Named_guids raw_interfaces_only
2. Create a class: derived from _ixxxevent. (XXX is the actual event name)
Implement the various virtual function overloads of the class, if the _ixxxevent is IUnkown interface only need overload QueryInterface, ADDREF, release functions; if _ Ixxxevent is a two-way interface that requires overloading to implement IUnkown interface three functions and IDispatch interface four functions.
Implements the event function, through the function, realizes the event by the Sink_entry_info the mapping, the Invoke function inside realizes (through the event ID) One of three methods realizes.
Using Sink_entry_info to implement the mapping of events
Such as:
Copy Code code as follows:

Begin_sink_map (Ceventsink)
Sink_entry_info (1,diid__inew01events,dispid_msg,msg,&msginfo)
End_sink_map ()

I've defined an MSF function in the component, so I'm insinuate it here. Then implement the Msg method.
3. How to call
3.1 Use engineering support COM, use AfxOleInit or Coinitialize/un CoInitialize
3.2 Get Component interface
3.3 Get connection point container, find connection point.
3.4 Use advise to pass a listener object to the component so that the event responds when the event occurs. Disconnect the connection point event through Unadvise when not in use. It also uses Afxconnectionadvice to pass the listener object to the component interface.
3.5 Release resources.
The specific code is as follows:
Copy Code code as follows:

#pragma once

#include "atldemo_i.h"
#import "Atldemo.tlb" Named_guids raw_interfaces_only

Class Cskin:public _ifunevent
{
Public
Cskin (void);
~cskin (void);
Private
DWORD M_dwrefcount;
Public
STDMETHODIMP Fire_ontype (LONG ntype)
{
CString strtemp;
Strtemp.format (_t ("The result is%d"), ntype);
AfxMessageBox (strtemp);
return S_OK;;
}
HRESULT stdmethodcalltype QueryInterface (Refiid iid, void **ppvobject)
{
if (iid = = diid__ifunevent)
{
m_dwrefcount++;
*ppvobject = (void *) this;
return S_OK;
}

if (iid = = IID_IUnknown)
{
m_dwrefcount++;
*ppvobject = (void *) this;
return S_OK;
}

return e_nointerface;
}
ULONG Stdmethodcalltype AddRef ()
{
m_dwrefcount++;
return m_dwrefcount;
}

ULONG Stdmethodcalltype release ()
{
ULONG l;

L = m_dwrefcount--;

if (0 = m_dwrefcount)
{
Delete this;
}

return l;
}

HRESULT Stdmethodcalltype GetTypeInfoCount (
/* [out] */__rpc__out UINT *pctinfo)
{
return S_OK;
}

HRESULT Stdmethodcalltype GetTypeInfo (
/* [in] * * UINT itinfo,
/* [in] */LCID LCID,
/* [out] */__rpc__deref_out_opt ITypeInfo **pptinfo)
{
return S_OK;
}

HRESULT Stdmethodcalltype GetIDsOfNames (
/* [in] * * __rpc__in REFIID riid,
/* [Size_is][in] * * __rpc__in_ecount_full (cnames) lpolestr *rgsznames,
/* [Range][in] * * UINT cnames,
/* [in] */LCID LCID,
* [Size_is][out] * * __rpc__out_ecount_full (cnames) DISPID *rgdispid)
{
return S_OK;
}

/* [Local] */HRESULT stdmethodcalltype Invoke (
/* [in] * * DISPID Dispidmember,
/* [in] * * REFIID riid,
/* [in] */LCID LCID,
/* [in] * wflags WORD,
/* [Out][in] * * Dispparams *pdispparams,
/* [out] */VARIANT *pvarresult,
/* [out] * * Excepinfo *pexcepinfo,
/* [out] */UINT *puargerr)
{
Switch (dispidmember)///According to different dispidmember, complete the different callback functions, the ID number of the event function
{
Case 2:
{
1st param: [in] long lValue.
VARIANT Varlvalue;
Long lValue = 0;
VariantInit (&varlvalue);
VariantClear (&varlvalue);
Varlvalue = (Pdispparams->rgvarg) [0];
LValue = V_I4 (&varlvalue);
Fire_ontype (LValue);
}
Break
Default:break;
}

return S_OK;
}
};

#include "StdAfx.h"
#include "Skin.h"

Cskin::cskin (void)
{
M_dwrefcount = 0;
}

Cskin::~cskin (void)
{
}

Implementation section:
Copy Code code as follows:

CoInitialize (NULL);

Ccomptr<ifun> Pfun;
HRESULT hr = pfun.cocreateinstance (clsid_fun);
if (HR!=S_OK)
{
return;
}

IConnectionPointContainer *PCPC;
hr = Pfun->queryinterface (IID_IConnectionPointContainer, (void * *) &AMP;PCPC);
if (! SUCCEEDED (HR))
{
return;
}
IConnectionPoint *PCP;
hr = Pcpc->findconnectionpoint (DIID__IFUNEVENT,&AMP;PCP);
if (! SUCCEEDED (HR))
{
return;
}
Pcpc->release ();

IUnknown *psinkunk;
Cskin *psink = new Cskin ();
hr = Psink->queryinterface (IID_IUnknown, (void * *) &psinkunk);
DWORD dwadvise;
hr = Pcp->advise (psinkunk,&dwadvise);//sink associated with connection point

LONG c = 0;
Pfun->add (1,5,&AMP;C);
Pcp->unadvise (dwadvise)//Disconnect point Event
Pcp->release ();
Pfun.release ();

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.