Realization of connected objects and receivers in 12.ATL

Source: Internet
Author: User
Tags define function uuid

Similar to the implementation of the previously described IDispatch, it is much easier to implement a connected object than the Mfc,atl, and it is done by using MIDL compilation to write IDL.

Here we use ATL to implement a Speek component object that can be spoken through the Ispeek interface, according to the size of the decibel that is communicated to the client via a junction point.


1. Implementing a Connected Object

To create an ATL project, right-click Add Class, select ATL Simple Object,

After filling out the component naming, the following:


Then choose to implement the connection point for the current interface, as follows:


Tick the connection point, and then we write IDL as follows, specifically refer to the ATL implementation com article.

Import "Oaidl.idl"; import "Ocidl.idl"; [Object,uuid (554A2800-7862-43EC-9DE6-799CB11AF71B), dual,nonextensible,helpstring ("ISpeek interface"), Pointer_default ( Unique)]interface Ispeek:idispatch{[id (1), helpstring ("Method Speek")] HRESULT Speek ([in] LONG nvolume);}; [UUID (163A45FC-1B75-4328-85CA-CFFDBD7A3F5C), version (1.0), helpstring ("Atlconnectpoint 1.0 Type library")]library Atlconnectpointlib{importlib ("Stdole2.tlb"); [ UUID (e44310a3-b5fb-4f97-afb2-a69287993c23), helpstring ("_ispeekevents interface")]dispinterface _ispeekevents{properties : Methods:[id (1), helpstring ("Method Onwhispter")]void onwhistper ([in] LONG nvolume); [ID (2), helpstring ("Method Ontalk")]void Ontalk ([in] LONG nvolume);}; [UUID (A7588351-c619-41fa-aeb8-8c92a814b9ea), helpstring ("Speek Class")]coclass Speek{[default] interface ispeek;[ Default, source] dispinterface _ispeekevents;};};
can see that

The component object generated here is Speek, note that it is preceded by an identity [Default,source], which identifies the default source interface

Ispeek interface Since we have checked the dual interface, we derive from Idisptach,

The generated connection point is _ispeekevents, where we specify the corresponding method Onwhisper and Ontalk IDs are 1 and 2 respectively, note that the type is dispinterface

Click Compile,

The resulting Component object is defined as follows:

Class atl_no_vtable Cspeek:p ublic ccomobjectrootex<ccomsinglethreadmodel>,public CComCoClass<CSpeek, & Clsid_speek>,public Iconnectionpointcontainerimpl<cspeek>,public Cproxy_ispeekevents<cspeek> Public Idispatchimpl<ispeek, &iid_ispeek, &libid_atlconnectpointlib,/*wmajor =*/1,/*wMinor =*/0>
which

IConnectionPointContainerImpl implements the connection point container

IDispatchImpl implements the interface Ispeek

The cproxy_ispeekevents implements the corresponding connection point


View the Interface mapping table and connection point mapping table as follows:

Begin_com_map (Cspeek) com_interface_entry (Ispeek) com_interface_entry (IDispatch) com_interface_entry ( IConnectionPointContainer) End_com_map () Begin_connection_point_map (Cspeek) Connection_point_entry (__uuidof (_ ispeekevents)) End_connection_point_map ()
The interfaces and connection points are managed separately in the corresponding container.


We see the cproxy_ispeekevents implementation in the auto-generated _ispeekevents_cp.h file as follows:

#pragma oncetemplate<class t>class cproxy_ispeekevents:p ublic iconnectionpointimpl<t, &__uuidof (_ ispeekevents) >{public:hresult Fire_ontalk (LONG nvolume) {HRESULT hr = S_OK; T * pThis = static_cast<t *> (this); int cconnections = M_vec. GetSize (); for (int iconnection = 0; iconnection < cconnections; iconnection++) {Pthis->lock (); Ccomptr<iunknown> punkconnection = M_vec. GetAt (iconnection);p this->unlock () IDispatch * pconnection = Static_cast<idispatch *> (PUNKCONNECTION.P); if (pconnection) {ccomvariant Avarparams[1];avarparams[0] = NVOLUME;AVARPARAMS[0].VT = Vt_i4;dispparams params = {avarParams, NULL, 1, 0} ; hr = Pconnection->invoke (2, Iid_null, locale_user_default, dispatch_method,¶ms, NULL, NULL, NULL);}} return HR;} HRESULT Fire_onwhistper (LONG Nvolume) {HRESULT hr = S_OK; T * pThis = static_cast<t *> (this); int cconnections = M_vec. GetSize (); for (int iconnection = 0; iconnection < cconnections; iconnection++) {Pthis->lock (); Ccomptr<iunknown> punkconnection = M_vec. GetAt (iconnection);p this->unlock () IDispatch * pconnection = Static_cast<idispatch *> (PUNKCONNECTION.P); if (pconnection) {ccomvariant Avarparams[1];avarparams[0] = NVOLUME;AVARPARAMS[0].VT = Vt_i4;dispparams params = {avarParams, NULL, 1, 0} ; hr = Pconnection->invoke (1, Iid_null, locale_user_default, dispatch_method,¶ms, NULL, NULL, NULL);}} return hr;}};
As you can see, the actual specific connection point implementation is IConnectionPointImpl,

