返回> 网站首页 

COM接入点使用方法 - 将控件封装到DLL动态库里

yoours2012-02-23 22:12:29 阅读 1393

简介一边听听音乐,一边写写文章。

      将控件封装到DLL动态库里面,本代码已做修改。
      由于要将控件封装到DLL动态库里,还要使用原有的接口和事件,查到可以使用COM接入点来实现。
      该实例是将控件封装到win32的动态库工程,脱离MFC。

 一、头文件:
#ifdef MYDLL32_EXPORTS
#define MYDLL32_API __declspec(dllexport)
#else
#define MYDLL32_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

MYDLL32_API BOOL Init();
MYDLL32_API BOOL Connection();
MYDLL32_API void Test();
MYDLL32_API void Close();
MYDLL32_API void Release();

#ifdef __cplusplus
}
#endif

二、cpp文件
#include "MyDLLApi.h"
// 必须以这种形式导入,生成 .tlh文件
#import "xxxx_yy.dll" raw_interfaces_only, raw_native_types, no_namespace, named_guids

//用以记录组件对象IUnknown接口指针 
Ixxxx_yy* ixxxx_yy;
// 该类是事件类,主要用于事件响应
class CSink : _Ixxxx_yyEvents
{
    private:
    DWORD       m_dwRefCount;
    public:

CSink::CSink() {m_dwRefCount = 0;}
CSink::~CSink() {}

void OnSend(long c, long st)
{
}
void OnRec(long addr, long t, short Value)
{
}

HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
    {
        m_dwRefCount++;
        *ppvObject = (void *)this;
        return S_OK;
    };

ULONG STDMETHODCALLTYPE AddRef()
    {
        m_dwRefCount++;
        return m_dwRefCount;
    };
    
ULONG STDMETHODCALLTYPE Release()
    {
        ULONG l;
        l  = m_dwRefCount--;
        if ( 0 == m_dwRefCount)
        {
            delete this;
        }
        return m_dwRefCount;
    };

HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pI)
{
return E_NOTIMPL;
};

HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID  riid, 
OLECHAR FAR* FAR*  rgszNames, 
unsigned int  cNames, 
LCID   lcid,
DISPID FAR*  rgDispId)       
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTinfo, LCID lcid, ITypeInfo FAR **ppTIinfo)
{
return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE Invoke(DISPID  dispIdMember, 
REFIID  riid, 
LCID  lcid, 
WORD  wFlags,
DISPPARAMS FAR*  pDispParams, 
VARIANT FAR*  pVarResult,
EXCEPINFO FAR*  pExcepInfo,
unsigned int FAR*  puArgErr)
{
HRESULT hr = S_OK;
if(pDispParams)
{
// 对于不同的响应事件,调用该分支
switch (dispIdMember)
{
case 0x01:
//InvokeHelper(0x1, DISPATCH_METHOD, VT_EMPTY, NULL, parms, c, st);
   // 参数为倒叙索引
OnSend(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0].lVal);
break;
case 0x02:
//InvokeHelper(0x2, DISPATCH_METHOD, VT_EMPTY, NULL, parms, addr, t, Value);
 // 参数为倒叙索引
OnRec(pDispParams->rgvarg[2].lVal, pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0].iVal);
break;
default:
return E_NOTIMPL;
}
}
return E_NOTIMPL;
}
};

// 连接,断开,退出COM连接点
CSink* m_xEventSink;

//记录组件对象
IConnectionPointContainer* pConnPtCont;
//接口指针 
//记录连接点接口指针 
IConnectionPoint* pConnPt;
DWORD m_dwCookie;//记录连接标识

//byte[]转VARIANT
VARIANT FormatByteArray(byte *Data, int len)
{
VARIANT Var_Data;
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound;

Var_Data.vt=VT_UI1|VT_ARRAY;
rgsabound.lLbound=0;
rgsabound.cElements=len;
if   (psa= SafeArrayCreate(VT_UI1,1,&rgsabound))
{
memcpy(psa->pvData,Data,len);
Var_Data.parray=psa;
}
else
{
VariantInit(&Var_Data);
}
return Var_Data;
}


