Microsoft的Visual Studio開發工具為軟體開發人員提供了強大的功能,通過整合式開發環境(IDE)的構建平台提供的菜單和工具條,開發人員可以產生項目,編寫代碼,調試直到最終產生應用程式。除此之外,Visual Studio還提供了一套完整的Automation 物件,通過操作這些Automation 物件提供的方法,開發人員在不使用菜單和工具條的情況下也能夠完成諸如開啟檔案、啟用視窗或改變視窗大小等操作。Visual Studio提供了兩種方法讓使用者控制整合式開發環境和它的自動化組件對象,一種是使用宏(Macros),另一種是使用內建外掛程式(Add-ins)。本文主要是介紹內建外掛程式(Add-ins)方面的內容。
每一個Automation 物件都代表了整合式開發環境的一個構件或相關的一組構件。例如Document代表一個開啟的文檔,而Documents對象則代表所有開啟的文檔,同樣,一個Window對象代表一個開啟的視窗,Windows對象代表所有開啟的視窗。使用內建外掛程式可以在脫離IDE的情況下開啟一個項目。修改項目中的檔案甚至重新Build這個項目。使用內建外掛程式還可以向IDE添加實用的命令,在工具條上建立按鈕,擴充IDE的功能。
IDSAddIn介面是Visual Studio定義的外掛程式介面,Visual Studio只是定義了這個介面,一個內建外掛程式就是一個IDSAddIn介面的實現,也就是說,一個內建外掛程式就是一個COM對象,它至少應該實現一個IDSAddIn介面。使用VC的Add-ins嚮導產生的內建外掛程式代碼核心就是一個CDSAddIn類:
class CDSAddIn : public IDSAddIn,
public CComObjectRoot,public CComCoClass<CDSAddIn, &CLSID_DSAddIn<
IDSAddIn介面其實只有兩個方法,分別是:
IDSAddIn::OnConnection 外掛程式被裝載
IDSAddIn::OnDisconnection 外掛程式被卸載
外掛程式工作的過程是這樣的,當IDE啟動一個外掛程式時,就按照IDSAddIn介面的約定調用外掛程式的coclass實現的OnConnection,並傳遞一個Application參數給外掛程式,外掛程式的OnConnection就完成外掛程式的初始化。並通過這個Application物件查詢IDE支援的其他Automation 物件,通過這些對象完成特定的任務。一個內建外掛程式典型的任務就是向系統的Commands對象註冊一個命令並在工具條上建立一個按鈕。當系統要卸載一個內建外掛程式時就會調用相應的OnDisconnection,外掛程式應該利用這個機會釋放已經申請的系統資源,從系統的Commands對象中登出已經註冊的命令,同時刪除添加在工具條上的按鈕。從這個過程可以看出,雖然外掛程式的載入和釋放都是被動進行的,但是通過實現自訂的OnConnection和OnDisconnection介面函數,外掛程式可以完成自己定製的初始化和銷毀任務,這很像是COM事件的回調過程,從介面函數的名字也可以看出一些倪端,介面函數的名字都是以“On”開頭,這通常是COM體系中事件介面的聲明方式。圖(1) 表示了內建外掛程式、IDSAddIn介面和實作類別之間的關係:
圖1. 外掛程式組件、IDSAddIn介面和實作類別之間的關係
Visual Studio的IDE通過IDSAddIn::OnConnection介面函數將一個很重要的參數傳遞給外掛程式,這個參數就是一個Application對象。Application對象對應的是整個Visual Studio IDE 的執行個體,簡單點講,可以理解為一個Application就是一個開啟的VC整合式開發環境。Application對象是整個Visual Studio內建群組件的核心組件,通過Application對象可以查詢整個Visual Studio IDE的所有內建對象,並通過這些內建對象控制Visual Studio。以下代碼示範了在不開啟VC的IDE的情況下開啟一個VC的工作區並執行Rebuild All命令編譯這個工作區的所有項目:
//虛擬碼,不可直接編譯
#import "..../devshl.dll"
IApplicationPtr pApp;
pApp.CreateObject(_T("MSDEV.Application"));
if(pApp != NULL)
{
pApp-<RebuildAll();
}
內建外掛程式通過IDSAddIn::OnConnection介面函數介面函數獲得一個當前整合式開發環境的Application對象,外掛程式隨後的所有工作都是圍繞著這個Application對象進行的,CDSAddIn負責儲存這個Application對象。Visual Studio的內建COM對象介面是一個比較複雜的介面模型,圖(2)就是這些內建介面的關係圖:
圖2. Visual Studio的內建COM對象介面關係圖
下面就以TabBars的自動添加格式化函數說明功能的部分代碼為例,示範如何通過Application對象實現在當前文檔中插入文字內容:
CComPtr<IDispatch< pDispDoc;
CComQIPtr<ITextDocument, &IID_ITextDocument< pDoc;
//m_pApplication是CDSAddIn儲存的一個Application對象
m_pApplication-<get_ActiveDocument(&pDispDoc);
pDoc = pDispDoc; //隱式的介面查詢
pDispDoc = NULL; //Release it
if(pDoc)
{
CComPtr<IDispatch< pDispSel;
CComQIPtr<ITextSelection, &IID_ITextSelection< pSel;
CComBSTR bstr;
CString strText;
pDoc-<get_Selection(&pDispSel);
pSel = pDispSel; // 查詢ITextSelection對象
pDispSel = NULL;
hr = pSel-<get_Text(&bstr); //得到當前選擇的文字
if(SUCCEEDED(hr))
{
strText = bstr;
strText.Replace(_T("/t"),_T(" ")); //將/t替換成空格
bstr = strText;
pSel-<put_Text(bstr);//寫入document
}
}
瞭解了Visual Studio的自動化介面以及如何使用這些介面之後,就可以大致瞭解TabBars是如何工作的,隨後的代碼解讀將重點介紹每個TabBars的功能是如何?的,並結合這些功能講解Visual Studio內建COM對象介面的用法。