ATL 连接点例子(atlduck)
2011-07-16 20:44 Clingingboy 阅读(2257) 评论(0) 编辑 收藏 举报
一.客户端获取连接点IConnectionPoint
LRESULT CMyDlg::OnCreateDoDuck(WORD wNotifyCode, WORD wID, HWND hwndCtl, BOOL& bHandled)
{
HRESULT hr;
IUnknown* pUnk = NULL;
IConnectionPointContainer* pConnPtContainer = NULL;
hr = CoCreateInstance(CLSID_DuckDoer, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pUnk);
if (!SUCCEEDED(hr))
{
::MessageBox(m_hWnd, _T("Could not create DuckDoer object. Make sure the server is registered."),
_T("Object Instantiation Error."), MB_OK | MB_ICONINFORMATION);
return 0L;
}
ATLENSURE(pUnk != NULL);
hr = pUnk->QueryInterface(IID_IConnectionPointContainer, (void**)&pConnPtContainer);
ATLENSURE(SUCCEEDED(hr) && pConnPtContainer != NULL);
hr = pConnPtContainer->FindConnectionPoint(IID_IDuckInt, &m_pIDuckConnectionPoint);
ATLENSURE(SUCCEEDED(hr) && m_pIDuckConnectionPoint != NULL);
ATLENSURE(m_pDuckInt != NULL);
pUnk->Release();
pConnPtContainer->Release();
return 0L;
}
二.服务器和客户端都是一个exe,所以此时服务器会开启一个窗体
class CAtlDuckModule : public CAtlExeModuleT< CAtlDuckModule >
{
public:
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_Atlduck, "{120B7294-65BF-11D0-9DDC-00A0C9034892}")
DECLARE_LIBID(LIBID_ATLDUCKLib)
HRESULT PreMessageLoop(int nShowCmd)
{
_ASSERT(CDuckDoer::m_pDlg == NULL);
CDuckDoer::m_pDlg = new CDuckDoerDlg();
CDuckDoer::m_pDlg->Create(NULL);
CDuckDoer::m_pDlg->ShowWindow(SW_SHOWNORMAL);
_ASSERT(CDuckDoer::m_pDlg != NULL);
HRESULT hr = CAtlExeModuleT<CAtlDuckModule>::PreMessageLoop(nShowCmd);
if (FAILED(hr))
return hr;
return S_OK;
}
};
三.客户端发送服务端一个接收器(调用Advise)
LRESULT CMyDlg::OnAdvise(WORD , WORD wID, HWND , BOOL& )
{
HRESULT hr;
ATLENSURE(m_pIDuckConnectionPoint != NULL);
hr = m_pIDuckConnectionPoint->Advise((IUnknown*)m_pDuckInt, &m_dwCookie);
return 0;
}
四.服务器端将此接收器存放起来
STDMETHODIMP CDuckDoer::Advise(IUnknown* pUnk, DWORD* pdwCookie)
{
if (!m_bLocked) // lock the server on the first advise received
{
((IDuckDoer*)this)->AddRef();
m_bLocked = TRUE;
}
HRESULT hr = CProxyIDuckInt<CDuckDoer>::Advise(pUnk, pdwCookie);
if (SUCCEEDED(hr))
{
…
}
return hr;
}
细节在CProxyIDuckInt<CDuckDoer>::Advise内部
五.服务器端通知客户端
LRESULT CDuckDoerDlg::OnQuack(WORD , WORD , HWND , BOOL& )
{
USES_CONVERSION;
TCHAR szWhosCalling[100];
_tcscpy_s(szWhosCalling, 100, _T("Server Quacking for Sink No. XX."));
CComBSTR szOut(szWhosCalling);
m_pObject->Fire_Quack(szOut);
return 1;
}
Fire_Quack代码可以自动生成,客户端必须有一个类实现了IDuckInt接口(就是通过调用Advise传入的接口)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现