1. 程式人生 > >c++簡單的ATL COM開發和調用實例

c++簡單的ATL COM開發和調用實例

信息 rect c++ director geb 啟動 dex oid comm

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
  1. #include?"stdafx.h"??#include?"FirstClass.h"????
  2. //?CFirstClass????
  3. STDMETHODIMP?CFirstClass::Add(LONG?para1,?LONG?para2,?LONG*?result)????
  4. {????
  5. ????//?TODO:?在此加入實現代碼????
  6. ?????*result?=?para1?+?para2;????
  7. ???return?S_OK;????
  8. }????


?

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
  1. void?CFirstCOMTestDlg::OnBnClickedButton1()????
  2. {????
  3. ????//?TODO:?在此加入控件通知處理程序代碼????
  4. ????CoInitialize(NULL);????
  5. ????CFirstClass?m_mymath;????
  6. ????if?(!m_mymath.CreateDispatch(_T("FirstCOM.math.1")))//創建COM對象:這裏的字符串一定要和註冊表中的ProgID一致!!!?????
  7. ????{????
  8. ????????MessageBox(_T("創建COM組件失敗:請檢查ProgID是否正確,組件是否已經註冊"));????
  9. ????????return;????
  10. ????}????
  11. ????else????
  12. ????{????
  13. ????????long?ret?=?m_mymath.Add(1,2);//調用COM接口?????
  14. ????????CString?strTemp;????
  15. ????????strTemp.Format(_T("%d"),ret);????
  16. ????????MessageBox(strTemp);????
  17. ????}????
  18. ????CoUninitialize();????
  19. }????


?

關於m_mymath.CreateDispatch(_T("FirstCOM.math.1")) 中字符串"FirstCOM.math.1",事實上跟我們上一章中定義類時ProgID有關,假設忘記,能夠在FirstClass.rgs文件中找。rgs是組件註冊的腳本文件,當你用 Regsvr32.exe註冊組件時,組件內部便是調用了這個文件。rgs文件是以資源的形式存於DLL內的。

?

[cpp]?view plaincopy
  1. KCR????
  2. {????
  3. ????FirstCOM.math.1?=?s?‘FirstClass?Class‘????
  4. ????{????
  5. ????????CLSID?=?s?‘{C56D80DE-DA4C-4731-81A6-48B8D0BDB2FD}‘????
  6. ????}????
  7. ????FirstCOM.math?=?s?‘FirstClass?Class‘????
  8. ????{???????????
  9. ????????CurVer?=?s?‘FirstCOM.math.1‘????
  10. ????}????


?

當中 CurVer=s‘FirstCOM.math.1‘ 中的?FirstCOM.math.1?就是我們須要的那個字符串。

?

4)編譯執行,點擊測試button。結果例如以下:

技術分享圖片

?

2、在SDK中調用最簡單最經常使用的一種,用#import導入類型庫,利用VC提供的智能指針包裝類

VS2010創建Win32控制臺應用程序。編寫例如以下代碼:

?

?

[cpp]?view plaincopy
  1. #include?"stdafx.h"??
  2. ??
  3. #include?"atlcomcli.h"??
  4. #import?"FirstCOM.dll"?no_namespace??
  5. ??
  6. int?_tmain(int?argc,?_TCHAR*?argv[])??
  7. {??
  8. ????CoInitialize(NULL);??
  9. ????CLSID?clsid;??
  10. ????CLSIDFromProgID(OLESTR("FirstCOM.math.1"),&clsid);??
  11. ????CComPtr<IFirstClass>?pFirstClass;//智能指針??
  12. ????pFirstClass.CoCreateInstance(clsid);??
  13. ????long?ret?=?pFirstClass->Add(1,2);??
  14. ????printf("%d\n",ret);??
  15. ????pFirstClass.Release();??
  16. ????CoUninitialize();??
  17. ??
  18. ????return?0;??
  19. }??
[cpp]?view plaincopy
  1. #include?"stdafx.h"??
  2. ??
  3. #include?"atlcomcli.h"??
  4. #import?"FirstCOM.dll"?no_namespace??
  5. ??
  6. int?_tmain(int?argc,?_TCHAR*?argv[])??
  7. {??
  8. ????CoInitialize(NULL);??
  9. ????CLSID?clsid;??
  10. ????CLSIDFromProgID(OLESTR("FirstCOM.math.1"),&clsid);??
  11. ????CComPtr<IFirstClass>?pFirstClass;//智能指針??
  12. ????pFirstClass.CoCreateInstance(clsid);??
  13. ????long?ret?=?pFirstClass->Add(1,2);??
  14. ????printf("%d\n",ret);??
  15. ????pFirstClass.Release();??
  16. ????CoUninitialize();??
  17. ??
  18. ????return?0;??
  19. }??

當中頭文件atlcomcli.h中定義了智能指針CComPtr。

c++簡單的ATL COM開發和調用實例