本文所用的程式架構均為對話方塊模式的MFC EXE工程。在編程前,首先要確定待操作的程式碼群組件是否已經在系統中註冊。如果程式碼群組件沒有註冊,可以通過Windows"System目錄下的regsvr32. exe程式對其進行註冊。
一、使用COM庫函數1.包含COM的標頭檔和介面定義的.c檔案
在標頭檔中包含了介面的C++定義,在.c檔案中說明了介面ID IID和類ID CLSID的符號化常量,例如寫了一個COM庫名稱叫“SimpleTest”,則需要包含以下檔案:
#include "simpletest.h"
#include "simpletest_i.c"
2.添加COM初始和終止代碼。
在應用程式類的初始化執行個體函數InitInstance()中添加如下代碼:
CoInitialize(NULL);
……
CoUnInitialize();
上述語句運行在MFC架構/非MFC架構中,但由於本文程式使用MFC架構,所以也可以利用AfxOleInit()函數對其進行初始化。
3. 建立組件對象。
HRESULT hr;
ISimpleInterface* pIntf = NULL;
hr = CoCreateInstance(CLSID_SimpleInterface, NULL, CLSCTX_SERVER ,
IID_ISimpleInterface, (void **)& pIntf);
if(SUCCEEDED(hr))
{
pIntf->Welcome();
pIntf->Release();
}
二、使用類嚮導匯入類型庫
通過類嚮導可以直接閱讀組件的類型庫,併產生封裝類型庫中每個介面的類,通過這些類的成員函數可以訪問組件介面的方法和屬性,與使用ActiveX控制項的方法有些類似。
1.添加對COM組件進行初始化的代碼。
通過類嚮導的From a Type Library加入組件的.tlb類型庫檔案,並從中引入其介面類。在本例中引入的類型庫檔案中只包含一個從ColeDispatchDriver派生的組件封裝類IAccount。通過封裝類的成員,可以瞭解到組件介面能提供哪些服務,而且可以通過它們訪問組件介面的方法和屬性。
在初始化對話方塊函數裡用COleDispatchDriver類的CreateDispatch()成員函數建立Account組件對象:
IAccount m_account;
……
m_account.CreateDispatch(“ATLSample.Account.1”));
其中ProgID值“ATLSample. Account. 1”可以通過Microsoft Visual Studio Tools 6.0裡的OLE View工具尋找到,其前提是該組件已被成功註冊過。
釋放Account組件對象也可以用COleDispatch-Driver類的ReleaseDispatch()函數來完成。
2.調用方法
對於在COM庫函數方法中用過的Post方法可用下述方法調用:
CString str=m_account. Post(100);
可以看出此種方法實現了同樣的功能但實現起來要比上一種方法簡單些,而且對理解COM的要求也不高。
對於第一大點的例子,可以這麼調用:
CoInitialize(NULL);
ISimpleInterface simple;
simple.CreateDispatch("SimpleTest.SimpleInterface.1");
simple.Welcome();
simple.ReleaseDispatch();
CoUninitialize();
三、使用#import 指令1.簡要介紹
對於類型庫檔案採用該指令是非常合適的,因為不管是調試版本還是發行版本,對於類型庫檔案而言,其路徑是固定的。#import指令在執行時將會從待引入的類型庫中提取出兩個檔案:一個.tlh檔案和一個.tli檔案,後者僅僅是封裝類的函數實現,而前者則包含了許多有關的重要訊息。智能介面指標也在其中定義:
_COM_SMARTPTR_TYPEDEF(IAccount,__uuidof(IAccount));
在實際編譯時間,編譯器會將其展開成下述代碼,並通過_com_ptr_t模板類為介面IAccount定義一個智能指標IAccountPtr。之所以說其是智能指標,是由於它替代IAccount時,會自動處理CoCreate-Instance和所有的IUnknow方法,使用起來非常方便:
typedef _com_ptr_t<_com_IIID< Iaccount,__uuidof(IAccount)>> IAccountPtr;
由於有了智能指標,我們就可以調用_com_ptr_t模板類的CreateInstance()函數來完成對介面指標的建立工作:
IAccountPtr m_account=NULL;
m_account.CreateInstance(__uuidof(Account));
由於在產生的.tlh檔案中包含結構聲明和declspec(uuid(“”))聲明,所以在這裡可以很方便地用__uuidof(Account)擷取介面的GUID。declspec(uuid(“”))聲明將GUID和類及每個介面聯絡起來,允許開發人員以uuidof操作符來擷取類和介面的GUID。
需要特別指出的是: 為防止原有代碼和新引入的代碼之間發生名字衝突,編譯器會定義一個由類型庫名稱標識的命名空間,並在其中聲明的任何名稱內附加一個標識符。而為了避免指定命名空間標識,可以在#import 語句後加上using namespace,而且還可以用rename_namespace來改變命名空間。比如在本例中可以進行如下處理:
#import “Account.tlb” rename_namespace(“AccountDriver”)
using namespace AccountDriver;
這樣,在使用智能介面指標IAccountPtr時只需定義即可:
IAccountPtr m_account;
至於對程式碼群組件中的函數和屬性的調用則同前兩種方法一樣,也是通過m_account來完成訪問的。由於_com_ptr_t模板類和智能指標的引入,#import 指令方法是這三種方法中使用COM組件最簡單的一種。
2.使用方法
在stdafx.h檔案的最後加上下面這句話:
#import "SimpleTest.tlb" no_namespace
ISimpleInterfacePtr* m_account= new ISimpleInterfacePtr;
m_account->CreateInstance(__uuidof(SimpleInterface));
m_account->Interface.Welcome();