李巍
天津市漢沽區(qū)公用房屋管理所 天津 300480
隨著Intranet/Intement的飛速發(fā)展,使軟件應(yīng)用置身于更加廣闊的環(huán)境中,從而對應(yīng)軟件提出了更高的要求。在這樣的環(huán)境下,面向?qū)ο蟮乃枷胍呀?jīng)難以適應(yīng)這種分布式的軟件模型,于是組件化程序設(shè)計思想得到了迅速的發(fā)展。
按照組件化程序設(shè)計的思想,復(fù)雜的應(yīng)用程序被設(shè)計成一些小的、功能單一的組件模塊,這些組件模塊可以運行在同一臺機器上,也可以運行在不同的機器上,甚至可以是不同的操作系統(tǒng)。為了實現(xiàn)這樣的應(yīng)用軟件,組件程序和組件程序之間需要一些極為細致的規(guī)范,只有組件程序遵守了這些共同的規(guī)范,軟件系統(tǒng)才能正常的運行。為此,OMG(Object Management group,對象管理組織)和Microsoft分別提出了CORBA和COM(Component Object Model,組件對象模型)標準,目前CORBA模型主要應(yīng)用于UNIX操作系統(tǒng)平臺,而COM則主要應(yīng)用于Microsoft Windows操作系統(tǒng)平臺上。
Windows系統(tǒng)提供了一個用于注冊進程內(nèi)組件的使用工具Regsvr32.exe,只要進程內(nèi)組件提供了相應(yīng)的入口函數(shù),則Regsvr32就可以完成注冊或稱注銷,而Regsvr32程序本身并不進行注冊工作。
除了利用Regsvr32程序進行注冊之外,還有其他一些安裝程序在安裝或卸載的過程中也可以調(diào)用組件程序中的DLLRegisterServer函數(shù)和DLLUnregisterServer函數(shù)完成組件程序的注冊和注銷操作。
COM本身除了規(guī)范以外,也有實現(xiàn)的部分,其中包括一些核心的系統(tǒng)級代碼,也正是這部分核心代碼,才使得對象和客戶之間可通過接口在二進制代碼級進行交互。在Microsoft Windows操作系統(tǒng)環(huán)境下,這些庫以.DLL文件的形式存在,其中包括以下內(nèi)容:
(1)提供了少量的API函數(shù)實現(xiàn)客戶和服務(wù)器端COM應(yīng)用的創(chuàng)建過程。在客戶端,主要是一些創(chuàng)建函數(shù);而在服務(wù)器端,提供一些對對象的訪問支持。
(2)COM通過注冊表查找本地服務(wù)器即EXE程序,以及程序名與CLSID的轉(zhuǎn)換等。
(3)提供了一種標準的內(nèi)存控制方法,使應(yīng)用控制進程中內(nèi)存的分配。
設(shè)計接收器對象與連接點對象之間如何建立關(guān)系的過程,這個過程是由客戶方控制的,所以客戶首先詢問對象是公為可連接對象,它只需調(diào)用對象的QueryInterface成員函數(shù),請求IConnection pointContainer接口,如果請求成功,則表明為可連接對象,并返IConnection pointContainer接口指針,否則說明對象不是可連接對象??蛻舻玫搅薎Connection pointContainer接口后,調(diào)用其成員函數(shù)獲取出接口的連接點對象,如果對象支持此出接口,則可以得到連接點對象,然而調(diào)用連接點對象的IConnection point接口的成員函數(shù)建立連接。如果客戶要取消連接,同樣調(diào)用IConnection point接口的成員函數(shù)即可。
首先在應(yīng)用類的InitInstance成員函數(shù)中加入COM或OLB庫初始化函數(shù),InitInstance函數(shù)開始處理調(diào)用AfxOleInit輔助函數(shù)代碼如下:
BOOL CTestCtrlApp::InitInstance()
{
// Initialize OLE libraries
if(!AfxOleInit())
{
AfxMessageBox("Initializing OLE library failed");
return FALSE;
}
AfxEnableControlContainer();
為對話框類加入內(nèi)嵌的接受對象,因為對話框類也是從CCmdtarget派生而來的,所以在對話框類中可以使用BEGIN_INTERFACE_PART/END_INTERFACE_PART宏定義接受器對象類。定義接受器對象類:
BEGIN_INTERFACE_PART(EventSink,IDispatch)
INIT_INTERFACE_PART(CTestCtrlDlg,EventSink)
STDMETHOD(GetTypeInfoCount)(unsigned int*);
STDMETHOD(GetTypeInfo)(unsigned int,LCID,ITypeInfo**);
STDMETHOD(GetIDsOfNames)(REFIID,LPOLESTR*,unsigned int,LCID,DISPID*);
STDMETHOD(Invoke)(DISPID,REFIID,LCID,unsigned short,DISPPARAMS*,
VARIANT*,EXCEPINFO*,unsigned int*);
END_INTERFACE_PART(EventSink)
對話框的操作,首先,在InitInstance成員函數(shù)中加入如下創(chuàng)建源對象的代碼:
GUID sourceobjCLSID;
HRESULThResult=::CLSIDFromProgID(L"SourceComp.S ourceObj",&sourceobjCLSID); if(FAILED(hResult))
{
return FALSE;
}
hResult = CoCreateInstance(sourceobjCLSID,NULL,
CLSCTX_INPROC_SERVER,IID_IDispatch,(void**)&m_pDispatch);
if(FAILED(hResult))
{
return FALSE;
}
按照消息控制函數(shù)0nConnection和OnDisconnection分別調(diào)用輔助函數(shù)Connection和Disconnection作為響應(yīng),并根據(jù)不同的返回值進行不同的處理。
按鈕消息控制Onsetproperty為源對象的屬性賦值,在賦值之后,源對象會引發(fā)事件。
所以,在連接已經(jīng)建立的狀態(tài)下,當用戶按下“設(shè)置屬性”按鈕時,會出現(xiàn)事件響應(yīng)消息框。
最后我們還必須對對話框類的析構(gòu)函數(shù)中的清除工作,包括斷開連接、釋放源對象等操作。在CTestCtrlDlg析構(gòu)函數(shù)加入下面代碼:
if(m_pDispatch != NULL){
if(m_dwCookie != 0)
Disconnection();
m_pDispatch->Release();
}
在VC++環(huán)境下COM的編程,VC++對CO3M開發(fā)提供了很好的支持,技術(shù)非常成熟,功能非常強大,使用VC++可以開發(fā)出功能強大,接口集合度高,占用資源少的應(yīng)用程序。使用VC++的MFC類,模板類,以及AppWizard,ClassWizard等用于產(chǎn)生應(yīng)用程序的特點,加快應(yīng)用程序的設(shè)計,用組件技術(shù)可以很好地開發(fā)出一個完整的應(yīng)用程序。
[1]蘇長齡.C/C++程序設(shè)計教程.中國水利水利出版社.2007.
[2][美]帕拉特著.COM精髓.信達工作室譯.2001.
[3]吳金平.VisualC++6.0編程與實踐.中國水利水電出版社.2001.