COM技術入門(2)
1.IDispatch的簡介與作用
a) 自動化技術讓解釋下語音能夠調用到自定義的接口,
b) 具有自動化功能的組件是支持IDispatch接口的COM組件
c) IDispatch能夠接收一個函數的字符串名稱,並執行這個函數.
d) 解釋性語言要調用COM組件的自定義接口都是通過自動化控制
程序把自定義接口中的函數的字符串和參數傳遞給IDispatch
而IDispatch間接的執行自定義接口中的函數.
e) 重要的函數 GetIDsOfNames和Invoke
GetIDsOfNames函數將讀取一個函數名稱,並返回其調用ID,
Invoke函數接收一個調度ID,跟函數參數,執行調用ID所對應函數功能.
f) 所以解釋下語音跟宏語音不必直接認識我們的自定義接口,
只要我們的COM組件支持了IDispatch接口,他們就能通過自動化控制
程序調用我們的IDispatch接口,通過傳入函數名字的字符串
和函數參數來執行調用我們的自定義接口.
2.常用的COM數據類型
a)基本類型
CHAR typedef char CHAR CHAR* char指針
BYTE 無符號的char BYTE*
SHORT typedef short SHORT SHORT*
USHORT 無符號short USHORT*
INT typedef int INT*
UINT 無符號int UINT*
LONG typedef long LONG*
ULONG 無符號long ULONG*
FLOAT FLOAT*
DOUBLE DOUBLE*
VARIANT_BOOL COM中的布爾類型 typedef short VARIANT_BOOL
註意: 0== FALSE -1== TRUE
VARIANT_BOOL*
b) 字符串
BSTR COM中的字符串類型
BSTR* BSTR指針
BSTR是指向的是寬字符串的指針,是一個帶有
字符計數值的字符串,且這個計數值是保存在字符數組的開頭
3.BSTR基本操作
a) 錯誤賦值 BSTR str = L"ABCD";
這樣是錯誤的,因為字符串前面沒有計數值
b)BSTR SysAllocString(const OLECHAR*)
是COM申請BSTR字符串的方法,把CHAR* 傳進去,返回BSTR類型
c)BSTR SysAllocStringLen(const OLECHAR* ,UINT)
根據字符串指針與字符個數構造BSTR字符串
d)UINT SysStringLen(BSTR)獲取字符串計數值
e)void SysFreeString(BSTR)釋放字符串,當COM中的
字符串(BSTR)不再使用後,調用該函數.
BSTR strA = SysAllocString(L"Hello"); //申請一個字符串
//申請指定個數字符串,從參數1中取
BSTR strB = SysAllocStringLen(strA,SysStringLen(strA));
SysFreeString(strA);
SysFreeString(strB);
4.COM常用數據類型
IUnknown* COM的最基本的接口指針
IUnknown** 指針的指針
IDispatch* 支持組件自動化的接口
IDispatch** IDispatch*的指針
如果寫的組件不想被 解釋性的語言 腳本語言
查找接口的話, 可以直接使用IUnknown接口
5.萬能數據類型 VARIANT
a) 具備跨語言的特性,同時能存儲任何的數據類型
為了實現這個類型的功能,C++中這個類型是一個結構體,
這個結構體,裏面又有聯合體,聯合多種基本數據類型
又有變量類型標誌VARTYPE vt.標誌他的類型
b) 初始化和清楚
VARIANT var; VariantInit(&var); //此時var.vt == VT_EMPTY控件 //..其他操作 //清除操作 VariantClear(&var);
c) VARIANT的使用
用VARIANT保存LONG類型
VARIANT var; VariantInit(&var); //此時var.vt == VT_EMPTY控件 //..其他操作 //清除操作 //VT_I4 ×××就是VT_I2 var.vt = VT_I4; //賦值 var.lVal = 100; VariantClear(&var);
FLOAT類型 VT_R4 DOUBLE VT_R8
var.fltVal flaot值
VARIANT使用BSTR類型
var.vt = VT_BSTR;
var.bstrVal = SysAllocString(L"HEllo");
VT_BOOL 布爾類型
d) 讀取值
//先判斷類型 在根據類型讀取
if(var.vt == VT_l4)
{
LONG lValue = var.lVar;
}
6.COM數據類型的轉換
LONG轉換成FLOAT
VARIANT var; 初始化
var.vt = VT_I4;
var.lVar = 100;
VariantChangeType(&var,&var,0,VT_R4);
if(var.vt = VT_R4)
{
LONG fValue = var.fltValue;
}
清空var
7.VARIANT類型的派生類
a) 在派生類擴展VARIANT類使得他的使用更加方便
#include <atlbase.h>ATL庫裏面就帶有一個派生類CComVariant
他簡化了初始化和清楚, 構造函數可以直接傳遞基本類型或者VARIANT類型
可以用C++的類型,也可以用COM基本類型來構造一個對象
INT a = 10; CComVariant b(a); double c = 100.0100; CComVariant d(c);
b) 賦值 重載了運算符 operator= 根據不同類型分配不同值
也就是說如果你是INT型 直接對象=值 d = 100;
(二)、測試簡單對象
一、ATL制作簡單對象(Simple Object)
完成即可
1.項目創建完成,添加簡單對象(Simple Object)
選擇簡單對象
輸入簡稱
ProgId
ATLProject.HelloSimpleObject
ProgID是程序員給某個CLSID指定一個程序員易記的名稱,
某些計算機語言通過PropID來標記組件 命名規則
<Program>.<Component>.<Version>
程序.組件.版本
雙重是支持IDispatch接口的,這樣這個接口就會支持一些腳本語言等等。
2.給簡單對象添加一個方法,
在類視圖選中剛添加的這個(選中接口不是添加的類)然後添加方法
接口方法是固定的HRESULT,所以只能用輸入的參數作為返回值.
in代表輸入
加一個指針就可以顯示out,表示是輸出的可作為返回值
retval表示用他做返回值
這個ID表示這個方法 在接口裏的ID,直接點擊完成即可
3.來到解決方案管理器查看項目ild文件
ATLProjectLib的uuid
組件的UUID他被ATLProjectLib包含,組件又包含了這個 我們自定義的接口
會發現我們的組件(簡單對象就是組件)支持我們自定義接口(IHelloSimpleObject)
接口定義上面會看到接口IID,
而且接口裏就有一個我們剛創建的方法, 他的ID是1
4.方法的聲明和實現
在.h文件裏聲明了
在.c文件裏實現了
5.添加屬性
他會自動給這個屬性添加 SET和GET方法,
ProPutRef表示為引用參數
添加屬性方法ID自增
6.編譯生成
除了dll文件還生成了兩個代碼文件(ATLProject_i.h和 _i.c)
這兩個文件裏面描述的是組件的相關信息,如接口方法接口iid,組件CLSID
7.組件的CLSID
組件的CLSID和IID一樣,都是GUID,
組件的CLSID用於標識組件,每一個組件都有一個與之對應的CLSID
紅色就是組件名,上面就是他的CLSID
這個就是你輸入的組件名
二、在MFC中測試簡單對象
直接創建一個對話框程序
stdafx.h添加 _i.h文件 stdafx.cpp 添加_h.c文件
測試代碼
組件這些都被宏定義了,使用更方便
HRESULT hr = E_FAIL; //使用COM組件必須初始化 hr = CoInitialize(NULL); if(SUCCEEDED(hr)) { //接口指針對象 IHelloSimpleObject* pHello = NULL; //創建接口指針實例 組件對象 //第一個參數是組件標識 //第二個參數NULL //第三個參數一般用這個CLSCTX_INPROC_SERVER //第四個參數接口標識符 //第五個參數 接口指針 返回 hr = CoCreateInstance(CLSID_HelloSimpleObject,NULL,CLSCTX_INPROC_SERVER, IID_IHelloSimpleObject,(LPVOID*)&pHello); if(SUCCEEDED(hr)) { LONG sum = 0; hr = pHello->SumLong(100,100,&sum); //讀取描述 BSTR bstrs = SysAllocString(L""); hr = pHello->get_m_desc(&bstrs); SysAllocString(bstrs); bstrs = NULL; //寫入 BSTR strb = SysAllocString(L"MFC中測試"); hr = pHello->put_m_desc(strb); SysAllocString(strb); bstrs = NULL; bstrs = SysAllocString(L""); hr = pHello->get_m_desc(&bstrs); SysAllocString(bstrs); bstrs = NULL; } //接口不再使用 pHello->Release(); } //不再使用com組件對象時 一般放在程序結束 CoUninitialize();
COM技術入門(2)