Compile COM connection point events in VC

Source: Internet
Author: User

 

Compile COM connection point events in VC

 

A typical solution in COM is to let the client object instantiate the server object and then call these objects. However, without a special mechanism, it is difficult for these server objects to redirect and callback to client objects. The COM connection point provides this special mechanism to implement bidirectional communication between the server and the client. Using the connection point, the server can call the client when some events occur on the server.

Principles include:

With the connection point, the server can define an interface to specify the events it can trigger. When an event is triggered on the server, the client to perform the operation will register with the server. Then, the client provides the implementation of the interface defined by the server.

The client can register with the server through some standard mechanisms. Com provides iconnectionpointcontainer and iconnectionpoint interfaces for this purpose.

The COM connection point Server Client can be written using C ++ and C # managed code. The C ++ client registers an instance of the class, which provides the implementation of the receiver interface. The hosting client registers a single event Delegate and creates a single receiver based on each event notification method. For details, refer to the interoperability section of C.

 

I. Programming of connection points

1. Use ATL to create a component program.

2. Add ATL simple object and support connection point events.

NOTE: If there is no current connection point event, you can manually add it in the. IDL file. For example

[

UUID (57ccb7a5-f3b6-4990-91cd-33a82e1aaa46 ),

Helpstring ("ifunevent dispinterface ")

]

Dispinterface _ ifunevent

{

Properties:

// The Event interface does not have any attributes

Methods:

[ID (1), helpstring ("method onresult")] hresult onresult ([out, retval] Long * retval );

[ID (2), helpstring ("method ONTYPE")] hresult ONTYPE ([in] Long ntype );

}

3. Because connection point events are supported, A _ xxxevent source interface is automatically generated. We add the method to be triggered.

4. Select the event object under the component. In the displayed dialog box, select Add method. You can add more methods...

5. Implementation Method (in fact, the component only declares the method, which is implemented only when the customer calls it ). Select components/classes, right-click them, and select implement connection... in the pop-up menu ....

The cproxy_xxxevent class is generated automatically. The fire function is implemented in the class.

6. Complete other interface functions of the component.

The connection points of components are easy to write. The key is how to monitor and receive events on the client. It is easy to implement in. net. But it is complicated in VC.

 

2. Connect to the client (VC)

1. Include the header file "_ I. H" and introduce the "Project. TLB" Ole library file. For example:

# Include "atldemo_ I .h"

# Import "atldemo. TLB" named_guids raw_interfaces_only

2. Create a class: Derived from _ ixxxevent. (Xxx indicates the actual event name)

Overload each virtual function of the implementation class. If _ ixxxevent is an iunkown interface, you only need to overload the QueryInterface, addref, and release functions; if _ ixxxevent is a bidirectional interface, you need to reload the three functions of the iunkown interface and the four functions of the idispatch interface.

Implement the event function by using the function, using sink_entry_info to implement event ing, and using the event ID in the invoke function.

 

Event ing using sink_entry_info

For example:

Begin_sink_map (ceventsink)

Sink_entry_info (1, diid _ inew01events, dispid_msg, MSG, & msginfo)

End_sink_map ()

I have defined an MSF function in the component, so the message is hashed here. Then implement the MSG method.

3. How to call

3.1 Use Project Support COM and afxoleinit or coinitialize/UN coinitialize

3.2 obtain the Component Interface

3.3 get the connection point container and find the connection point.

3.4 use advise to send a listening object to the component, so that the event will respond when the event occurs. When not in use, unadvise is used to disconnect the connection point event. Afxconnectionadvice is also used to send the listening object to the component interface.

3.5 release resources.

The Code is 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,

/* [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,

/* [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,

/* [In] */word wflags,

/* [Out] [in] */dispparams * pdispparams,

/* [Out] */variant * pvarresult,

/* [Out] */partition info * ppartition info,

/* [Out] */uint * puargerr)

{

Switch (dispidmember) // based on different dispidmember, complete different callback functions and ID numbers of the event Functions

{

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:

Coinitialize (null );

 

Ccomptr <ifun> pfun;

Hresult hR = pfun. cocreateinstance (clsid_fun );

If (HR! = S_ OK)

{

Return;

}

 

Iconnectionpointcontainer * pcpc;

HR = pfun-> QueryInterface (iid_iconnectionpointcontainer, (void **) & pcpc );

If (! Succeeded (HR ))

{

Return;

}

Iconnectionpoint * PCP;

HR = pcpc-> findconnectionpoint (diid _ ifunevent, & 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); // the receiver is associated with the connection point

 

Long C = 0;

Pfun-> Add (1, 5, & C );

// PCP-> unadvise (dwadvise) // disconnect the connection point event

PCP-> release ();

Pfun. Release ();

 

Couninitialize ();

 

References:

COM connection points by Alex C. punnen:

Http://www.codeproject.com/KB/COM/connectionpoint.aspx

COM Component Design and Application

Http://www.vckbase.com/document/viewdoc? Id = 1525

Code for compiling and calling COM connection points in VC

Http://download.csdn.net/source/3437607

 

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.