c++簡單的ATL COM開發和調用實例
1、打開VS2010。新建ATL COM 項目。步驟:“文件” --》“新建” --》“項目”,選擇“Visual C++” --》“ATL 項目” ,填寫“名稱” FirstCOM --》“確定”。
2、ATL 項目向導,勾選 【支持COM+ 1.0】和【支持部件註冊器】,其它默認。點擊完畢。
3、切換到類視圖。右鍵單擊項目“FirstCOM”--》“加入”? --》“類”。
?
4、選“ATL”? --》“ATL 簡單對象” --》“加入”。
5、ATL? 簡單對象向導,“簡稱”中輸入類名稱FirstClass,其它輸入框會自己主動填寫,最以下的“ProgID”沒有自己主動填寫,最好自己寫上一個,如FirstCOM.math,否則後面無法正確調用組件,點擊“完畢”。假設出現提示【是否覆蓋現有文件】,點擊【是】就可以。
6、切換到類視圖。選中剛才加入的接口IFirstClass。例如以下,然後右鍵單擊【加入】加入方法。
?
7、加入方法向導,在"方法名"? 下輸入Add。添加兩個輸入參數:勾選【in】。選擇參數類型LONG,輸入參數名para1,點擊“加入”。相同操作添加參數para2。
然後添加一個返回參數:先選擇參數類型LONG*,再勾選【retval】,輸入參數名result。點擊加入。點擊“完畢”就可以,假設點擊下一步,不須要填寫信息,點擊“完畢”就可以。
8、切換到解決方式資源管理器,展開項目“源文件”, 雙擊 FirstCom.idl?打開IDL定義文件。看到例如以下代碼,就是定義的COM方法了。
?
9、雙擊打開FirstClass.cpp? 編輯代碼:*result = para1 + para2
[cpp]?view plaincopy- #include?"stdafx.h"??#include?"FirstClass.h"????
- //?CFirstClass????
- STDMETHODIMP?CFirstClass::Add(LONG?para1,?LONG?para2,?LONG*?result)????
- {????
- ????//?TODO:?在此加入實現代碼????
- ?????*result?=?para1?+?para2;????
-
???return?S_OK;????
- }????
?
10、編譯執行,會生成dll文件。並自己主動註冊到系統中。
?
問題及解決方法
問題1:我在Win64位系統中編譯的,出現錯誤:無法打開預編譯頭文件:“Debug\FirstCOM.pch”:No such file or directory。
解決:右鍵點擊你創建的項目,選擇“屬性”,彈出“FirstCOM 屬性頁”,在左側展開"配置屬性"--》展開“C/C++”--》選中“預編譯頭”。在右邊的“預編譯頭”下拉菜單中選擇“不使用預編譯頭文件”,點擊“確定”button退出。
原因分析:編譯器一般都是以文件為單位進行編譯,假設改動了project中的一個文件。那麽將導致全部文件都要又一次編譯,這種編譯將耗費非常長時間。為了提高編譯速度,將那些不常被改動,比較穩定,文件單獨包括到一個指定的頭文件中。然後生成一個預編譯頭文件 *.pch 。?VC++中默認的頭文件為 stdAfx.h。 但光有頭文件無法編譯,所以還要用到StdAfx.cpp,StdAfx.cpp裏僅僅包括一句有效代碼,這樣編譯時。通過編譯 stdAfx.cpp就把大部分系統頭文件編譯進來。 Debug文件夾下便會產生一個 存儲了預編譯信息的 *.pch 文件。
假設 *.pch文件損壞或者不存在。就會出現“問題1”所看到的的無法打開預編譯頭文件的錯。
如需深究。可參考博客:無法打開包括文件:“Stdfx.h”
問題2:攻克了問題1之後。又出現:errorMSB8011: 未能註冊輸出。請嘗試啟用“逐用戶重定向”,或者使用提升的權限從命令提示符處註冊該組件。
解決:項目-》屬性-》鏈接器-》逐用戶重定向--》設置為?true??(該方案網上常見,但仍“未能”根本解決這個問題)
分析: 因為win7權限問題。所以出現故障3。須要通過使用命令提示符來幫助註冊該組件。
問題3:無法啟動程序:“I:\VSProject\FirstCOM\Debug\FirstCOM.dll”。
解決:程序 --》 附件?--》 命令提示符,在”命令提示符“上點擊鼠標右鍵,選擇”以管理員身份執行“命令,這個時候將打開Dos命令窗體。
接下來輸入:regsvr32 ? “I:\VS Project\FirstCOM\Debug\FirstCOM.dll” ?(就是?regsvr32+.dll文件所在的全然路徑了。全路徑最好用引號括起來)
按Enter 鍵,就能夠註冊成功了。
?
?
以下簡介怎樣調用COM組件。
1、在MFC中調用有一種非常方便的方法,就是通過ClassWizard利用類型庫生成包裝類,只是有個前提就是com組件的接口必須是派生自IDispatch。
詳細方法:
(1)VS2010新建一個MFC基於對話框程序。調出類向導,點擊“加入類”下拉菜單,選擇“類型庫中的MFC類”(From?a?type?libarary)。
(2)選“註冊表”,然後在“可用類型庫”中定位到FirstCOMLib<1.0>,接下來會出來該庫中的全部接口,選擇你想生成的接口包裝類IFirstClass後點擊“完畢”。向導會自己主動生成對應的.h文件,這樣你就能夠在你的MFCproject中像使用普通類那樣使用COM組件了.
(3)代碼編寫:
首先引入頭文件 ??#include "CFirstClass.h"
為對話框程序加入一個“測試”button,加入button單擊響應函數
?
[cpp]?view plaincopy- void?CFirstCOMTestDlg::OnBnClickedButton1()????
- {????
- ????//?TODO:?在此加入控件通知處理程序代碼????
- ????CoInitialize(NULL);????
- ????CFirstClass?m_mymath;????
- ????if?(!m_mymath.CreateDispatch(_T("FirstCOM.math.1")))//創建COM對象:這裏的字符串一定要和註冊表中的ProgID一致!!!?????
- ????{????
- ????????MessageBox(_T("創建COM組件失敗:請檢查ProgID是否正確,組件是否已經註冊"));????
- ????????return;????
- ????}????
- ????else????
- ????{????
- ????????long?ret?=?m_mymath.Add(1,2);//調用COM接口?????
- ????????CString?strTemp;????
- ????????strTemp.Format(_T("%d"),ret);????
- ????????MessageBox(strTemp);????
- ????}????
- ????CoUninitialize();????
- }????
?
關於m_mymath.CreateDispatch(_T("FirstCOM.math.1")) 中字符串"FirstCOM.math.1",事實上跟我們上一章中定義類時ProgID有關,假設忘記,能夠在FirstClass.rgs文件中找。rgs是組件註冊的腳本文件,當你用 Regsvr32.exe註冊組件時,組件內部便是調用了這個文件。rgs文件是以資源的形式存於DLL內的。
?
[cpp]?view plaincopy- KCR????
- {????
- ????FirstCOM.math.1?=?s?‘FirstClass?Class‘????
- ????{????
- ????????CLSID?=?s?‘{C56D80DE-DA4C-4731-81A6-48B8D0BDB2FD}‘????
- ????}????
- ????FirstCOM.math?=?s?‘FirstClass?Class‘????
- ????{???????????
- ????????CurVer?=?s?‘FirstCOM.math.1‘????
- ????}????
?
當中 CurVer=s‘FirstCOM.math.1‘ 中的?FirstCOM.math.1?就是我們須要的那個字符串。
?
4)編譯執行,點擊測試button。結果例如以下:
?
2、在SDK中調用最簡單最經常使用的一種,用#import導入類型庫,利用VC提供的智能指針包裝類
VS2010創建Win32控制臺應用程序。編寫例如以下代碼:
?
?
[cpp]?view plaincopy- #include?"stdafx.h"??
- ??
- #include?"atlcomcli.h"??
- #import?"FirstCOM.dll"?no_namespace??
- ??
- int?_tmain(int?argc,?_TCHAR*?argv[])??
- {??
- ????CoInitialize(NULL);??
- ????CLSID?clsid;??
- ????CLSIDFromProgID(OLESTR("FirstCOM.math.1"),&clsid);??
- ????CComPtr<IFirstClass>?pFirstClass;//智能指針??
- ????pFirstClass.CoCreateInstance(clsid);??
- ????long?ret?=?pFirstClass->Add(1,2);??
- ????printf("%d\n",ret);??
- ????pFirstClass.Release();??
- ????CoUninitialize();??
- ??
- ????return?0;??
- }??
- #include?"stdafx.h"??
- ??
- #include?"atlcomcli.h"??
- #import?"FirstCOM.dll"?no_namespace??
- ??
- int?_tmain(int?argc,?_TCHAR*?argv[])??
- {??
- ????CoInitialize(NULL);??
- ????CLSID?clsid;??
- ????CLSIDFromProgID(OLESTR("FirstCOM.math.1"),&clsid);??
- ????CComPtr<IFirstClass>?pFirstClass;//智能指針??
- ????pFirstClass.CoCreateInstance(clsid);??
- ????long?ret?=?pFirstClass->Add(1,2);??
- ????printf("%d\n",ret);??
- ????pFirstClass.Release();??
- ????CoUninitialize();??
- ??
- ????return?0;??
- }??
當中頭文件atlcomcli.h中定義了智能指針CComPtr。
c++簡單的ATL COM開發和調用實例