VC++內(nèi)部COM插件的編程實(shí)現(xiàn)
Posted on 2006-09-30 22:58 Coolfiry 閱讀(283) 評(píng)論(0) 編輯 收藏 所屬分類: C/C++
一、閑聊
今天要談的話題是COM,稍微深入一點(diǎn),不知道大家用過C++Test或者Visual Assistant之類的軟件沒有,它們都有個(gè)非常引人注目的功能,那就是把它們自身嵌入到VC開發(fā)環(huán)境中去。這個(gè)功能讓我癡迷不已,原因只有一個(gè):我想做一個(gè)可以嵌入VC開發(fā)環(huán)境的VC工程解析器,這樣用戶在VC開發(fā)環(huán)境中就可以直接對(duì)當(dāng)前或所有工程進(jìn)行各種分析,統(tǒng)計(jì)。那么實(shí)現(xiàn)它簡(jiǎn)單嗎?簡(jiǎn)單,Next和Copy即可輕松完成;僅僅這些嗎?不是,它的背后還有博大精深的COM做支撐。不管困難與否,還是讓我們先試為快。
二、效果圖
三、實(shí)現(xiàn)步驟:
<3.1>新建一個(gè)<DevStudio Add-in Wizard>類型工程,輸入工程名稱"CodeAnalyser".
<3.2>進(jìn)入第二個(gè)畫面,系統(tǒng)要求用戶輸入插件的名稱和描述信息。并且要求用戶選擇是否需要生成工具欄以及是否自動(dòng)添加VC事件響應(yīng)代碼。
<3.3>點(diǎn)擊"Finish"結(jié)束向?qū)ВM(jìn)入代碼編輯窗口。
在這里我們要說的一點(diǎn)是:該工程引用了ICommands接口,并從該接口上派生出 CCommands類。該類完成了所有用戶自定義函數(shù)接口,VC應(yīng)用程序消息響應(yīng)和VC調(diào)試動(dòng)作的消息響應(yīng)工作。當(dāng)我們真正為CCommands類添加成員函數(shù)之前我們必須先為ICommands接口添加相應(yīng)的函數(shù)接口聲明。在本工程中我總共為ICommands接口添加了兩個(gè)函數(shù)接口,它們名字分別為:GetCurDirCommandMethod和QuitCommandMethod聲明如下:(在CodeAnalyer.odl文件中)
在接口ICommands添加接口函數(shù),那么相應(yīng)的我們也要在類CCommands中聲明和實(shí)現(xiàn)ICommands接口函數(shù),函數(shù)的內(nèi)部代碼和普通工程代碼沒什么區(qū)別。
<3.4> 創(chuàng)建工具欄,連接工具欄按鈕事件
所有的幕后工作已經(jīng)準(zhǔn)備就緒,只差個(gè)工具欄界面就一切OK了。打開類CDSAddIn,它里面有三個(gè)成員函數(shù),其中OnConnection和OnDisconnection成員函數(shù)的意義非常重要。它們的意義如下:
<1>OnConnection:插件的初始化任務(wù)都在這里完成。如COM服務(wù)的啟動(dòng),工具欄/菜單欄的創(chuàng)建,工具欄按鈕/菜單項(xiàng)的添加與修改等等。
<2>OnDisconnection:插件的卸載工作都在這里完成。如COM服務(wù)的卸載,工具欄/菜單欄的銷毀,釋放等等。
了解了它們各自的用途之后我們就可以在相應(yīng)的消息事件中添加代碼了。很顯然工具欄的初始化應(yīng)該在OnConnection事件中完成。
在OnConnection事件中系統(tǒng)首先獲得了VC應(yīng)用程序接口,然后調(diào)用一個(gè)接口函數(shù):AddCommand來為插件添加命令和命令影射函數(shù)。然后再使用另外一個(gè)接口函數(shù)AddCommandBarButton向工具欄中添加工具欄按鈕,其中每個(gè)工具欄按鈕會(huì)和一個(gè)命令標(biāo)志符號(hào)相連接,這樣就能實(shí)現(xiàn)按鈕和命令(消息)之間的一一對(duì)應(yīng)。下面是添加一個(gè)命令和一個(gè)工具欄按鈕的代碼(如果你要添加多個(gè)工具欄按鈕只要重復(fù)此步驟即可):
<3.5> 編譯,連接及在VC中引入插件
以上就是我們所有的代碼工作,接下來趕快Build以下吧。編譯通過的話,在你的工程Debug目錄下會(huì)有個(gè)dll文件。然后打開VC編輯器,在VC任何一個(gè)工具欄上點(diǎn)擊鼠標(biāo)右鍵,彈出如下圖所示菜單。然后選擇”Customize”子菜單,打開如下圖所示的工具欄定制窗口:
接著選擇該窗口的最后一頁"Add-Ins and Macro Files"出現(xiàn)下圖所示窗口。
然后點(diǎn)擊”Browse...”按鈕,這時(shí)打開你工程下的Debug目錄中的DLL文件,這樣你就可以看到你制作的工具欄了。同樣你再次打開上面的菜單,這次可以看到多了一個(gè)工具欄,并且名字亂七八糟的,怎么改變工具欄的名字呢?方法很簡(jiǎn)單:打開上面窗口中的”Toolbars”選項(xiàng)頁,在工具欄列表框中找到你的工具欄,然后在”Toolbar name”編輯框中輸入你想要的名字即可。再打開上面的菜單看看名字是不是變了,哈哈!
OK,今天的話題就聊到這里。
今天要談的話題是COM,稍微深入一點(diǎn),不知道大家用過C++Test或者Visual Assistant之類的軟件沒有,它們都有個(gè)非常引人注目的功能,那就是把它們自身嵌入到VC開發(fā)環(huán)境中去。這個(gè)功能讓我癡迷不已,原因只有一個(gè):我想做一個(gè)可以嵌入VC開發(fā)環(huán)境的VC工程解析器,這樣用戶在VC開發(fā)環(huán)境中就可以直接對(duì)當(dāng)前或所有工程進(jìn)行各種分析,統(tǒng)計(jì)。那么實(shí)現(xiàn)它簡(jiǎn)單嗎?簡(jiǎn)單,Next和Copy即可輕松完成;僅僅這些嗎?不是,它的背后還有博大精深的COM做支撐。不管困難與否,還是讓我們先試為快。
二、效果圖
![]() |
三、實(shí)現(xiàn)步驟:
<3.1>新建一個(gè)<DevStudio Add-in Wizard>類型工程,輸入工程名稱"CodeAnalyser".
<3.2>進(jìn)入第二個(gè)畫面,系統(tǒng)要求用戶輸入插件的名稱和描述信息。并且要求用戶選擇是否需要生成工具欄以及是否自動(dòng)添加VC事件響應(yīng)代碼。
![]() |
<3.3>點(diǎn)擊"Finish"結(jié)束向?qū)ВM(jìn)入代碼編輯窗口。
在這里我們要說的一點(diǎn)是:該工程引用了ICommands接口,并從該接口上派生出 CCommands類。該類完成了所有用戶自定義函數(shù)接口,VC應(yīng)用程序消息響應(yīng)和VC調(diào)試動(dòng)作的消息響應(yīng)工作。當(dāng)我們真正為CCommands類添加成員函數(shù)之前我們必須先為ICommands接口添加相應(yīng)的函數(shù)接口聲明。在本工程中我總共為ICommands接口添加了兩個(gè)函數(shù)接口,它們名字分別為:GetCurDirCommandMethod和QuitCommandMethod聲明如下:(在CodeAnalyer.odl文件中)
interface ICommands : IDispatch { // methods [id(1)] //在Vtable中的函數(shù)索引號(hào) HRESULT GetCurDirCommandMethod(); //得到VC當(dāng)前工作目錄 [id(2)] //在Vtable中的函數(shù)索引號(hào) HRESULT QuitCommandMethod (); //退出VC編輯器 }; |
在接口ICommands添加接口函數(shù),那么相應(yīng)的我們也要在類CCommands中聲明和實(shí)現(xiàn)ICommands接口函數(shù),函數(shù)的內(nèi)部代碼和普通工程代碼沒什么區(qū)別。
//Implement(CCommands類內(nèi)部接口函數(shù)的聲明) public: STDMETHOD(GetCurDirCommandMethod)(THIS); STDMETHOD(QuitCommandMethod)(THIS); //Function Code(Ccommands類內(nèi)部接口函數(shù)的實(shí)現(xiàn)) //得到當(dāng)前VC開發(fā)環(huán)境的工作目錄[您也可以讓它成為你想要實(shí)現(xiàn)的功能代碼] 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開發(fā)環(huán)境 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> 創(chuàng)建工具欄,連接工具欄按鈕事件
所有的幕后工作已經(jīng)準(zhǔn)備就緒,只差個(gè)工具欄界面就一切OK了。打開類CDSAddIn,它里面有三個(gè)成員函數(shù),其中OnConnection和OnDisconnection成員函數(shù)的意義非常重要。它們的意義如下:
<1>OnConnection:插件的初始化任務(wù)都在這里完成。如COM服務(wù)的啟動(dòng),工具欄/菜單欄的創(chuàng)建,工具欄按鈕/菜單項(xiàng)的添加與修改等等。
<2>OnDisconnection:插件的卸載工作都在這里完成。如COM服務(wù)的卸載,工具欄/菜單欄的銷毀,釋放等等。
了解了它們各自的用途之后我們就可以在相應(yīng)的消息事件中添加代碼了。很顯然工具欄的初始化應(yīng)該在OnConnection事件中完成。
在OnConnection事件中系統(tǒng)首先獲得了VC應(yīng)用程序接口,然后調(diào)用一個(gè)接口函數(shù):AddCommand來為插件添加命令和命令影射函數(shù)。然后再使用另外一個(gè)接口函數(shù)AddCommandBarButton向工具欄中添加工具欄按鈕,其中每個(gè)工具欄按鈕會(huì)和一個(gè)命令標(biāo)志符號(hào)相連接,這樣就能實(shí)現(xiàn)按鈕和命令(消息)之間的一一對(duì)應(yīng)。下面是添加一個(gè)命令和一個(gè)工具欄按鈕的代碼(如果你要添加多個(gè)工具欄按鈕只要重復(fù)此步驟即可):
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); //和下面添加工具欄按鈕對(duì)應(yīng) VERIFY_OK(pApplication->AddCommand(bszCmdString,bszMethod,0,dwCookie,&bRet)); //AddCommand 參數(shù)含義: //bszCmdString:命令字符串。 //bszMethod:Icommands接口函數(shù)名。 //第三個(gè)參數(shù)代表位圖偏移量。 //第四和第五個(gè)參數(shù)分貝為系統(tǒng)參數(shù)和返回值(參照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目錄下會(huì)有個(gè)dll文件。然后打開VC編輯器,在VC任何一個(gè)工具欄上點(diǎn)擊鼠標(biāo)右鍵,彈出如下圖所示菜單。然后選擇”Customize”子菜單,打開如下圖所示的工具欄定制窗口:
![]() ![]() |
接著選擇該窗口的最后一頁"Add-Ins and Macro Files"出現(xiàn)下圖所示窗口。
![]() |
然后點(diǎn)擊”Browse...”按鈕,這時(shí)打開你工程下的Debug目錄中的DLL文件,這樣你就可以看到你制作的工具欄了。同樣你再次打開上面的菜單,這次可以看到多了一個(gè)工具欄,并且名字亂七八糟的,怎么改變工具欄的名字呢?方法很簡(jiǎn)單:打開上面窗口中的”Toolbars”選項(xiàng)頁,在工具欄列表框中找到你的工具欄,然后在”Toolbar name”編輯框中輸入你想要的名字即可。再打開上面的菜單看看名字是不是變了,哈哈!
![]() |
OK,今天的話題就聊到這里。