#ifdef __cplusplus
extern "C" {
#endif
MYDLL32_API BOOL Init()
{
HRESULT hResult; 

hResult = ::CoInitialize(NULL); 
if(FAILED(hResult)) 
//MessageBox(L"不能初始化COM库!"); 
return FALSE; 

ixxxx_yy = NULL; 
hResult = ::CoCreateInstance(CLSID_xxxx_yy, NULL, CLSCTX_ALL, IID_Ixxxx_yy, (void**)&ixxxx_yy); 
if(hResult != S_OK) 
ixxxx_yy = NULL; 
//MessageBox(L"不能创建ConnObject对象!"); 
return FALSE; 

m_dwCookie = 0;//预置连接标识为0
return TRUE;
}

//连接
MYDLL32_API BOOL Connection()
{
if(m_dwCookie!=0) 
return TRUE; 

if(ixxxx_yy!=NULL) 
HRESULT hResult; 
hResult = ixxxx_yy->QueryInterface(IID_IConnectionPointContainer, (void**)&pConnPtCont); 
if(FAILED(hResult)) 
//MessageBox(L"不能获取对象的IConnectionPointContainer接口!"); 
return FALSE; 

//ASSERT(pConnPtCont!=NULL); 
hResult = pConnPtCont->FindConnectionPoint(DIID__Ixxxx_yyEvents, &pConnPt); 
if(FAILED(hResult)) 
pConnPtCont->Release(); 
//MessageBox(L"不能获取对象的IEventSink连接点接口!"); 
return FALSE; 

//ASSERT(pConnPt!=NULL); 
//获取事件接收器指针 
IUnknown* pIEventSink = NULL;

m_xEventSink = new CSink();
m_xEventSink->QueryInterface(IID_IDispatch,(void**)&pIEventSink);
//通过连接点接口的Advise方法将事件接收器指针传给可连接对象 
if(SUCCEEDED(pConnPt->Advise(pIEventSink,&m_dwCookie))) 
//MessageBox(L"与可连接对象ConnObject建立连接成功!");
return TRUE;
else 
//MessageBox(L"不能与ConnObject建立连接!"); 
return FALSE;
}

return TRUE;
}

//断开
MYDLL32_API void Close()
{ if(m_dwCookie==0) 
return; 

pConnPt->Unadvise(m_dwCookie); 
pConnPt->Release(); 
pConnPtCont->Release(); 
m_dwCookie = 0; 
}

//在退出应用时
MYDLL32_API void Release()
{
// TODO: Add your control notification handler code here
ixxxx_yy->Release(); 
::CoUninitialize(); 
}

MYDLL32_API void Test()
{
// TODO: Add your control notification handler code here
ixxxx_yy->put_CapVersion(CP::P22);
ixxxx_yy->put_Type(TType::G2);
ixxxx_yy->put_Packet(1);

short st;
ixxxx_yy->get_Size(&st);


byte k[] = {0x00,0xF0,0x10,0x03};
VARIANT packet = FormatByteArray(k, 4);
VARIANT_BOOL bl;
ixxxx_yy->FData(&packet, &bl);

VARIANT pPacket;
ixxxx_yy->GetVersion(&pPacket);
}
#ifdef __cplusplus
}
#endif

三、.tlh文件

struct __declspec(uuid("11111111111111111111111"))
Ixxxx_yy : IDispatch
{
。。。。。。
// 这里都是方法
}

对于事件的获得,可以通过加入mfc控件后产生的文件来得到。
最关键的是文件末尾部分:
extern "C" const GUID __declspec(selectany) LIBID_xxxx_yydll =
    {11111111111}};
extern "C" const GUID __declspec(selectany) DIID__Ixxxx_yyEvents =
    {11111111111};
extern "C" const GUID __declspec(selectany) CLSID_xxxx_yy =
    {1111111111111};
extern "C" const GUID __declspec(selectany) IID_Ixxxx_yy =
    {111111111111};


微信小程序扫码登陆

文章评论

1393人参与,0条评论