介紹
本教程的目的是告訴你如何使用ATL創建一個COM服務器,並使用Visual C++ 和Visual Basic程序來分別調用這個服務器。我並不想深入探討COM的細節,也不想讓你深陷 於IDL之中。這一教程只是為VC++的新手程序員設計的,告訴他們利用ATL來創建一個COM對象 有多麼簡單,並讓他們能對ATL產生更多的興趣。
第1步:啟動ATL COM Wizard
你所需要做的第一件事情就是啟動Visual C++並創建一個新的工程,選擇 “ATL COM Wizard”,工程名為“Simple_ATL”。設置好工程的路徑 之後,單擊OK按鈕。你會看到,屏幕上給了你若干選項。第一個選項為“Server Type”。我們將要創建一個服務器DLL,所以請確認服務器的類型選為“Dynamic Link Library”。我們並不需要關心下面的其它三個復選框,所以我們可以將它們忽略 掉。按下Finish按鈕,這樣向導就會為你產生適當的文件了。之後,一個“New Project Information”窗口就會出現,你可以從上面得知向導都會創建什麼文件,按 下“OK”接受這一切。
第2步:創建一個新的ATL對象
請確認你能 在VC++的IDE中看到Workspace View,如果不能的話則請單擊“View”菜單,然後 選擇“Workspace”。在這個視圖中你會看到三個選項卡,請單擊 “ClassView”欄,你應該會看到“Simple_ATL Classes”。請在此右 擊鼠標鍵,並在彈出菜單中選擇“New ATL Object”,你將會看到下面這樣的窗 口:
默認的選擇項“Simple Object”就是我們所 要的了,請單擊next按鈕,你會來到“ATL Object Wizard Properties”窗口中 。在“Short Name”文本框中輸入“First_ATL”。請注意,這時候向 導就會自動地填寫其它的文本框。然後,單擊頂部的“Attributes”標簽,在這 裡你需要做一些選擇。第一項線程模型(Threading Model)的選擇,我們選擇默認的單元( Apartment)模型。對於接口(Interface),我們選擇雙重(Dual)。最後,因為我們的程 序與聚合(Aggregation)無關,所以我們選擇“No”的單選按鈕。你不必關心底 部的三個復選框,直接單擊OK就可以了,這時候向導就會為我們創建一個新的ATL簡單對象。
第3步:添加一個方法
如果你現在在工作區中單 擊了“ClassView”標簽,那麼你會注意到向導在其中添加了一串東西。我們想添 加的第一個東西是一個方法,可以在“IFirst_ATL”上右擊鼠標鍵,並選擇 “Add Method”。
一旦你單擊了“Add Method”之後,你就會看到“Add Method to Interface”窗口。在返回值類型(Return Type)處你會看到,這個方法會 默認返回HRESULT,在大多數情況下你不需要改變它。下一個文本框允許我們輸入方法的名稱 ,我們可以輸入“AddNumbers”。最後一個文本框是讓我們輸入參數的,由於我 們想做兩個數的相加並獲得一個返回的結果,所以我們需要三個參數,並且最後一個參數是 一個指針。現在,我們不必看那關於IDL的300頁教程了,可以直接在參數文本框中輸入:
[in] long Num1, [in] long Num2, [out] long *ReturnVal
簡單地說來,我 們聲明了兩個long類型的參數,這兩個值是傳入的([in]),還有一個最後傳出的返回值結 果([out])。(你第一次看到這樣的東西可能會有些奇怪,但是如果你讀了一兩本關於COM 的書的話,就會覺得親切多了。)現在就可以單擊OK按鈕了。然後,單擊 “ClassView”標簽,並展開所有的“+”標志,使得樹型視圖完全展 開。你會在接口(IFirst_ATL)的頂部看到我們的“AddNumbers”方法以及我們 給予它的參數。在這個方法上雙擊鼠標鍵,並插入以下的代碼:
STDMETHODIMP CFirst_ATL::AddNumbers(long Num1,
long Num2, long *ReturnVal)
{
// TODO: Add your implementation code here
*ReturnVal = Num1 + Num2;
return S_OK;
}
第4步:編譯DLL
無論你相信與否,你 已經擁有一個用ATL編寫的COM服務器了!當然,我們還需要編譯它。請按下F7鍵,這樣VC++ 就可以編譯了。編譯器工作片刻後就會在注冊表中注冊你的新DLL了,這樣一來其它的程序就 可以使用它了。讓我們來測試一下。
第5步:在Visual Basic中測試COM服務器
那麼,先讓我們用VB來測試這個COM服務器吧。(如果你沒有VB的話,你可以跳過這 一節,直接在VC++中測試。)啟動VB,並選擇“標准EXE(Standard EXE)”建立 工程,並在對話框上放置一個命令按鈕。現在,我們需要添加COM服務器的引用,請單擊 “工程(Project)”菜單並選擇“引用(References)”,找到 “Simple ATL 1.0 Type Library”並選擇它。
單擊確定(OK)按鈕之後,你可以雙擊先前放置的命令按鈕,VB會切換到這個 按鈕的代碼窗口。添加以下的代碼:
Private Sub Command1_Click()
Dim objTestATL As SIMPLE_ATLLib.First_ATL
Set objTestATL = New First_ATL
Dim lngReturnValue As Long
objTestATL.AddNumbers 5, 7, lngReturnValue
MsgBox "The value of 5 + 7 is: " & lngReturnValue
Set objTestATL = Nothing
End Sub
如果你是個VB的程序員, 那麼這些代碼對於你是很直觀的:我們聲明了一個對象,並從COM服務器調用 “AddNumbers”的方法,然後顯示結果。現在按下F5來運行這個VB工程,單擊命 令按鈕,你就會看到期望的結果了:
並不是很難吧?那麼我們再來一次,這一次用VC++。
第6步:在Visual C++中測試COM服務器
如果你的Simple_ATL工程仍然開著,那麼就關了它並創建一個新 工程。選擇“Win32 Console Application”,起名為“Test_ATL”, 在下一個窗口中單擊OK按鈕接受所有默認值,最後單擊Finish按鈕。現在,你應該有了一個 空工程。那麼,按下Ctrl+N為工程加入一個新文件,選擇“C++ Source File”並 命名為“Test_ATL.cpp”,單擊OK接受。你現在應該有了一個打開的空白文件, 我們需要在其中添加一些代碼來測試COM服務器。代碼如下:
// 你需要指明 Simple_ATL工程的路徑來引用這個頭文件
#include "..\Simple_ATL\Simple_ATL.h"
#include <iostream.h>
// 把以下的內容從Simple_ATL工程目錄的Simple_ATL_i.c文件中復制過來
// 注意:你也 可以直接包含Simple_ATL_i.c文件,我在此只想清楚地表明這些const常量來自何處以及它們 的樣子
const IID IID_IFirst_ATL =
{0xC8F6E230,0x2672,0x11D3,
{0xA8,0xA8,0x00,0x10,0x5A,0xA9,0x43,0xDF}};
const CLSID CLSID_First_ATL =
{0x970599E0,0x2673,0x11D3,
{0xA8,0xA8,0x00,0x10,0x5A,0xA9,0x43,0xDF}};
void main(void)
{
// 聲明一個HRESULT變量以及一個Simple_ATL接口的指針
HRESULT hr;
IFirst_ATL *IFirstATL = NULL;
// 現在初始化COM
hr = CoInitialize(0);
// 使用SUCCEEDED宏來看看我們是否能夠獲得接口的指針
if(SUCCEEDED(hr))
{
hr = CoCreateInstance( CLSID_First_ATL, NULL,
CLSCTX_INPROC_SERVER,
IID_IFirst_ATL, (void**) &IFirstATL);
// 如果成功了,那麼調用AddNumbers方法
// 否則給用戶顯示一條適當的信息
if(SUCCEEDED(hr))
{
long ReturnValue;
IFirstATL->AddNumbers(5, 7, &ReturnValue);
cout << "The answer for 5 + 7 is: "
<< ReturnValue << endl;
IFirstATL->Release();
}
else
{
cout << "CoCreateInstance Failed." << endl;
}
}
// 卸載COM
CoUninitialize();
}
第7步:編譯並運行程序
現在你 可以按下F5鍵來編譯程序,然後按下Ctrl+F5來運行之。你應該可以看到一個DOS窗口,給出 了你所期望的結果。