【ATL/DLL】VS2005 互发消息

【目的】:创建两 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;
}

【效果】:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值