1. 新建项目
这里我们使用ATL,来接受C# COM控件向外发送的事件。
2. 初始化ATL
#include "stdafx.h" CComModule _module; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { _module.Init(NULL, hModule);//初始化 } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: { _module.Term();//释放 } break; } return TRUE; }
3. 定义一个显示UI的接口类
IShowUI.h
#ifdef DLL_SHOW_UI #define DLL_CLASS _declspec(dllimport) #else #define DLL_CLASS _declspec(dllexport) #endif #ifndef _ISHOW_UI_H_ #define _ISHOW_UI_H_ #include <functional> #include <atlconv.h> using std::function; class DLL_CLASS IShowUI { protected: IShowUI(); virtual ~IShowUI(); public: static IShowUI* CreateInstance(); static void DestoryInstance(IShowUI* pIShowUI); public: virtual void SetCallback(function<void(BSTR)>* pCallback) = 0; virtual void ShowDialog(BSTR bstrDialogType, BSTR bstrParam) = 0; }; #endif
IShowUI.cpp
#include "IShowUI.h" #include "ShowUIImpl.h" IShowUI::IShowUI() { } IShowUI::~IShowUI() { } IShowUI* IShowUI::CreateInstance() { IShowUI* pIShowUI = new CShowUIImpl; return pIShowUI; } void IShowUI::DestoryInstance(IShowUI* pIShowUI) { if (pIShowUI) { delete pIShowUI; } }
4. 定义一个显示UI的实现类
ShowUIImpl.h
#ifndef _SHOW_UI_IMPL_H_ #define _SHOW_UI_IMPL_H_ #include "IShowUI.h" #ifdef _DEBUG #import "../NetActiveX/bin/Debug/NetActiveX.tlb" #else #import "../NetActiveX/bin/Release/NetActiveX.tlb" #endif class CHandleEvent; class CShowUIImpl : public IShowUI { public: CShowUIImpl(); virtual ~CShowUIImpl(); public: virtual void SetCallback(function<void(BSTR)>* pCallback); virtual void ShowDialog(BSTR bstrDialogType, BSTR bstrParam); private: function<void(BSTR)>* m_pCallback; CHandleEvent* m_pHandleEvent; NetActiveX::IShowDialogPtr m_showDialogPtr; }; #endif
ShowUIImpl.cpp
#include "stdafx.h" #include "IShowUI.h" #include "ShowUIImpl.h" #include "SystemString.h" #include <atlcom.h> //处理C# COM控件发送的事件 class CHandleEvent : public IDispEventImpl<0, CHandleEvent, &(__uuidof(NetActiveX::IEvent)), &(__uuidof(NetActiveX::__NetActiveX)), 1, 0> { public: CHandleEvent() { m_pCallback = NULL; } void SetEventCallback(std::function<void(BSTR)>* pCallback) { m_pCallback = pCallback; } STDMETHOD(NotifyEvent)(BSTR bstr) { if (m_pCallback) { (*m_pCallback)(bstr); } return S_OK; } BEGIN_SINK_MAP(CHandleEvent) SINK_ENTRY_EX(0, (__uuidof(NetActiveX::IEvent)), 20, NotifyEvent)//事件处理函数,此处的事件ID=20必须和C# NotifyEvent定义的完全一样 END_SINK_MAP() private: function<void(BSTR)>* m_pCallback;//事件处理回调函数 }; CShowUIImpl::CShowUIImpl() { CoInitialize(NULL); m_pCallback = NULL; m_pHandleEvent = new CHandleEvent; m_showDialogPtr = NetActiveX::IShowDialogPtr(__uuidof(NetActiveX::ShowDialogImpl)); } CShowUIImpl::~CShowUIImpl() { delete m_pHandleEvent; m_pHandleEvent = NULL; CoUninitialize(); } void CShowUIImpl::SetCallback(function<void(BSTR)>* pCallback) { m_pCallback = pCallback; } void CShowUIImpl::ShowDialog(BSTR bstrDialogType, BSTR bstrParam) { if (m_showDialogPtr.GetInterfacePtr()) { CSystemString strDialogType(bstrDialogType); CSystemString strParam(bstrParam); m_pHandleEvent->SetEventCallback(m_pCallback);//设置事件处理回调函数 m_pHandleEvent->DispEventAdvise(m_showDialogPtr);//注册事件 m_showDialogPtr->ShowDialog(strDialogType.GetBSTR(), strParam.GetBSTR()); m_pHandleEvent->DispEventUnadvise(m_showDialogPtr);//取消事件 } }
5. 其他辅助类
SystemString.h
#ifndef _SYSTEM_STRING_H_ #define _SYSTEM_STRING_H_ class CSystemString { public: explicit CSystemString(BSTR bstr) { if (bstr) { m_bstr = SysAllocString(bstr); } else { m_bstr = NULL; } } ~CSystemString() { Clear(); } void Clear() { if (m_bstr) { SysFreeString(m_bstr); m_bstr = NULL; } } BSTR GetBSTR() {return m_bstr;} private: CSystemString(CSystemString&); CSystemString& operator =(CSystemString&); private: BSTR m_bstr; }; #endif
6. 新建一个C++ win32控制台应用程序,调用DLL显示C#对话框
#include "stdafx.h" #include <string> #include <functional> #define DLL_SHOW_UI #include "IShowUI.h" using std::string; using std::wstring; #pragma comment(lib, "DllInterface.lib") class EmployeeData { public: void ParseString(wstring s) { int beg = -1; int end = -1; beg = 0; end = s.find(L",", beg); if (end != -1) { m_name = s.substr(beg, end - beg); beg = end + 1; } end = s.find(L",", beg); if (end != -1) { m_sex = s.substr(beg, end - beg); beg = end + 1; } end = s.find(L",", beg); if (end != -1) { m_age = _wtoi(s.substr(beg, end - beg).c_str()); beg = end + 1; } end = s.find(L",", beg); if (end != -1) { m_phone = s.substr(beg, end - beg); beg = end + 1; } end = s.length(); if (beg < end) { m_mobile = s.substr(beg, end - beg); } } wstring ToString() { wstring s = L""; wchar_t psz[32] = {0}; s += m_name; s = s + L"," + m_sex; s = s + L"," + _itow(m_age, psz, 10); s = s + L"," + m_phone; s = s + L"," + m_mobile; return s; } wstring m_name; wstring m_sex; int m_age; wstring m_phone; wstring m_mobile; }; void Callback(BSTR bstr) { EmployeeData employee; employee.ParseString(bstr); } int _tmain(int argc, _TCHAR* argv[]) { IShowUI* pShowUI = IShowUI::CreateInstance(); EmployeeData employee; function<void(BSTR)> call = std::bind(&Callback, std::tr1::placeholders::_1); employee.m_name = L"123"; employee.m_sex = L"男"; employee.m_age = 10; employee.m_phone = L"123456"; employee.m_mobile = L"13245678952"; BSTR bstr = L"EmployeeDialog"; wstring s = employee.ToString(); BSTR bstrParam = (BSTR)s.c_str(); pShowUI->SetCallback(&call);//设置事件响应回调 pShowUI->ShowDialog(bstr, bstrParam);//显示员工属性对话框 IShowUI::DestoryInstance(pShowUI); pShowUI = NULL; return 0; }