zoukankan      html  css  js  c++  java
  • C++调用C#之C++DLL调用C# COM控件

    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;
    }
    



     

  • 相关阅读:
    技术学习之分析思想
    测试类的必要性
    Webstorm配置运行React Native
    React Native
    npm太慢, 淘宝npm镜像使用方法
    数据库设计那些事儿
    Linux 安装nodejs
    Java
    解决 vmware workstations 14 开启虚拟机黑屏
    编程与盖楼的思考
  • 原文地址:https://www.cnblogs.com/dongc/p/5225115.html
Copyright © 2011-2022 走看看