天天看點

VC++内部COM插件的程式設計實作

作者:李曉飛

下載下傳本文示例工程

VC++内部COM插件的程式設計實作

一、閑聊

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

VC++内部COM插件的程式設計實作

二、效果圖

VC++内部COM插件的程式設計實作
VC++内部COM插件的程式設計實作

三、實作步驟:

VC++内部COM插件的程式設計實作

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

VC++内部COM插件的程式設計實作

<3.2>進入第二個畫面,系統要求使用者輸入插件的名稱和描述資訊。并且要求使用者選擇

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

VC++内部COM插件的程式設計實作
VC++内部COM插件的程式設計實作

<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;
}      
VC++内部COM插件的程式設計實作

<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));
}      
VC++内部COM插件的程式設計實作

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

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

VC++内部COM插件的程式設計實作
VC++内部COM插件的程式設計實作

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

VC++内部COM插件的程式設計實作

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

VC++内部COM插件的程式設計實作

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

VC++内部COM插件的程式設計實作
輸入您的搜尋字詞 送出搜尋表單
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

繼續閱讀