程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> VC++內部COM插件的編程實現

VC++內部COM插件的編程實現

編輯:關於VC++

一、閒聊

首先,在這裡向前段時間沒來得及回復你們問題的朋友們說 聲對不起了,這段時間工作實在太忙,我快倒!哈哈!好了,讓我們轉入正題, 今天要談的話題是COM,稍微深入一點,不知道大家用過C++Test或者Visual Assistant(可到VC知識庫工具欄目下載)之類的軟件沒有,它們都有個非常引 人注目的功能,那就是把它們自身嵌入到VC開發環境中去。這個功能讓我癡迷不 已,原因只有一個:我想做一個可以嵌入VC開發環境的VC工程解析器(VC/Delphi 工程解析器已被收錄在VC知識庫在線雜志第19期中),這樣用戶在VC開發環境中 就可以直接對當前或所有工程進行各種分析,統計。那麼實現它簡單嗎?簡單, Next和Copy即可輕松完成;僅僅這些嗎?不是,它的背後還有博大精深的COM做 支撐。不管困難與否,還是讓我們先試為快。

二、效果圖

 

三、實現步驟:

<3.1>新建一個<DevStudio Add- in Wizard>類型工程,輸入工程名稱 "CodeAnalyser". 

<3.2>進入第二個畫面,系統 要求用戶輸入插件的名稱和描述信息。並且要求用戶選擇

是否需要生成 工具欄以及是否自動添加VC事件響應代碼。

<3.3>點擊"Finish"結束向導,進入代碼編輯窗口。

在這裡我們要說的一點是:該工程引用了ICommands接口,並從該接口上 派生出 CCommands類。該類完成了所有用戶自定義函數接口,VC應用程序消息響 應和VC調試動作的消息響應工作。當我們真正為CCommands類添加成員函數之前 我們必須先為ICommands接口添加相應的函數接口聲明。在本工程中我總共為 ICommands接口添加了兩個函數接口,它們名字分別為: GetCurDirCommandMethod和QuitCommandMethod聲明如下:(在CodeAnalyer.odl 文件中)

interface ICommands : IDispatch
{
  // methods
  [id(1)] //在Vtable中的函數索引號
  HRESULT GetCurDirCommandMethod(); //得到VC當前工作目錄
  [id(2)]  // 在Vtable中的函數索引號
  HRESULT QuitCommandMethod ();   // 退出VC編輯器
};
在接口ICommands添加接口函數,那麼相應的我們 也要在類CCommands中聲明和實現ICommands接口函數,函數的內部代碼和普通工 程代碼沒什麼區別。

//Implement(CCommands類內部接口函數的聲 明)
public:
  STDMETHOD(GetCurDirCommandMethod)(THIS);
  STDMETHOD(QuitCommandMethod)(THIS);
//Function Code (Ccommands類內部接口函數的實現)
//得到當前VC開發環境的工作目錄[您 也可以讓它成為你想要實現的功能代碼]
STDMETHODIMP CCommands::GetCurDirCommandMethod()
{
  AFX_MANAGE_STATE (AfxGetStaticModuleState());
  VERIFY_OK(m_pApplication- >EnableModeless(VARIANT_FALSE));
  BSTR bstrCurDir;
   m_pApplication->get_CurrentDirectory(&bstrCurDir);
   CString str(bstrCurDir);
  ::MessageBox(NULL, str, "VC工作 目錄", MB_OK | MB_ICONINFORMATION);
  VERIFY_OK (m_pApplication->EnableModeless(VARIANT_TRUE));
  return S_OK;
}
//退出VC開發環境
STDMETHODIMP CCommands::QuitCommandMethod()
{
  AFX_MANAGE_STATE (AfxGetStaticModuleState());
  VERIFY_OK(m_pApplication- >EnableModeless(VARIANT_FALSE));
  if(::MessageBox(NULL,
    "您想退出VC++編輯器嗎(Y/N)?",
    " 詢問信息...",
    MB_YESNO | MB_ICONQUESTION) == IDYES)
      m_pApplication->Quit();
  VERIFY_OK (m_pApplication->EnableModeless(VARIANT_TRUE));
  return S_OK;
}

