【目的】:创建两 DLL,使两 DLL 能互发消息
【工具】:VS2005
【步骤简介】:
1、创建 MFC APPLICATION 工程 Message
2、创建 MFC DLL 工程 Common
3、再创建两 ATL SIMPLE 工程 Sender 和 Receiver。如下图。
【Wizard】:
1、Common工程选择自动化
2、Sender和Receiver都选上两附加选项:
【属性设置】:
1、输出:
我把输出文件都放在bin目录下,源文件发在src目录下。VS在生成Message工程后,关闭工程,然后再Message文件夹下新建src文件夹,将Message、Message.sln等文件(夹)移入src。再创建common、sender、receiver工程。
生成文件都输出到bin文件夹
2、特殊设置
将类型库放入lib
【代码】:
1、message调用sender接口启动消息的发送
#import "../../bin/Sender.dll" no_namespace
void CMessageDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
try
{
ISendMsgPtr pSender;
HRESULT hr = pSender.CreateInstance(__uuidof(SendMsg));
if(SUCCEEDED(hr))
{
pSender->Start();
}
}
catch(...)
{
}
}
2、common.idl 为 common.dll 声明 IAdapter 接口
// Common.idl : Common.dll 的类型库源
// 此文件将由 MIDL 编译器处理以产生
// 类型库 (Common.tlb)。
[ uuid(7520BCC4-AA02-4037-9E27-9141FACD3BD6), version(1.0) ]
library Common
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
object,
uuid(8FDED875-8019-4c79-9EB6-A9A4C412A91D),
dual,
nonextensible,
helpstring("IAdapter 接口"),
pointer_default(unique)
]
interface IAdapter : IDispatch{
[id(1), helpstring("方法Attach")] HRESULT Attach([in] IDispatch* pDispatch);
[id(2), helpstring("方法Detach")] HRESULT Detach();
[id(3), helpstring("方法OnMsg")] HRESULT OnMsg([in] BSTR bstrMsg);
};
};
3、Sender 头文件
//导入依赖库文件
#import "../../lib/Common.tlb"no_namespace raw_interfaces_only named_guids
#import "../../lib/Receiver.tlb"no_namespace raw_interfaces_only named_guids
// CSendMsg
class ATL_NO_VTABLE CSendMsg :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CSendMsg, &CLSID_SendMsg>,
public IDispatchImpl<ISendMsg, &IID_ISendMsg, &LIBID_SenderLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IDispatchImpl<IAdapter, &__uuidof(IAdapter), &LIBID_SenderLib>//继承 IAdapter
{
public:
CSendMsg()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_SENDMSG)
BEGIN_COM_MAP(CSendMsg)
COM_INTERFACE_ENTRY(ISendMsg)
//COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IAdapter) //暴露接口
COM_INTERFACE_ENTRY2(IDispatch, IAdapter)//暴露接口
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
protected:
CComPtr<IReceiveMsg> m_pAgent;
void CreateAgent();
public:
STDMETHOD(Start)(void); //供message调用的方法
STDMETHODIMP Attach(IDispatch* pDispatch);//实现IAdapter接口方法
STDMETHODIMP Detach(); //实现IAdapter接口方法
STDMETHODIMP OnMsg(BSTR bstrMsg); //实现IAdapter接口方法
};
OBJECT_ENTRY_AUTO(__uuidof(SendMsg), CSendMsg)
sender实现文件:
STDMETHODIMP CSendMsg::Start(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加实现代码
CreateAgent();
if(m_pAgent)
{
BSTR bstrMsg = _com_util::ConvertStringToBSTR("来自 Sender 的消息!");
m_pAgent->OnMsg(bstrMsg);
SysFreeString(bstrMsg);
}
return S_OK;
}
STDMETHODIMP CSendMsg::Attach(IDispatch* pDispatch)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
return S_OK;
}
STDMETHODIMP CSendMsg::Detach()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
return S_OK;
}
//消息发送与接收
STDMETHODIMP CSendMsg::OnMsg(BSTR bstrMsg)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
char *pszMsg = _com_util::ConvertBSTRToString(bstrMsg);
if( IDOK == MessageBox(AfxGetApp()->GetMainWnd()->m_hWnd, CString(pszMsg), _T("Sender Box"), MB_OKCANCEL))
{
BSTR bstrMsg = _com_util::ConvertStringToBSTR("来自 Sender 的消息!");
m_pAgent->OnMsg(bstrMsg);//发送消息
SysFreeString(bstrMsg);
}
delete []pszMsg;
return S_OK;
}
//创建与receiver的联系
void CSendMsg::CreateAgent()
{
if(m_pAgent != NULL)
return;
try{
HRESULT hr = CoCreateInstance(__uuidof(ReceiveMsg), NULL,\
CLSCTX_INPROC, __uuidof(IReceiveMsg), (LPVOID *)&m_pAgent);
if(SUCCEEDED(hr))
{
m_pAgent->Attach((IDispatch*)(IReceiveMsg*)this);
}
}
catch(...)
{
}
}
4、receiver的头文件部分代码,receiver自身只要提供以下三个方法并实现就可以了:
#import "../../lib/Common.tlb"no_namespace raw_interfaces_only named_guids
STDMETHOD(Attach)(IDispatch* pDispatch); //自身提供的方法
STDMETHOD(Detach)(void); //自身提供的方法
STDMETHOD(OnMsg)(BSTR bstrMsg); //自身提供的方法
receiver的实现:
STDMETHODIMP CReceiveMsg::Attach(IDispatch* pDispatch)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加实现代码
try
{
if(pDispatch == NULL)
{
return S_FALSE;
}
/*
在 Sender 中,创建 IReceiveMsg 接口,并调用 CReceiveMsg::Attach, 将 Sender 接口
pDispatch 传进来,在CReceiveMsg::Attach中查询 IAdapterPtr 接口,赋给 m_pAdapter
*/
IAdapterPtr pAdapter;
HRESULT hr = pDispatch->QueryInterface(__uuidof(IAdapter), (void **)&pAdapter);
if(SUCCEEDED(hr))
{
m_pAdapter = pAdapter;
}
}
catch(...)
{
}
return S_OK;
}
STDMETHODIMP CReceiveMsg::Detach(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加实现代码
return S_OK;
}
STDMETHODIMP CReceiveMsg::OnMsg(BSTR bstrMsg)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加实现代码
char *pszMsg = _com_util::ConvertBSTRToString(bstrMsg);
if( IDOK == MessageBox(AfxGetApp()->GetMainWnd()->m_hWnd, CString(pszMsg), _T("Receiver Box"), MB_OKCANCEL))
{
BSTR bstrMsg = _com_util::ConvertStringToBSTR("来自 Receiver 的消息!");
m_pAdapter->OnMsg(bstrMsg);
SysFreeString(bstrMsg);
}
delete []pszMsg;
return S_OK;
}
【效果】: