ATL,Active Template Library活動模闆庫,是一種 微軟程式庫,支援利用C++語言編寫ASP代碼以及其它ActiveX程式。通過活動模闆庫,可以建立 COM元件,然後通過ASP頁面中的 腳本對COM對象進行調用。這種COM元件可以包含屬性頁、對話框等等控件。 ATL簡介 一. 什麼是ATL 自從1993年Microsoft首次公布了COM技術以後,Windows平台上的開發模式發生了巨大的變化,以COM為基礎的一系列 軟體元件化技術将Windows程式設計帶入了元件化時代。廣大的開發人員在為COM帶來的軟體元件化趨勢歡欣鼓舞的同時,對于COM開發技術的難度和煩瑣的細節也感到極其的不便。COM程式設計一度被視為一種高不可攀的技術,令人望而卻步。開發人員希望能夠有一種友善快捷的COM開發工具,提高開發效率,更好地利用這項技術。 針對這種情況,Microsoft公司在推出COM SDK以後,為簡化COM程式設計,提高開發效率,采取了許多方案,特别是在MFC(Microsoft Foundation Class)中加入了對COM和OLE的支援。但是随着Internet的發展,分布式的元件技術要求COM元件能夠在網絡上傳輸,而又盡量節約寶貴的網絡帶寬資源。采用MFC開發的COM元件由于種種限制不能很好地滿足這種需求,是以Microsoft在1995年又推出了一種全新的COM開發工具ATL。 ATL是ActiveX Template Library 的縮寫,它是一套C++模闆庫。使用ATL能夠快速地開發出高效、簡潔的代碼(Effective and Slim code),同時對COM元件的開發提供最大限度的代碼自動生成以及可視化支援。為了友善使用,從Microsoft Visual C++5.0版本開始,Microsoft把ATL內建到Visual C++開發環境中。1998年9月推出的Visual Studio 6.0 內建了ATL 3.0版本。目前,ATL已經成為Microsoft标準開發工具中的一個重要成員,日益受到C++開發人員的重視。 ATL究竟給開發人員帶來了什麼樣的益處呢?這還要先從ATL産生以前的COM開發方式說起。 在ATL産生以前,開發COM元件的方法主要有兩種:一是使用COM SDK直接開發COM元件,另一種方式是通過MFC提供的COM支援來實作。 直接使用COM SDK開發COM元件是最基本也是最靈活的方式。通過使用Microsoft提供的開發包,我們可以直接編寫COM程式。但是,這種開發方式的難度和工作量都很大,一方面,要求開發者對于COM的技術原理具有比較深入的了解(雖然對技術本身的深刻了解對使用任何一種工具都是非常有益的,但對于COM這樣一整套複雜的技術而言,在短時間内完全掌握是很難的),另一方面,直接使用COM SDK要求開發人員自己去實作COM應用的每一個細節,完成大量的重複性工作。這樣做的結果是,不僅降低了工作效率,同時也使開發人員不得不把許多精力投入到與應用需求本身無關的技術細節中。雖然這種開發方式對于某些特殊的應用很有必要,但這種程式設計方式并不符合元件化程式設計方法所倡導的可重用性,是以,直接采用COM SDK不是一種理想的開發方式。 使用MFC提供的COM支援開發COM應用可以說在使用COM SDK基礎上提高了自動化程度,縮短了開發時間。MFC采用 面向對象的方式将COM的基本功能封裝在若幹MFC的C++類中,開發者通過繼承這些類得到COM支援功能。為了使 派生類友善地獲得COM對象的各種特性,MFC中有許多預定義宏,這些宏的功能主要是實作COM接口的定義和對象的注冊等通常在COM對象中要用到的功能。開發者可以使用這些宏來定制COM對象的特性。 另外,在MFC中還提供對Automation 和 ActiveX Control的支援,對于這兩個方面,Visual C++也提供了相應的AppWizard和ClassWizard支援,這種可視化的工具更加友善了COM應用的開發。 MFC對COM和OLE 的支援确實比手工編寫COM程式有了很大的進步。但是MFC對COM的支援是不夠完善和徹底的,例如對COM接口定義的IDL語言,MFC并沒有任何支援,此外對于近些年來COM和 ActiveX技術的新發展MFC也沒有提供靈活的支援。這是由MFC設計的基本出發點決定的。MFC被設計成對Windows平台程式設計開發的面向對象的封裝,自然要涉及Windows程式設計的方方面面,COM作為Windows平台程式設計開發的一個部分也得到MFC的支援,但是MFC對COM的支援是以其全局目标為出發點的,是以對COM 的支援必然要服從其全局目标。從這個方面而言,MFC對COM的支援不能很好的滿足開發者的要求。 随着 Internet技術的發展,Microsoft将ActiveX技術作為其網絡戰略的一個重要組成部分大力推廣,然而使用MFC開發的ActiveX Control,代碼備援量大(所謂的“肥代碼 Fat Code”),而且必須要依賴于MFC的運作時刻庫才能正确地運作。雖然MFC的運作時刻庫隻有部分功能與COM有關,但是由于MFC的繼承實作的本質,ActiveX Control必須背負運作時刻庫這個沉重的包袱。如果采用靜态連接配接MFC運作時刻庫的方式,這将使ActiveX Control代碼過于龐大,在網絡上傳輸時将占據寶貴的網絡帶寬資源;如果采用動态連接配接MFC運作時刻庫的方式,這将要求 浏覽器一方必須具備MFC的運作時刻庫支援。總之MFC對COM技術的支援在網絡應用的環境下也顯得很不靈活。 解決上述COM開發方法中的問題正是ATL的基本目标。 首先ATL的基本目标就是使COM應用開發盡可能地自動化,這個基本目标就決定了ATL隻面向COM開發提供支援。目标的明确使ATL對COM技術的支援達到淋漓盡緻的地步。對COM開發的任何一個環節和過程,ATL都提供支援,并将與COM開發相關的衆多工具內建到一個統一的程式設計環境中。對于COM/ActiveX的各種應用,ATL也都提供了完善的Wizard支援。所有這些都極大地友善了開發者的使用,使開發者能夠把注意力集中在與應用本身相關的邏輯上。 其次,ATL因其采用了特定的基本實作技術,擺脫了大量備援代碼,使用ATL開發出來的COM應用的代碼簡練高效,即所謂的“Slim Code”。ATL在實作上盡可能采用優化技術,甚至在其内部提供了所有C/C++開發的程式所必須具有的C啟動代碼的替代部分。同時ATL産生的代碼在運作時不需要依賴于類似MFC程式所需要的龐大的代碼子產品,包含在最終子產品中的功能是使用者認為最基本和最必須的。這些措施使采用ATL開發的COM元件(包括ActiveX Control)可以在網絡環境下實作應用的分布式元件結構。 第三,ATL的各個版本對Microsoft的基于COM的各種新的元件技術如MTS、ASP等都有很好的支援,ATL對新技術的反應速度大大快于MFC。ATL已經成為Microsoft支援COM應用開發的主要開發工具,是以COM技術方面的新進展在很短的時間内都會在ATL中得到反映。這使開發者使用ATL進行COM程式設計可以得到直接使用COM SDK程式設計同樣的靈活性和強大的功能。 本文的目的就是希望在有限的篇幅中能夠使讀者對ATL的使用和基本原理有一個初步的了解,為廣大的COM開發人員更好地使用ATL開發起到抛磚引玉的作用。 二. ATL基本技術 雖然使用ATL開發COM 應用是一件非常簡單的事情,但是在ATL簡單易用的界面後面卻包含着複雜的技術。面對ATL生成的大量代碼,我們即使不去深入地了解這些代碼的含義也可以開發出COM應用來,但是如果我們要充分地挖掘ATL的潛力,開發出更靈活、強大的COM應用,則必須對ATL使用的基本技術有所了解。研究ATL的實質最好的教材就是由Visual C++提供的ATL 源代碼。本文這一部分隻是對ATL中用到的最基本的技術進行簡單的介紹。 簡單地說來,ATL中所使用的基本技術包括以下幾個方面: COM技術 C++模闆類技術(Template) C++多繼承技術(Multi-Inheritance) COM技術是了解ATL的基礎,使用ATL進行開發要對COM技術的基本概念有最低限度的了解。由于COM是一項非常複雜龐大的技術體系,限于本文的篇幅,這裡不再贅述。對于本文中提到的COM基本概念也不做過多的解釋,請讀者參閱有關的參考書籍。 作為ATL最核心的實作技術的模闆是對标準C++語言的擴充,但是在大多數的C++程式設計環境中,人們很少使用它,這是因為模闆的功能雖然很強,但是它内部機制比較複雜,需要比較多的C++知識和經驗才能靈活地使用它。在MFC中的CObjectArray等功能類就是由模闆來定義的。完全通過模闆來定義程式的整體類結構,ATL是迄今為止做得最為成功的。 所謂模闆類簡單地說是對類的抽象。我們知道C++語言用類定義了構造對象(這裡指C++對象而不是COM對象)的方式,對象是類的執行個體,而模闆類定義的是類的構造方式,使用模闆類定義執行個體化的結果産生的是不同的類。是以可以說模闆類是“類的類”。 在C++語言中模闆類的定義格式如下: 注意:<和>是左右尖括号,可能無法正常顯示。 template < class T> class MyTemp { MyTemp<T>( ){ }; ~MyTemp<T>( ) { }; int MyFunc( int a) ; } …………. Int MyTemp<T>::MyFunc( int a) { } 首先使用C++的關鍵字“template”來聲明一個模闆類的定義。在關鍵字後面是用尖括号括起來的類型參數。正是根據這個類型參數, 編譯器才能在編譯過程中将模闆類的具體定義轉化為一個實際的類的定義,即生成一個新的類。接下來的定義方式與普通的類定義十分相似,隻是在類的函數定義中都要帶有類型參數的說明。 下面的程式段說明了模闆類的用法: typedef MyTemp<MyClass> myclassfromtemp; myclassfromtemp m; int a = m.Myfunc(10); 通常在使用模闆類時為了友善起見,使用一個關鍵字“typedef”為新定義出來的類取一個名字。在上面的程式段中假設“MyClass”是一個由使用者定義的類,通過将這個類的名字作為類型參數傳遞給模闆類,我們可以建立一個新的類,這個類的行為将以模闆類的定義為基礎,例如它具有模闆類定義的所有成員函數,同時這個類又是對模闆類行為的一種修改,這種修改是通過使用者提供的類型參數來實作的。賦予模闆類以不同的類型參數,則得到行為架構相似但具體行為不同的一組類的集合。有了新的類的定義以後,我們可以象使用普通類一樣來建立一個類的執行個體,即一個新的對象,并且調用這個對象的成員函數。 模闆類是對标準C++語言的最新擴充,雖然它的功能很強大,但是要想使用好模闆類需要相當多的關于語言和程式設計的經驗和知識,而且錯誤地使用模闆類又會對程式的結構和運作效率帶來大的副作用,是以一般的程式設計環境和程式設計書籍對模闆類的使用都采取謹慎的态度。而ATL的核心就是由幾十個模闆類構成的,通過研究ATL的源代碼可以使我們對模闆類的使用有比較深刻全面的認識。 多繼承技術同模闆一樣,是C++語言中極具争議性的技術。使用多繼承技術可以使程式的設計和實作更加靈活,但是,由于多繼承的複雜性和自身概念上的一些問題,使多繼承在各種面向對象的語言環境中得到的支援都非常有限。例如Small Talk根本就不允許多繼承,同樣MFC也不支援多繼承技術。 多繼承最大的問題是所謂的“鑽石結構”。例如下面的代碼: class A { ..... }; class B : public A { .. . }; class C : public A { ..... }; class D : public C,B { ........ } 由于類D同時從類C和B繼承,是以在下面的語句中就會發生歧義: D* pD = new D; (A*)pD->Func(...); 由于類D通過類C和類B 分别繼承了類A,這裡的強制轉化就會發生歧義。 ATL使用了C++最新規範中加入的兩個運算符号 static_cast、dynamic_cast代替簡單的強制轉化,進而消除多繼承帶來的歧義。使用這兩個運算符号,我們可以在對象運作過程中擷取對象的類型資訊。上面的代碼可以采用下面的方式修改: D* pD = new D; static_cast<A*>(static_cast<B*>(pD))->Func(...); 為什麼模闆類和多繼承技術會成為ATL主要的工具呢?原因在于,采用模闆可以在編譯過程中快速的生成具有使用者定制功能的類,這對于COM這樣一個複雜的技術體系在實作效率上得到了很大的提高。通過使用模闆類,使用者可以把精力集中在自己開發的類的基本邏輯上,在完成了自己的類的設計以後,通過繼承不同的類,生成不同的模闆類,就可以快速地實作COM的功能,同時又避免了采用單繼承結構造成的大量功能備援。 總之,正是由于在設計實作過程中采用了模闆類和多繼承技術,才使ATL成為一個小巧靈活的COM開發工具,能夠适應開發人員對COM應用開發的各種需要。 三. ATL基本使用 這一部分将重點介紹ATL的基本使用過程。由于ATL已經被內建在Microsoft Visulal Studio的Visual C++開發環境中,是以要使用ATL必須先安裝Visual C++。在下面的讨論中有關COM的基本知識請參閱有關的文檔,這裡不再詳細說明。 使用ATL開發一個COM應用基本可以分為以下幾個步驟: 建立一個新的ATL工程,并對工程的選項進行适當的配置。 向新建立的工程添加新的ATL類,并對該類進行一些初始配置工作。 根據COM應用的基本要求向新的ATL類加入新的接口定義,并實作相應的接口成員函數。 編譯連接配接工程,注冊COM應用。 下面将根據這些步驟依次介紹ATL的基本使用過程(給出的是Visual Studio 6.0的使用): 1. 建立工程 首先啟動Visual C++ 內建開發環境,選擇“File”菜單下的“New...”指令,在“New”對話框中選擇“Project”頁。 選擇“ATL COM AppWizard”項,這是建立ATL工程的AppWizard向導入口。然後在“Project name”編輯框中輸入工程的名字,單擊“OK”按鈕,進入AppWizard對話框。 在AppWizard對話框中主要的設定選項有: COM服務程式的類型: - 動态連接配接庫(Dynamic Linking Library) 最終産生一個動态連接配接庫(DLL)形式的COM服務程式; - 應用程式(Executable application)最終産生一個可執行程式類型(EXE)的COM服務程式; - NT服務(NT Service):産生一個以NT服務方式運作的COM服務程式。 允許嵌入Proxy/Stub代碼。由Microsoft提供的MIDL編譯IDL檔案以後,将産生用于對象排程(Marshaling)的Proxy/Stub的代碼。傳統地,這部分代碼與COM服務程式的代碼是分離的,但是由于新的COM标準支援多線程環境下的COM對象服務,是以在動态連接配接庫的COM服務程式中也要有Proxy/Stub的支援。為了支援在網絡上的傳輸,ATL允許使用者選擇将Proxy/Stub的代碼包括在生成的DLL代碼中。這個選項在EXE和NT服務類型的COM應用條件下不可選。 允許支援MFC。由于ATL對除COM以外的基本的Windows程式設計方面的支援極為有限,同時許多程式員對MFC又非常熟悉,是以在ATL的工程設定中允許在ATL工程内部支援使用MFC,即可以使用MFC定義的類。這在一方面來看是非常友善的,特别是對于習慣于使用MFC的開發人員來說,能夠使用MFC提供的各種功能強大的類的支援,而不必直接使用Windows SDK。從另一個方面來看,在ATL工程中使用MFC同時就喪失了ATL代碼輕量級的特點。 支援MTS。MTS是Microsoft Transaction Server的縮寫,它是Microsoft在COM技術方面的一個新的分支,這裡不作詳細說明。 完成上面的設定以後,可以選擇FINISH完成工程的設定,ATL将建立相應的工程。 2. 加入ATL類 完成工程的建立和設定以後,下一步就是向工程中加入一個新的ATL類。Visual Studio內建環境提供了向導工具“ATL Object Wizard”用于加入一個新的ATL類。操作過程并不複雜,隻是一組對話框操作而已。 首先通過內建環境的“Insert”菜單下的“New ATL Object…”指令進入“ATL Object Wizard”對話框。 這個對話框即為建立ATL對象的向導起始界面。對話框的左邊部分說明了待建立對象的基本類型,這裡主要有以下的幾種類型: 對象(Object)基本的COM對象類型; 控制(Control)ActiveX Control類型的ATL對象; 其他(Miscellaneous)輔助功能,如對話框的生成等; 資料通路(Data Access)資料通路,支援MTS等。 右邊部分說明了每種類型的詳細内容,對于一般的COM服務程式,使用對象表中的簡單對象(Simple Object)就可以了。 標明待建立對象的基本類型以後,單擊“Next>”按鈕進入下一步,進入對象屬性設定對話框,如圖4和圖5所示。 對象屬性設定分為兩個過程:先是對象名字辨別的設定,然後是對對象的基本屬性進行設定。首先是對象的名字辨別設定。 在對象辨別編輯框中輸入待建立對象的名字,ATL對象向導将同步地根據使用者輸入的對象辨別設定該對象的C++辨別和COM辨別。對象的C++辨別包括對象的類名,cpp檔案名和頭檔案名。COM辨別包括對象在類型庫中的CoClass段和實作的主接口的名字,同時還有在 系統系統資料庫中的類型名以及ProgID。 對象名字辨別設定完成以後,選擇對象屬性頁(Attribute)進入對象的屬性設定頁面。 對象的屬性設定是ATL對象建立過程中最複雜的部分,包括以下幾個主要部分: 對象的線程模型(Thread Model) 對象的線程模型是COM對象在多線程環境下被通路時對通路方式的控制,預設情況下在ATL中采用的是套間模型Apartment,由系統通過消息隊列方式提供并發控制。 對象的接口模型(Interface) COM對象的接口可以是雙接口(Dual Interface)。雙接口不同于普通接口(Custom Interface) 之處在于雙接口是從Automation基本接口IDispatch繼承的,而普通接口是從IUnknown接口直接繼承來的。預設的接口模型是雙接口。 對象的聚合模型(Aggregate) COM規範不允許對象的實作繼承,但是可以通過聚合方式重用其它的COM對象。ATL對象屬性設定中的聚合模型可以指定待建立的COM對象是否支援聚合模型。預設的選項是支援對象的聚合。 對象對錯誤處理的支援(Support ISupportErrorInfo) 選取這個選項可以在對象的運作過程中支援錯誤處理。預設情況下這個選項不被選中。 對象對連接配接點的支援(Support Connection Points) 連接配接點是COM對象的事件機制。選中這個選項可以使待建立的COM對象具有發出事件的能力。預設情況下該選項不被選中。 對象對自由線程排程的支援(Free Thread Marshaller, 簡稱FTM) 對象的自由線程排程是對象在處于自由線程模型狀态下,為了簡化對象的通路過程而采用的一種優化政策。預設情況下該選項不被選中。 對于上述的任何一個選項的較長的描述都涉及到COM技術一些核心的内容,并且都已超出本文的範圍,是以本文隻對ATL給出的預設選項加以說明,對這些内容感興趣的讀者可以參考Microsoft提供的文檔。 完成了上面的設定以後,就可以按“OK”按鈕完成對象的建立過程。下一步就是向所生成的ATL類的接口中加入成員函數的定義,以及接口成員函數的實作過程。 3. 加入接口定義,實作接口函數 加入了ATL類定義之後,我們可以打開Visual C++內建環境下 項目管理器(Workspace)中的Class View來檢查生成的類定義的情況。我們可以看到一個新的類已經生成,同時,還生成了相應的接口定義。ATL Object Wizard為我們生成了類定義的.h 和.cpp檔案,此外還有用于接口定義的IDL檔案。有了這些檔案以後,我們就可以為接口加入成員函數,完成類的定義。 首先在Class View中選中相應的接口,顯示為接口IATLTest,單擊滑鼠右鍵打開菜單,如圖7。此彈出式菜單定義了為接口加入屬性和方法的操作。選取其中的“Add Method...”項,可以為接口加入方法成員;選取“Add Property...”則可以為接口加入新的屬性成員。 加入屬性和方法的對話框可以參看圖8和圖9。如果我們要在接口中加入一個方法,則選取“Add Method...”菜單指令。假設方法名為ABC,方法的傳回類型為COM規定的HRESULT類型。我們也可以定義非HRESULT傳回類型的函數,但是這需要手工修改接口定義的IDL檔案。我們定義ABC方法的一個參數為a,類型為整數型。完成了方法的定義以後,單擊“OK”按鈕則把此方法加入到接口中。 屬性的加入過程是類似的。屬性加入對話框要求指定屬性的類型、名字以及屬性的通路方式。在屬性和方法的編輯對話框中都有一個“Attributes”按鈕,在給出了一個屬性或方法的基本定義之後,單擊此按鈕,可以對屬性和方法的一些進階特性進行設定。 方法成員加入以後,我們可以通過Class View來檢查ATL為我們所做的工作。首先我們看到ATL在接口的定義中加入了該方法的定義;同時在對應的ATL類定義中,也加入了一個相應的方法的定義;在類對應的.cpp檔案中,加入了此方法的實作架構。此後,我們隻要在這個函數架構中加入該方法的代碼邏輯,一個接口函數的定義和實作就基本完成了。依照這種方式,我們可以完成整個COM對象的定義和實作。 完成以上的步驟之後,我們就可以編譯連接配接應用了。 4. 編譯連接配接應用、注冊COM服務程式 對ATL工程的編譯連接配接過程包括下面的幾個步驟: 使用MIDL編譯工程的IDL檔案,形成接口定義的頭檔案和用于排程(Marshalling)的代碼; 編譯工程的.cpp檔案形成目标檔案; 連接配接目标檔案,形成應用子產品; 注冊COM服務程式。 關于工程編譯連接配接的其它部分同Visual C++中MFC工程的編譯連接配接過程相似,這裡隻重點介紹一下COM服務程式的注冊過程。 在ATL中,COM服務程式的注冊是在工程編譯連接配接的最後階段,由ATL輔助完成的。在手工的COM程式設計中,服務程式的注冊是比較麻煩的工作。在ATL中,系統通過讀取在建立工程過程中形成的注冊 腳本檔案來完成注冊工作。注冊腳本(Register Script 簡稱RGS)是ATL提供的文本方式的注冊輔助檔案。下面是注冊腳本檔案的一個執行個體。 HKCR - 表示系統資料庫中COM對象的注冊項,是HKEY_CLASS_ROOT的縮寫 { AuthTest.ActiveXObject.1 = s 'ActiveXObject Class' { CLSID = s '' } - 對象的ProgID AuthTest.ActiveXObject = s 'ActiveXObject Class' { CLSID = s '' } -對象的與版本無關的ProgID NoRemove CLSID -對象CLSID注冊項 { ForceRemove = s 'ActiveXObject Class' { ProgID = s 'AuthTest.ActiveXObject.1' VersionIndependentProgID = s 'AuthTest.ActiveXObject' InprocServer32 = s '%MODULE% -伺服器類型,表示DLL伺服器 { val ThreadingModel = s 'both' -線程模型,這裡是BOTH型 } } } } RGS檔案包含注冊COM服務程式的各項内容,通常我們不必修改此RGS檔案,必要時我們也可以手工修改RGS檔案來定制子產品的注冊過程。 四. 應用ATL的一個例子 上面介紹了使用ATL建立一個COM服務程式的基本過程。在介紹過程中,我們實際上已經生成了一個COM服務程式的基本架構,隻是沒有填寫實際的内容。在下面部分,我們實際開發一個十分簡單的COM服務程式,并且為它編寫一段客戶代碼進行測試,使大家對使用ATL開發COM服務程式的過程有一個全面整體的了解。 我們要開發的服務程式的功能很簡單,它隻實作一個接口,這個接口名字是ISimpleInterface,接口隻有一個成員函數,叫做Welcome。這個函數的功能隻是輸出一個“Hello World!”的字元串。 按照上一部分介紹的建立COM服務程式的步驟,我們進行如下的操作: 1 打開Visual C++內建開發環境; 2 建立一個稱為SimpleTest的ATL工程; 3 在這個工程中插入新的對象,對象的名字是SimpleInterface; 4 設定接口ISimpleInterface的有關屬性,使它成為一個雙接口; 5 在對象的接口ISimpleInterface中加入方法Welcome; 6 打開ATL加入的Welcome方法的架構,可以看到如下的代碼段: STDMETHODIMP CActiveXObject::get_TestProp(long *pVal) { AFX_MANAGE_STATE(AfxGetStaticModuleState()) // TODO: Add your implementation code here return S_OK; } 7 将程式架構中的注釋部分替換為下面的代碼: ::MessageBox(NULL,_T(”Hello World!”),_T(”Welcome”), MB_OK); Welcome方法被調用時将彈出一個消息框。 8 編譯連接配接工程。 上面的步驟完成以後,我們就有了一個簡單的COM服務程式,而且已經被注冊到目前系統中。 下面我們要完成一個簡單的COM客戶程式。一個COM客戶程式簡單地說是使用COM元件對象的程式。客戶程式調用COM對象的基本流程是: 建立COM對象的執行個體。這可以通過調用Windows系統的API函數CoCreateInstance來完成。 通過接口調用函數。 調用IUnknown::Release釋放COM對象執行個體 我們的客戶程式是使用MFC編寫的一個基于對話框的簡單應用程式。具體的過程如下: 1 打開Visual C++內建開發環境; 建立一個稱為SimpleClient的基于對話框的MFC工程; 在對話框中加入一個按鈕,名字為TEST; 在SimpleClientDlg.cpp檔案中加入如下的代碼: (1) 在cpp檔案 #include “simpleclientdlg.h”之後加入下面的代碼: #include "d:\simpletest\simpletest.h" #include "d:\simpletest\simpletest_i.c" // 根據需要修改頭檔案的路徑 加入的頭檔案是在編譯COM服務程式過程中自動生成的,其中包含接口本身的定義、接口IID的定義和COM對象的CLSID的定義。包含該頭檔案可以使客戶程式能夠使用COM服務程式。 (2) 在按鈕TEST的消息控制函數中加入如下的代碼: CoInitialize(0); HRESULT hr; ISimpleInterface* pIntf = NULL; hr = CoCreateInstance(CLSID_SimpleInterface, NULL, CLSCTX_SERVER , IID_ISimpleInterface, (void **)& pIntf); if(SUCCEEDED(hr)) { pIntf->Welcome(); pIntf->Release(); } CoUninitialize(); 上面的代碼首先通過系統API CoCreateInstance建立COM對象,得到接口的指針,然後調用接口成員函數Welcome,最後通過IUnknown::Release()函數釋放COM對象執行個體。 編譯連接配接客戶程式 最後,我們可以測試客戶程式是否正常運作。啟動客戶程式,當單擊“TEST”按鈕時我們可以看到彈出一個消息框,這正是我們的COM服務程式提供的功能。