標籤:com 組件編程 執行個體
測試環境: VS2008 + SP1 補丁 XP 32位系統
1、啟動VS2008,建立項目,
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D0/wKioL1PHw17htmhdAAHvKe8xWCQ531.jpg" title="1.jpg" alt="wKioL1PHw17htmhdAAHvKe8xWCQ531.jpg" />
2、再次建立項目,
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D0/wKioL1PHxDjSAzg_AAIuhgFNed0404.jpg" title="1.jpg" alt="wKioL1PHxDjSAzg_AAIuhgFNed0404.jpg" />
需要注意的就是 在 Solution 那裡 選擇 Add to Solution ,同時,上面的 Location 會自動定位到當前的解決方案裡。這個項目,直接點擊Finish 結束就行了。
3、將視圖切換到檔案視圖(View 菜單中的 Solution Explorer) ,
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D0/wKioL1PHxl7ikFiBAAG2IGH781E225.jpg" title="1.jpg" alt="wKioL1PHxl7ikFiBAAG2IGH781E225.jpg" />
可以看到這裡面有 類似 檔案夾的 東東,,它們是 Filter 就是將某一些相同類型的檔案 整理在一起的功能,我們將它們全部摺合起來。
還有一點,我們會看到這裡有兩個項目 ,帶 PS 的那個,我們暫時用不到,直接 在 它上面 右擊,選擇 Remove 即可 ,這樣,我們這個解決方案裡就只有一個 項目 了。
然後,我們 選中 QMath 這個 項目 ,然後在 Project功能表項目 中 選擇 Add Class ,為它添加一個類
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/3E/D1/wKioL1PHx5Lz9MH9AAHNRSaymy4105.jpg" title="1.jpg" alt="wKioL1PHx5Lz9MH9AAHNRSaymy4105.jpg" />
左邊選擇 ATL ,右邊選擇 ATL SIMPLE OBJECT 。然後點擊 ADD。
在彈出的對話方塊中,只需要要在 C++ SHORT NAME 中 寫上 QPrimerMath 即可,
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D1/wKiom1PHxyCSYRf_AAGawumowXo557.jpg" title="1.jpg" alt="wKiom1PHxyCSYRf_AAGawumowXo557.jpg" />
然後點擊下一步,這裡比較重要,我們一定要選擇 Custom
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/3E/D1/wKioL1PHyHrSDR11AAF-4Cli_rE329.jpg" title="1.jpg" alt="wKioL1PHyHrSDR11AAF-4Cli_rE329.jpg" />
然後就可以點擊 Finish了。
切換到類別檢視,我們可以看到 多了 兩個東東,,一個 是 I.... ,這個就是介面啦,一個是C...,這個就是組件類了。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/3E/D1/wKiom1PHx8Lzeuk9AAD0zNJR1uw627.jpg" title="1.jpg" alt="wKiom1PHx8Lzeuk9AAD0zNJR1uw627.jpg" />
然後,我們要為 介面添加 方法 ,在介面 上右擊 ,選擇 Add --> Add Method 彈出圖示對話方塊
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D1/wKiom1PHyEnQU020AAFA3dF3zvI663.jpg" title="1.jpg" alt="wKiom1PHyEnQU020AAFA3dF3zvI663.jpg" />
在這裡面,我們可以 為 我們的介面添加 方法 ,這個 地方的步驟 ,我還是一步一步寫下來吧,
1、輸入 方法名 ,如 Add
2、點擊 in ,然後 參數類型 輸入 LONG 參數名稱 輸入 nA,然後點擊Add ,這樣就添加了一個輸入參數,然後再次點擊 in ,同之前的操作一樣,添加第二個參數,nB ,在COM 中 傳回值是要用指標往外帶值的,但是我們看到 retval 這個參數屬性又是灰掉的,,腫麼辦? 先在 參數類型中 輸入 LONG* ,然後你就看到 out 和 retval 都可以用了,然後輸入 參數名,其它的都一樣操作了。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D2/wKioL1PHys6RMNZ3AAFml7Pp5qY487.jpg" title="1.jpg" alt="wKioL1PHys6RMNZ3AAFml7Pp5qY487.jpg" />
這樣來理解一下,這個函數 叫 Add, 有兩個輸入參數,一個通過指標向外帶的 傳回值,OK。
然後直接 點擊 Finish 就可以了。
在整個過程中,時刻要記得儲存代碼。
下面,我們就在 組件類中 實現代碼
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/3E/D2/wKioL1PHy4LCT1oHAAFrVi1W5Mk109.jpg" title="1.jpg" alt="wKioL1PHy4LCT1oHAAFrVi1W5Mk109.jpg" />
雙擊 這個 Add 方法,然後為它 寫上 實現代碼。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/3E/D2/wKiom1PHytizW8tLAAKSzvj7_d0716.jpg" title="1.jpg" alt="wKiom1PHytizW8tLAAKSzvj7_d0716.jpg" />
好了,然後我們 迅速的 再 做 其它 4 個 方法 ,,Sub,Mul,Div,Mod
,,,,等等,,迅速,怎麼迅速呢?當然是 手工添加啦,因為這些函數 參數都是類似的,,只是函數名 和 實現代碼不同而以。
1、為 介面 添加上 其它 4 個方法 ,如何快速呢? 這裡要告訴你幾個小技巧,快速複製一行,滑鼠只要在當前行,按下 CTRL + C 就複製了當前行,不需要選中哦。雙擊 介面 中的 Add 的聲明 ,定位到了如下 位置
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/3E/D3/wKioL1PHzPWAagdMAAKeshVDPFs361.jpg" title="1.jpg" alt="wKioL1PHzPWAagdMAAKeshVDPFs361.jpg" />
其實它裡面就 一行,
[helpstring("method Add")] HRESULT Add([in] LONG nA, [in] LONG nB, [out,retval] LONG* nResult);
我們只要將 游標 定位 到這一行,注意,不要選中 任何東東,,直接 CTRL + C ,然後 CTRL + V 四次。 效果如
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D3/wKioL1PHzXOijeFgAAJoXsh5AG8235.jpg" title="1.jpg" alt="wKioL1PHzXOijeFgAAJoXsh5AG8235.jpg" />
哈哈,是不是 很方便 ,然後 就是 修改函數名,這裡也有小技巧,,就是 塊選,我先示範一下效果,
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D3/wKioL1PHzcyytYX1AABUCUwyQpg924.jpg" title="1.jpg" alt="wKioL1PHzcyytYX1AABUCUwyQpg924.jpg" />
不只是可以 塊選擇,還可以塊複製 和 粘貼 ,所以嘛,你懂的,,先改 前面的 五個,然後 複製,然後再 選中 後面的 五個,再 粘貼,那麼到底怎麼塊選擇呢,技巧就是 在選擇的時候 按住 ALT 鍵。
其實很多編輯類的軟體都提供了這一功能哦,比如 NOTEPAD++。
介面中 聲明了 這五個方法 了,,在 組件類 中 也要 進行聲明 ,並且 還要實現它們的功能。
直接開啟組件類對應的 標頭檔, 或者 直接 雙擊 組件類 的類名 也可以,在這裡面,我們可以找到 如所示的 Add函式宣告
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/3E/D3/wKioL1PHztyAQ_ExAABnaZgl2uc123.jpg" title="1.jpg" alt="wKioL1PHztyAQ_ExAABnaZgl2uc123.jpg" />
所以嘛,其它的我也不用說了,你都會了,不要忘記 塊操作哦。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/3E/D3/wKiom1PHzhjxcmhYAAEhYH0Uk6M194.jpg" title="1.jpg" alt="wKiom1PHzhjxcmhYAAEhYH0Uk6M194.jpg" />
OK,類中,我們也聲明完了,,接下來,我們就是 要到 類中 實現 操作了。其實,在這裡,還有小技巧,那就是 VS中快速鍵的 定製,我相信你,如果看到這裡了,你的VS 應該是 安裝有 VAX 外掛程式了,,。沒有的話,你可以百度一下 VS2008 VAX 外掛程式了。
然後我們 點擊 工具 菜單下 自訂 ,彈出
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D3/wKioL1PHz76SeXhWAAG12oSCl3k039.jpg" title="1.jpg" alt="wKioL1PHz76SeXhWAAG12oSCl3k039.jpg" />
點擊 左下角 的 鍵盤,
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D4/wKiom1PHzwGilo3pAAIiSXRZyS0155.jpg" title="1.jpg" alt="wKiom1PHzwGilo3pAAIiSXRZyS0155.jpg" />
在 Show commands containing 中 輸入 VAssistX.RefactorCreateIm ,下面的列表中 就會只剩餘一項了,然後 在下面 可以為它 指定 加速鍵 ,我指定為 了 CTRL + Q,按兩次。
好了,我相信你可以搞定它。
那麼這個功能是做什麼用的呢,說白了 就是 為我們 自動 添加 實現代碼的,,然後我們將 滑鼠 放在 組件類 中 聲明 的 Sub 方法 上, 按下 上面的 加速鍵, 會發現,CPP檔案中 自動添加了
如下的 代碼650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D4/wKioL1PH0RqTexyvAACbbOLbIXY434.jpg" title="1.jpg" alt="wKioL1PH0RqTexyvAACbbOLbIXY434.jpg" />
這個時候,如果我們 按 CTRL + TAB 鍵,則會 切換 加 標頭檔中,按一下 下方向鍵,就會定位到 Mul 這三個字母上,然後再 CTRL + Q 兩次,是不是很方便呢。
快速添加完五個函數的實現。
同時呢,我們的五個 函數的 具體實現 也 差不多,只是 運算子不一樣而以,複製行,粘貼,但是在粘貼的時候要注意,這個 複製行 在複製的時候 ,將分行符號也複製了,,而且在 粘貼的時候 是 將資料 粘貼在 滑鼠所在 當前行的 上一行。
所以,我們先 將 滑鼠 放在
*nResult = nA + nB; 這一行上
然後 複製,
STDMETHODIMP CQPrimerMath::Sub( LONG nA, LONG nB, LONG* nResult )
{
return S_OK; 然後將滑鼠 放在 這一行上,再 粘貼
}
上面都是一些技巧,掌握了這些技巧 ,你的效率會高出很多哦。
由於 除法中 nB 是不可以 為0 的,,但是我們只是 為了示範 ,不做 特殊處理。
這樣,我們就 製作了一 個 組件類了,,是不是感覺 很棒呢。
我們編譯產生一下。然後大家去網上下載一個 OLEVIEW 的工具,,VS2008中好像沒有,但 2010中又有了。
開啟這個工具,
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/3E/D4/wKioL1PH0vySs3qNAACEyU031cg610.jpg" title="1.jpg" alt="wKioL1PH0vySs3qNAACEyU031cg610.jpg" />
然後點擊 工具列中 3個紅色箭頭的 表徵圖,然後,開啟我們產生的 DLL 檔案
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/3E/D4/wKioL1PH04Hwlg_bAAEd729UqdA572.jpg" title="1.jpg" alt="wKioL1PH04Hwlg_bAAEd729UqdA572.jpg" />
好,我們按上面的方法 ,再添加一個組件類,名字叫做 QAdvancedMath ,注意一定要選擇 CUSTOM 。
為它添加 一個 求 階乘的 方法。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/3E/D5/wKiom1PH03Oznk9MAADhpDMuy48535.jpg" title="1.jpg" alt="wKiom1PH03Oznk9MAADhpDMuy48535.jpg" />
很簡單,然後我們再產生 一下。
哦,我的產生出錯了。
1>LINK : fatal error LNK1168: cannot open Debug\QMath.dll for writing
這是因為我的OLEVIEW 還在使用著 這個DLL,所以 要關掉它。
然後再產生 就OK了。
再用工具查看一下
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/3E/D5/wKioL1PH1Q3wZLs8AAEG4ajN9Iw156.jpg" title="1.jpg" alt="wKioL1PH1Q3wZLs8AAEG4ajN9Iw156.jpg" />
我們發現,我們這裡有兩個 COCLASS,也叫做 組件類,下面,我們要 來 畫一下,這裡面的 繼承關係
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/3E/D5/wKiom1PH1cHzkPPTAAEVlI1JRCw527.jpg" title="1.jpg" alt="wKiom1PH1cHzkPPTAAEVlI1JRCw527.jpg" />
好,這就是 它的 最基本的 繼承 圖表啦。。當然 ,中間的 兩個 介面 還 繼承了 其它 的 介面,這個暫時不討論它。
中 的 第三層,,是表示 組件類的,,每個組件類 都有一個 類ID,也叫 CLSID ,其形式 表示為 CLSID_類名 ,但是類名 是要 去年 最前面的 字母 C 的。
中 的 第二層,,是表示 介面的,每個介面也都有一個 介面ID,也叫 IID,其形式 表示 為
IID_I類名 ,但是類名 是要 去年 最前面的 字母 C 的。
因為組件類 是 二進位 共用的 ,所以 每個 組件類 實現的 功能 只能由 介面負責 調用,為了區分開 所有的 組件類,就使用了上面的 類ID 和 介面ID。
在OLEVIEW 裡,可以看到它們的具體定義。
好了,既然是 共用使用的,那麼我們就示範一下 在MFC 中 如何使用 它。
點擊 File -- Add -- Add New Project 選擇MFC 應用程式,
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D6/wKiom1PH15zgMXM-AAHm2w76Lzs497.jpg" title="1.jpg" alt="wKiom1PH15zgMXM-AAHm2w76Lzs497.jpg" />
下面的有一步 要對著 所示進行選擇
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/3E/D6/wKiom1PH2BaTWp6hAAH1_wEQYOQ477.jpg" style="float:none;" title="1.jpg" alt="wKiom1PH2BaTWp6hAAH1_wEQYOQ477.jpg" />
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/3E/D6/wKioL1PH2TDww-3cAAGuzGgg-is009.jpg" style="float:none;" title="2.jpg" alt="wKioL1PH2TDww-3cAAGuzGgg-is009.jpg" />
這裡選擇 Active Accessibility 主要是 讓 MFC 做 COM 的自動 初始化 ,加上這句話後,在
BOOL CTestQMathApp::InitInstance() 中 會添加如下 語句。
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
然後,我們 在對話方塊 中 添加 兩個 按鈕
ID 分別為
IDC_BTN_PRIMER_MATH
IDC_BTN_ADVANCED_MATH
標題分別為
Test Primer Math
Test Advanced Math
添加響應函數
void CTestQMathDlg::OnBnClickedBtnPrimerMath(){ IQPrimerMath * pPrimerMath = NULL; HRESULT hr = CoCreateInstance(CLSID_QPrimerMath,NULL,CLSCTX_INPROC_SERVER,IID_IQPrimerMath,(LPVOID *)&pPrimerMath); if (FAILED(hr)) return; LONG n1 = 100,n2 = 25, nResult = 0; pPrimerMath->Add(n1,n2,&nResult); pPrimerMath->Sub(n1,n2,&nResult); pPrimerMath->Mul(n1,n2,&nResult); pPrimerMath->Div(n1,n2,&nResult); pPrimerMath->Mod(n1,n2,&nResult); pPrimerMath->Release(); CoFreeUnusedLibraries();}void CTestQMathDlg::OnBnClickedBtnAdvancedMath(){ IQAdvancedMath * pAdvancedMath = NULL; HRESULT hr = CoCreateInstance(CLSID_QAdvancedMath,NULL,CLSCTX_INPROC_SERVER,IID_IQAdvancedMath,(LPVOID *)&pAdvancedMath); if (FAILED(hr)) return; LONG nVal = 10 ,nResult = 0; pAdvancedMath->Factorial(nVal,&nResult); SetDlgItemInt(IDC_BTN_ADVANCED_MATH,nResult); pAdvancedMath->Release(); CoFreeUnusedLibraries();}
好了,一編譯會出很多錯誤。
這是為什麼呢,因為我們沒有引入相關的定義,這些定義在哪裡呢? 我們DLL 項目中 還有一個過濾器呢,就是它們兩個啦,只要將它們 加入 我們 的 對話方塊 項目 中就 可以了。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/3E/D8/wKioL1PH3G-S3AnkAADR-fr-iNg701.jpg" title="1.jpg" alt="wKioL1PH3G-S3AnkAADR-fr-iNg701.jpg" />
#include "../QMath/QMath_i.h"
#include "../QMath/QMath_i.c"
好了,最後呢,我們的代碼 還是有一個小問題呢,,就留給大家去發現,,去解決啦。。。
TIPS: 就是 求 階乘 那裡,,,我們沒有 對 *nResult 賦值為 1,所以結果 一直是 0.。大家自己改改吧,,我們不是來說明這些東西的,,大家要弄清楚 重點。
好了,,就倒這裡,,,2個半小時 過去了。。。
本文出自 “千千闕歌” 部落格,謝絕轉載!