來源: 盧小昊的日志
手把手教你給VC++編寫插件
下午偶然注意到VC++6.0新建工程標簽頁下的DevStudio Add-in Wizard,沒有接觸過,看名字是給Developer Studio開發插件,心生喜感,於是百度之,發生百度檢索幾乎找不到一篇完整的文字講述這個wizard的使用,所以在CSDN搜了搜,費盡周折下載了一個只有幾行實際代碼的demo,同時在MSDN提供的實例中看到了類似的demo,研究了幾個小時,基本理清了這種插件的編寫過程,總結出來,以供大家交流。IDE插件的用處不言而喻,大名鼎鼎的Bound Check和Visual Assist X都屬於這類插件。但我剛剛接觸,水平很有限,更多地是希望得到有共同愛好的朋友的指教。
鑒於各種“手把手教你XXX”文體橫行,我也來手把手一次吧。
我這里的環境是Visual C++ 6.0,相信其他Visual Studio版本的方法是大同小異的。
1. 創建工程。啟動VC++,新建一個DevStudio Add-in Wizard工程,如圖,比如我這里命名為Addin,確定。
工程設置,這里填寫你給插件的描述,這將在Visual Studio裝載插件時在列表中顯示。比如我寫Addin by Lusta。
上圖中2個復選框最好都選上,第一個使工程有默認的按鈕工具條,第二個使該工程默認重寫了響應Developer Studio事件的函數。確認。
2. 相關准備。進入工程,查看Class View,會發現它自動生成了這么幾個類。
其中,CXXXApp的作用相當於其他一般工程類型中的App類,比如MFC中的CWinApp類,是整個可執行程序或者鏈接庫的啟動類。
CCommands類負責完成從界面觸發的操作,具體的細節我也講不清楚,因為這里用到了COM組件,似乎。我不是很了解,基本只是摸清了大概的框架。
CDSAddIn類,完成某些初始化工作。具體描述在MSDN中可以找到,MSDN中有關於插件開發的幾篇文章。我沒有細看,主要得研究代碼才懂。
ICommands,聲明為interface ICommands : IDispatch{}; 我也看不懂了,interface ICommands不知道是屬於什么類或者什么組件,COM技術?但是我看懂了這其中的函數實際就是響應VC界面上插件工具條按鈕點擊的代碼實體。
Globals變量中有不少內容,但都屬於Wizard生成,可以不管。
對了,我們還沒有想好編寫的這個插件得有些什么功能。這些決定了我們要在ICommands中寫進一些什么函數。
比如,我經常用windows記事本來臨時做一些大段代碼的批量處理,替換,查找,要比VC自身提供的功能方便很多,所以我們在這里給插件添加一個啟動windows記事本的功能。
windows還有一些小工具也很實用,比如我的專業是遙感,所以經常是做圖像處理,偶爾會用windows畫圖工具來截取圖片或者轉換圖像格式,所以也可以把啟動MSPaint添加插件工具條按鈕中。這些沒必要細說,我這里還添加了啟動計算器的功能,因為Visual Studio調試並不提供手動計算的功能,比如你計算某幅位圖的存儲寬度。另外,增加一個通過百度搜索某一關鍵字的功能,以及關於本插件的信息。
3.編寫代碼。使用向導,右擊類視圖中的ICommands,點擊Add Method,似乎這里都是叫方法,不叫函數。注意:ICommands中已經默認生成了一個叫做AddinCommandMethod的方法,你可以刪除它,也可以重寫它做自己的事。Add Method對話框如下:
填寫名稱,參數列表,下面的聲明可以不修改,其中的id[X]代表該方法的ID,這個ID標識了該方法與插件工具條按鈕的順序,比如id[6]的方法,響應第6個按鈕的點擊。
我在這里添加了4個方法,分別是:
注意第一個是自動生成的。然后我們可以在類視圖中看到ICommands下出現了一共5個方法。
接下來要做的是,在工具條中插入這么多個按鈕,並設置好按鈕的圖形(BMP位圖)。在類視圖中點開CDSAddin類的OnConnection(),這是一個插件連接時的初始化過程。
在這里我們可以看到之前默認生成的AddinCommandMethod方法,它是如何與第一個按鈕關聯起來的。代碼如下:
我嘗試了半天,參考demo,才知道了按鈕與方法的關聯都是這樣一個一個完成的。唯一不同的是,要做這樣幾個對應的修改(依次對應圖中紅框)。
A: 修改為對應方法的名字(我也不知道這里的區別在哪)
B: 修改為事先創建好的字符串資源ID,下面會詳細介紹。
C: 修改為對應的方法名。
D: 這個數字的參數名是nBitmapOffset,意思是按鈕位圖上的偏移值(如果你熟悉MFC工具條的位圖就能明白,加載工具條是自動把位圖的某一段分割為一個按鈕)。
Windows提供的demo中,是用{ }把兩段這樣的代碼分別圈起來的,形成了不同的作用域,這樣就免去了聲明不同命局部變量的麻煩。這樣我們就只需把這個{}包括其中的內容拷貝,粘貼4次,然后修改里面的相應參數即可。
這里需要注意兩點。一是nBitmapOffset這個參數,要根據你所繪制的工具條位圖的順序來對應方法的順序。比如第一個按鈕的nBitmapOffset = 0,第二個按鈕的nBitmapOffset = 1,琢磨琢磨你就懂了。這里我也是調試了老半天才發現的。MSDN上沒有任何說明,網上更找不到了。
我的理解是:方法與按鈕的關聯唯一地由這個參數決定。不管我有沒有理解錯,你可別弄混了就是。
接下來詳細說說上面代碼中的IDS_CMD_STRING1字符串資源的格式。如下圖:
Caption由\n分為3個部分,第一部分是什么我沒有發現,第二部分是光標移到插件按鈕上時狀態欄提示,第三部分是光標提示。這里似乎如果格式錯誤的話就會導致按鈕加載失敗。得好好注意。
最后就是完成方法的具體實現。這里已經沒有什么需要說的了,都是一般函數的編寫一樣。比如這里我這么測試一下:
彈一個框,顯示notepad。其他類似。如果需要完成功能的話當然easy了,用ShellExecute()或者別的都行。至於搜索文本,MSDN的SAMPLE中有一個API查詢的例子,里面用到了獲取選定文本的方法,這里不細述,獲取選定文本后我們只需構建出這么一個東西http://www.baidu.com/s?wd=XXXXX就行了。然后ShellExecute。
至於位圖按鈕,就得自己畫或者編輯了,分為2個,一個是32×32,5個按鈕就是160×32,另一個是中等尺寸,16×16,5個按鈕就是80×16。我這里是用Photoshop畫的,比較麻煩。
最后我們看看最終效果。
我們把編譯好的Addin.dll拷貝到VC++安裝目錄下面的addin目錄中,比如我的Visual C++6.0安裝在D:\盤,所以我可以打開D:\Program Files\Microsoft Visual Studio\Common\MSDev98\AddIns,粘貼到這里,而后在VC++中點擊tools->customize,在customize對話框中點選Add-ins and Macro files標簽頁,如果沒錯的話應該看到列表中有Addin by Lusta。勾選,close。如果有什么問題的話,VC++會提示無法裝載,問題在哪就得自己找了。
圖中Toolbar8就是我剛剛加載的插件,旁邊是Visual Assist X的工具條。可以看到光標提示“Notepad”。我們點擊它,可以看到彈框。
說明插件已經成功注入了VC++主程序。我們的編寫到此結束。
關於插件的卸載,需要強調的是,應該先重復tools->customize操作,將勾去掉,close。最后刪除拷貝的dll文件。如果直接刪除的話注冊表里面有殘余。
好了,到這里為止。我只是憑借記憶總結了一下一般的編寫過程。有什么不妥的不對的地方歡迎指正。文字描述有點麻煩,可能存在講不清楚的地方,如果有需要這個代碼的,可以聯系我。