The Fire_ontalk and Fire_onwhistper are automatically generated here to inform the customer to perform the corresponding operation separately.



All we need to do is implement the Ispeek interface , notifying the client of the incoming voice size callback, as follows:

STDMETHODIMP Cspeek::speek (LONG nvolume) {if (Nvolume <= 200)//Speak softly {fire_onwhistper (nvolume);} else//speak loudly {fire_ontalk (nvolume);} return S_OK;}

Isn't it very simple?


2. Implement the Receiver

The implementation of the receiver in ATL is generally implemented using IDispEventSimpleImpl, which is actually the idisptach of another look-up table implementation, its principle and MFC Dispatch_map very similar , but this is called SINK_ MAP.

Here I make it a generic template class that can be applied directly, as follows:

Define the event source, which you can specify, to keep different event sources different. Multiple event sources, this distinguishes the typeinfostatic _atl_func of the different disp IDs of different event sources by defining a # define Source_id_speek1class cdispeventhandlerbase{public:// _info onwhisperinfo;static _atl_func_info ontalkinfo;}; Template <class t>class cdispeventhandler:public cdispeventhandlerbase, public idispeventsimpleimpl<source_ Id_speek, T, &__uuidof (_ispeekevents) >{public://define different source of events DISP idstatic const int speek_disp_id_whisper= 1; The static const int speek_disp_id_talk= 2;//defines a handler function for different DISP IDs for different event sources, and the corresponding function void Stdmethodcalltype onwhisper must be implemented in the subclass (LONG Nvolume) {t* PT = static_cast<t*> (this); return Pt->onwhisper (Nvolume);} void Stdmethodcalltype ontalk (LONG nvolume) {t* PT = static_cast<t*> (this); return Pt->ontalk (Nvolume);} Define event handler mapping table Begin_sink_map (T) sink_entry_info (Source_id_speek, __uuidof (_ispeekevents), Speek_disp_id_whisper, Onwhisper, &onwhisperinfo) sink_entry_info (Source_id_speek, __uuidof (_ispeekevents), SPEEK_DISP_ID_TALK,OnTalk , &ontalkinfo) End_sink_map ()};__declspec (SELectany) _atl_func_info cdispeventhandlerbase::onwhisperinfo= {cc_stdcall, vt_empty, 1, {VT_I4}};__declspec ( Selectany) _atl_func_info cdispeventhandlerbase::ontalkinfo= {cc_stdcall, vt_empty, 1, {VT_I4}};

You only need to define function calling conventions, return types, parameter types in Cdispeventhandlerbase, and add corresponding handler functions to the event handler mapping table.


3. Connect and Disconnect

Here we inherit the Cdispeventhandler class in the main dialog box, as follows:

Class Cmaindlg:public Cdialogimpl<cmaindlg>, public cdispeventhandler<cmaindlg>


This allows us to simplify the connection and disconnection operations with IDispEventSimpleImpl, as follows:

BOOL Connectsource () {HRESULT hr;hr = CoCreateInstance (__uuidof (Speek), NULL, Clsctx_inproc_server, __uuidof (Ispeek), ( lpvoid*) &m_pspeek); if (FAILED (HR) &&!m_pspeek) {return FALSE;} hr = Cdispeventhandler::D ispeventadvise (M_pspeek, &__uuidof (_ispeekevents)), if (FAILED (HR)) {return FALSE;} return TRUE;} BOOL Disconnectsource () {HRESULT hr = E_FAIL;HR = Cdispeventhandler::D ispeventunadvise (M_pspeek, &__uuidof (_ ispeekevents)); if (FAILED (HR)) {return FALSE;} if (M_pspeek && succeeded (M_pspeek->release ())) {M_pspeek = Null;return TRUE;} return FALSE;}
When connecting and disconnecting, only one source object's interface and the interface IID to be connected can be used.


Well, the rest of us need to do is very simple, to implement the source object notification when the customer needs to do something , here the box prompt, as follows:

The/**************************** receiver implements **********************************/void Stdmethodcalltype OnWhisper (LONG Nvolume) {CString Csstrinfo;csstrinfo.format (l "whisper, Decibel:%d", Nvolume);:: MessageBox (NULL, Csstrinfo, L "notification", MB_OK);} void Stdmethodcalltype ontalk (LONG nvolume) {CString Csstrinfo;csstrinfo.format (L "yelling, decibel:%d", Nvolume);:: MessageBox (NULL, Csstrinfo, L "notice", MB_OK);}

ATL implements the Connection object and connection point method download link

Original, reprint please indicate from http://blog.csdn.net/wenzhou1219

Realization of connected objects and receivers in 12.ATL

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.