The strange thing happened. I have just compiled the program and do it correctly. I don't seem to call once _Module.init (), and later deleted the code, it should not be the role of this code, because I have re-established a project and wrote a client code again, and the result is still Correct, and ATL Internal book also mentioned that QueryInterface is implemented in the template class. After reading a lot of posts, I feel that I can't finish it. Now summarize the client implementation method of the connection point, I hope to help beginners.
I don't say the principle of the connection point, many posts say it is very clear, search for "Connection Point Principle" on the forum. I just said that the template class with ATL in the MFC is implemented, because this method is more simple than using the most original method, don't use the functions in the IDispatch interface, especially the Invoke function (more troublesome) . 1. Use the #import instruction to import the DLL server you use, which automatically generates information such as interface description and interface ID, example: #import "f: / vc exercise / 0504tl/debug/050104atl.dll" Raw_Interfaces_only, no_namespace, named_guids Place it in stdafx.h. 2, add the insert in the ATL Support Select menu in the MFC - "Insert an ATL object, confirm that add ATL support, do not have to add an ATL object, because you don't need it. 3, construct your event receiver class. Code is as follows //EventSink.hclass CEventSink: public IDispEventImpl <1, CEventSink, & DIID__ISpeakEvents, & LIBID_MY050104ATLLib, 1, 0> {public: CEventSink () {} public: BEGIN_SINK_MAP (CEventSink) SINK_ENTRY_EX (1, DIID__ISpeakEvents, 1, OnSay) END_SINK_MAP ( ) void __stdcall OnSay (long aVal);}; // EventSink.cpp # include "stdafx.h" #include "EventSink.h" void __stdcall CEventSink :: OnSay (long aVal) {AfxMessageBox ( "called by Event from dll Server ! ");} This has completed the work of the event receiver class, then establishing a connection to establish a connection to deliver the IUNKNOWN pointer of the receiver class to the source object IUNKNOWN * PUNK; HRESULT HR = m_dispatch-> queryinterface (IID_IUNKNOWN (void **); if (successted (HR)) {peventsink-> dispeventadvise (PUNK);} m_dispatch is a common member variable I created in the MFC dialog class to save the server's automation interface pointer Use it to find the iUnknown pointer to pass to the source object. At this point, the receiver can work. Disconnect connection and establishment connection similar: iUnknown * punk; hResult hr = m_dispatch-> queryinterface (IID_IUNKNOWN, (void **) & punk); if (succeededed (hr)) {peventsink-> dispeventunadvise (punk);
Written by primitive methods, the more trouble, but clear thinking, both in their own hands class CMy050104COMClientDlg: public CDialog {// Constructionpublic: CMy050104COMClientDlg (CWnd * pParent = NULL); // standard constructor // Dialog Data // {{AFX_DATA (CMY050104comClientDLG) ENUM {IDD = IDD_MY050104comclient_dialog}; longog}; long m_roal; long m_say; //}} AFX_DATA
// ClassWizard generated virtual function overrides // {{AFX_VIRTUAL (CMy050104COMClientDlg) protected: virtual void DoDataExchange (CDataExchange * pDX); // DDX / DDV support //}} AFX_VIRTUAL
// ImplementationProtace: hicon m_hicon;
// Generated message map functions // {{AFX_MSG (CMy050104COMClientDlg) virtual BOOL OnInitDialog (); afx_msg void OnSysCommand (UINT nID, LPARAM lParam); afx_msg void OnPaint (); afx_msg HCURSOR OnQueryDragIcon (); afx_msg void OnButton1 (); afx_msg void OnButton2 (); afx_msg void OnButton3 (); afx_msg void OnButton4 (); afx_msg void OnButton5 (); //}} aFX_MSG DECLARE_MESSAGE_MAP () public: DWORD m_dwCookie; LPDISPATCH m_Dispatch; // Added By YYHe 2005-1-4 16:48:58 // declare_interface_map () // What is this macro action? Here goes BEGIN_INTERFACE_PART (EventSink, IDispatch) INIT_INTERFACE_PART (CMy050104COMClientDlg, EventSink) STDMETHOD (GetTypeInfoCount) (unsigned int *); STDMETHOD (GetTypeInfo) (UINT, LCID, ITypeInfo **); STDMETHOD (GetIDsOfNames) (REFIID, LPOLESTR *, UINT, LCID, DISPID *); STDMETHOD (Invoke) (Dispid, Refiid, LCID, Word, Disprams *, Variant *, EXCEPINFO *, UINT *); END_INTERFACE_PART (Eventsink)
Int onConnection (); int ondisconnection ();} Implementation section: Void cmy050104comclientdlg :: Onbutton4 () // Establish connection {if (onConnection ()! = 1) {AFXMESSAGEBOX ("Connection Failed!");}}
STDMETHODIMP_ (ULONG) CMy050104COMClientDlg :: XEventSink :: AddRef () {return 1;} STDMETHODIMP_ (ULONG) CMy050104COMClientDlg :: XEventSink :: Release () {return 0;} STDMETHODIMP CMy050104COMClientDlg :: XEventSink :: QueryInterface (REFIID iid, LPVOID * ppvObj) {METHOD_PROLOGUE_EX_ (CMy050104COMClientDlg, EventSink) if (IsEqualIID (iid, IID_IUnknown) || IsEqualIID (iid, IID_IDispatch) || IsEqualIID (iid, DIID__ISpeakEvents)) {* ppvObj = this; AddRef (); return S_OK;} else { return E_NOINTERFACE;}} STDMETHODIMP CMy050104COMClientDlg :: XEventSink :: GetTypeInfoCount (unsigned int *) {return E_NOTIMPL;} STDMETHODIMP CMy050104COMClientDlg :: XEventSink :: GetTypeInfo (UINT, LCID, ITypeInfo **) {return E_NOTIMPL;} STDMETHODIMP CMy050104COMClientDlg :: XEventSink :: GetIDsOfNames (REFIID, LPOLESTR *, UINT, LCID, DISPID *) {return E_NOTIMPL;} STDMETHODIMP CMy050104COMClientDlg :: XEventSink :: Invoke (DISPID DispID, REFIID, LCID, WORD, DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT * ) {AFXMESSAGEBOX ("Event Occoured!"); Trace ("/ N IDSPID =% D / N", DISPID); Return S_OK;
}
int CMy050104COMClientDlg :: OnConnection () {BOOL RetVal = 0; if (m_dwCookie = 0!) {return 2;} LPCONNECTIONPOINTCONTAINER pConnPtCont = NULL;! if ((m_Dispatch = NULL) && (SUCCEEDED (m_Dispatch-> QueryInterface (IID_IConnectionPointContainer, ( void **) & pConnPtCont)))) {ASSERT (pConnPtCont = NULL);! LPCONNECTIONPOINT pConnPt = NULL; DWORD dwCookie;! if (SUCCEEDED (pConnPtCont-> FindConnectionPoint (DIID__ISpeakEvents, & pConnPt))) {ASSERT (pConnPt = NULL); PCONNPT-> Advise (& M_XEventsink, & DWCOOKIE); RETVAL = 1; PConnpt-> Release ();} PConnptCont-> Release (); m_dwcookie = dwcookie;}
return RetVal;} int CMy050104COMClientDlg :: OnDisConnection () {BOOL RetVal = 0; if (m_dwCookie == 0) {return 2;} LPCONNECTIONPOINTCONTAINER pConnPtCont = NULL;! if ((m_Dispatch = NULL) && (SUCCEEDED (m_Dispatch-> QueryInterface (IID_IConnectionPointContainer, (void **) & pConnPtCont)))) {ASSERT (pConnPtCont = NULL);! LPCONNECTIONPOINT pConnPt = NULL; DWORD dwCookie; if (SUCCEEDED (pConnPtCont-> FindConnectionPoint (DIID__ISpeakEvents, & pConnPt))) {ASSERT (pConnPt! = NULL); PConnpt-> Unadvise (m_dwcookie); m_dwcookie = 0; retval = 1; PConnpt-> Release (); PConnptCont-> release ();
}
Return RetVal;
Void cmy050104comclientdlg :: OnButton5 () {= 1) {AFXMESSAGEBOX ("Disconnection Failed!");}}