返回> 网站首页
COM接入点使用方法 - 将控件封装到DLL动态库里
yoours2012-02-23 22:12:29
简介一边听听音乐,一边写写文章。
将控件封装到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};
文章评论
1648人参与,0条评论