<3.4> 創建工具欄,連接工具欄按鈕事件

所 有的幕後工作已經准備就緒,只差個工具欄界面就一切OK了。打開類CDSAddIn, 它裡面有三個成員函數,其中OnConnection和OnDisconnection成員函數的意義 非常重要。它們的意義如下:

<1>OnConnection:插件的初始化任 務都在這裡完成。如COM服務的啟動,工具欄/菜單欄的創建,工具欄按鈕/菜單 項的添加與修改等等。

<2>OnDisconnection:插件的卸載工作都 在這裡完成。如COM服務的卸載,工具欄/菜單欄的銷毀,釋放等等。

了 解了它們各自的用途之後我們就可以在相應的消息事件中添加代碼了。很顯然工 具欄的初始化應該在OnConnection事件中完成。

在OnConnection事件中 系統首先獲得了VC應用程序接口,然後調用一個接口函數:AddCommand來為插件 添加命令和命令影射函數。然後再使用另外一個接口函數AddCommandBarButton 向工具欄中添加工具欄按鈕,其中每個工具欄按鈕會和一個命令標志符號相連接 ,這樣就能實現按鈕和命令(消息)之間的一一對應。下面是添加一個命令和一 個工具欄按鈕的代碼(如果你要添加多個工具欄按鈕只要重復此步驟即可):

LPCTSTR szCommand = _T("GetCurDirCommand");
VARIANT_BOOL bRet;
CString strCmdString;
strCmdString.LoadString(IDS_CMD_STRING);
strCmdString = szCommand + strCmdString;
CComBSTR bszCmdString(strCmdString);
CComBSTR bszMethod(_T("GetCurDirCommandMethod"));
CComBSTR bszCmdName(szCommand);  //和下面添加工具欄按鈕對應
VERIFY_OK(pApplication->AddCommand (bszCmdString,bszMethod,0,dwCookie,&bRet));
//AddCommand 參數 含義:
//bszCmdString:命令字符串。
//bszMethod:Icommands接 口函數名。
//第三個參數代表位圖偏移量。
//第四和第五個參數分 貝為系統參數和返回值(參照MSDN的IApplication介紹)
if (bRet == VARIANT_FALSE)
{
  *OnConnection = VARIANT_FALSE;
   return S_OK;
}
//添加工具欄按鈕
if (bFirstTime == VARIANT_TRUE)
{
   VERIFY_OK(pApplication- >AddCommandBarButton(dsGlyph, bszCmdName, m_dwCookie));
}

<3.5> 編譯,連接及在VC中引入插件

以上就是我 們所有的代碼工作,接下來趕快Build以下吧。編譯通過的話,在你的工程Debug 目錄下會有個dll文件。然後打開VC編輯器,在VC任何一個工具欄上點擊鼠標右 鍵,彈出如下圖所示菜單。然後選擇”Customize”子菜單,打開如下 圖所示的工具欄定制窗口:

接著 選擇該窗口的最後一頁"Add-Ins and Macro Files"出現下圖所示窗 口。

然後 點擊”Browse...”按鈕,這時打開你工程下的Debug目錄中的DLL文 件,這樣你就可以看到你制作的工具欄了。同樣你再次打開上面的菜單,這次可 以看到多了一個工具欄,並且名字亂七八糟的,怎麼改變工具欄的名字呢?方法 很簡單:打開上面窗口中的”Toolbars”選項頁,在工具欄列表框中 找到你的工具欄,然後在”Toolbar name”編輯框中輸入你想要的名 字即可。再打開上面的菜單看看名字是不是變了,哈哈!

OK, 今天的話題就聊到這裡,還是老規矩,有什麼問題請MAIL給我,再次祝大家學習 愉快. Bye!

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved