连接点问题的一点心得

奇怪的事情发生了。我刚才编译了程序,执行正确了。记得好像是调用了一次_Module.Init(),后来又删除掉了了那段代码,应该不是这段代码起的作用,因为我重新建立了一个项目,又写了一遍客户端代码,结果仍然正确,而且ATL Internal 一书中也提到了QueryInterface在模板类中实现了。看了好多这方面的帖子,感觉都说的不彻底,不能看完就能自己实现。现在总结一下连接点的客户端实现方法,希望给初学者帮上忙。

我就不说连接点的原理了,很多帖子说的很清楚,在论坛上搜索“连接点 原理”就可以找到。
我就说一下用在mfc中用ATL的模板类来实现,因为这个方法比用最原是的方法来实现简单的多,不用自己去实现IDispatch接口中的函数,尤其是Invoke函数(比较麻烦)。
1、用#import指令导入你用到的dll服务器,它会自动生成接口说明和接口ID等信息,例子:
#import "F:/vc练习/050104ATL/Debug/050104ATL.dll" raw_interfaces_only, no_namespace, named_guids
把它放在StdAfx.h里面。
2、在MFC中添加ATL支持
  选择菜单中的插入-》插入ATL对象,确认添加ATL支持之后,不用真的添加一个ATL对象,因为用不着。
3、构造自己的事件接收器类。代码如下
//EventSink.h
class  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 !");
}
这样就已经完成了事件接收器类的工作,接着就是建立连接了
建立连接目的就是把接收器类的IUnknown指针传递给源对象
         IUnknown *pUnk ;
 HRESULT hr = m_Dispatch->QueryInterface(IID_IUnknown,(void**)&pUnk);
 if (SUCCEEDED(hr) )
 { 
  pEventSink->DispEventAdvise(pUnk); 
 }
m_Dispatch是我在MFC对话框类中建立的一个共有成员变量,用来保存服务器的自动化接口指针,用它来查找到IUnknown指针,传递给源对象。至此,接收器就可以工作了。断开连接与建立连接相似:
 IUnknown *pUnk ;
 HRESULT hr = m_Dispatch->QueryInterface(IID_IUnknown,(void**)&pUnk);
 if (SUCCEEDED(hr) )
 { 
  pEventSink->DispEventUnadvise(pUnk); 
 }




用原始的方法写,则比较麻烦,不过思路清晰,都在自己的掌握之中
class CMy050104COMClientDlg : public CDialog
{
// Construction
public:
 CMy050104COMClientDlg(CWnd* pParent = NULL); // standard constructor

// Dialog Data
 //{{AFX_DATA(CMy050104COMClientDlg)
 enum { IDD = IDD_MY050104COMCLIENT_DIALOG };
 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

// Implementation
protected:
 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 Y.Y.He   2005-1-4  16:48:58
 
// DECLARE_INTERFACE_MAP()  //看看这个宏得作用是什么?这里不用
 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,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
 END_INTERFACE_PART(EventSink)

    int OnConnection();
 int OnDisConnection();
}
实现部分:
void CMy050104COMClientDlg::OnButton4() //建立连接
{
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()
{
if (OnDisConnection() != 1)
{
 AfxMessageBox("DisConnection Failed !");

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值