zoukankan      html  css  js  c++  java
  • 借助模板类自动实现COM连接点接收器(Sink)更新

    之前在借助模板类自动实现COM连接点接收器(Sink)中对原作者的代码进一步封装,弄清了连接点使用的原理,在看ATL代码的过程中,发现ATL本身就提供了AtlAdvise/AtlUnadvise这样的机制来简化连接点的使用,CComPtrBase中也有Advise这个成员函数,它是对AtlAdvise,进一步封装,因此,对ConnectionHelper的代码可以再简化,简化后Connect()只有十来行了。原作者写的GetConnectPoint函数也用不上了。

    #if !defined( __sinkimpl_h_INCLUDED__ )
    #define __sinkimpl_h_INCLUDED__ 
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    
    template<typename T, typename EventInterface, const GUID * evtLibID = NULL >
    class ATL_NO_VTABLE CSinkImpT
    	: public CComObjectRootEx<CComSingleThreadModel>
    	, public CComCoClass<CSinkImpT<T, EventInterface, evtLibID>, &__uuidof(T)>
    	, public IDispatchImpl < EventInterface, &__uuidof(EventInterface), evtLibID >
    {
    public:
    	CSinkImpT() {}
    	virtual ~CSinkImpT() {}
    
    	typedef IDispatchImpl<EventInterface, &__uuidof(EventInterface), evtLibID> _parentClass;
    	typedef CSinkImpT<T, EventInterface, evtLibID> _thisClass;
    
    	STDMETHOD( Invoke )(DISPID dispidMember, REFIID riid,
    						 LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
    						 EXCEPINFO* pexcepinfo, UINT* puArgErr)
    	{
    		T * pThis = static_cast<T *>(this);
    		return pThis->DoInvoke( dispidMember, riid,
    								lcid, wFlags, pdispparams, pvarResult,
    								pexcepinfo, puArgErr );
    	}
    
    	DECLARE_NO_REGISTRY()
    
    	DECLARE_PROTECT_FINAL_CONSTRUCT()
    
    	BEGIN_COM_MAP( _thisClass )
    		COM_INTERFACE_ENTRY( IDispatch )
    		COM_INTERFACE_ENTRY( EventInterface )
    	END_COM_MAP();
    
    	STDMETHOD( DoInvoke )(DISPID dispidMember, REFIID riid,
    						   LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
    						   EXCEPINFO* pexcepinfo, UINT* puArgErr)
    	{
    		return _parentClass::Invoke( dispidMember, riid,
    									 lcid, wFlags, pdispparams, pvarResult,
    									 pexcepinfo, puArgErr );
    	}
    };
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    // ComDllLib::ITestComPtr pCom;
    // HRESULT hr = pCom.CreateInstance( L"Test.Com" );
    // ConnectionPointHelper<ComDllLib::ITestCom, ComDllLib::_ITestComEvent, CSink3> cph( pCom );
    //
    template<typename EventInterface, typename EventProcessor>
    class ConnectionPointHelper
    {
    	CComPtr<IUnknown> m_spInterface;
    	DWORD m_dwCookie;
    public:
    	ConnectionPointHelper( IUnknown* pInterface ) : m_spInterface( pInterface ), m_dwCookie( 0 ) { Connect(); }
    	~ConnectionPointHelper() { Disconnect(); }
    protected:
    	void Connect()
    	{
    		HRESULT hr = E_FAIL;
    		do
    		{
    			if ( m_spInterface == NULL || m_dwCookie != 0 ) { break; }
    
    			CComObject<EventProcessor> * pTmp = NULL;
    			hr = CComObject<EventProcessor>::CreateInstance( &pTmp );
    			if ( FAILED( hr ) ){ break; }
    
    			CComQIPtr<IUnknown, &IID_IUnknown> spSink( pTmp );
    
    			hr = m_spInterface.Advise( spSink, __uuidof(EventInterface), &m_dwCookie );
    
    		} while ( FALSE );
    	}
    
    	void Disconnect()
    	{
    		HRESULT hr = E_FAIL;
    		do {
    			if ( m_dwCookie == 0 ) { break; }
    
    			AtlUnadvise( m_spInterface, __uuidof(EventInterface), m_dwCookie );
    			m_dwCookie = 0;
    
    		} while ( FALSE );
    	}
    
    };
    #endif // !defined( __sinkimpl_h_INCLUDED__ )
    

      以上就是全部代码,减少到不到100行。

    使用方法:

    		{ // .tlh中的接口方式调用
    			ComDllLib::ITestComPtr pCom;
    			CComPtr<IUnknown> pUnknown;
    			HRESULT hr = pCom.CreateInstance( L"Test.Com" );
    			if ( SUCCEEDED( hr ) )
    			{
    				hr = pCom->QueryInterface( IID_IUnknown, reinterpret_cast<void**>(&pUnknown) );
    				if ( SUCCEEDED( hr ) )
    				{
    					ConnectionPointHelper<ComDllLib::_ITestComEvent, CSink3> cph( pUnknown );
    					LONG c = pCom->Add( 1, 5 );
    				}
    			}
    		}
    

      

    		{ // IDispatch方式调用
    			CComPtr<IDispatch> spDisp;
    			HRESULT hr = spDisp.CoCreateInstance( L"Test.Com" );
    			if ( SUCCEEDED( hr ) )
    			{
    				CComQIPtr<IUnknown, &IID_IUnknown> spUnknown( spDisp );
    				ConnectionPointHelper<ComDllLib::_ITestComEvent, CSink3> cph( spUnknown );
    				_variant_t ret;
    				_variant_t m = 2, n = 3;
    				spDisp.Invoke2( (LPCOLESTR) L"Add", &m, &n, &ret );
    			}
    		}
    

      

  • 相关阅读:
    Linux中$含义
    Linux文本处理之grep
    MySQL8.0.15的安装与配置---win10
    Jenkins实现自动运行jmeter脚本
    Hystrix初识
    Feign初始
    AS的Gradle下载不成功
    Linux安装一些软件
    OAuth2初识
    IDEA无法打开等奇异问题终极解决方法
  • 原文地址:https://www.cnblogs.com/honker/p/3778288.html
Copyright © 2011-2022 走看看