像 C++Test、Visual Assist 這樣的工具能無縫嵌入 VC 開發環境,實現工程分析、統計等功能。其核心支撐是龐大的 COM 架構。本文以開發一個名為「CodeAnalyser」的 VC 增益為例,完整演示從項目創建、接口定義、命令實現、工具欄集成到部署調試的全過程。
項目名 CodeAnalyser。向導第二步設置增益名稱、描述,選擇是否生成工具欄及自動添加 VC 事件響應代碼。
ICommands 與 CCommands向導生成的工程引用 ICommands 接口,派生出 CCommands 類,承擔所有用戶自定義命令、VC 應用消息響應、調試事件響應。**鐵律:先在 .odl 文件中為 ICommands 添加接口聲明,再在 CCommands 中聲明並實現。**
interface ICommands : IDispatch {
[id(1)] HRESULT GetCurDirCommandMethod(); // 獲取 VC 當前工作目錄
[id(2)] HRESULT QuitCommandMethod(); // 退出 VC 編輯器
};
// CCommands.h
public:
STDMETHOD(GetCurDirCommandMethod)(THIS);
STDMETHOD(QuitCommandMethod)(THIS);
// CCommands.cpp
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, _T("VC工作目錄"), MB_OK | MB_ICONINFORMATION);
VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
return S_OK;
}
STDMETHODIMP CCommands::QuitCommandMethod() {
AFX_MANAGE_STATE(AfxGetStaticModuleState());
VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
if (::MessageBox(NULL, _T("您想退出VC++編輯器嗎(Y/N)?"), _T("詢問"), MB_YESNO | MB_ICONQUESTION) == IDYES)
m_pApplication->Quit();
VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
return S_OK;
}
AFX_MANAGE_STATE 確保 MFC 模塊狀態正確;EnableModeless 禁用/啟用無模式對話框,防止重入;m_pApplication 是向導自動維護的 VC 應用程序接口指針。
CDSAddIn 關鍵函數CDSAddIn 中兩大核心虛函數:
OnConnection:增益加載時調用。**所有初始化在此完成**:COM 服務啟動、工具欄/菜單創建、按鈕添加、命令映射。OnDisconnection:增益卸載時調用。執行清理:銷毀 UI、釋放 COM、關閉句柄。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));
// 參數:命令字符串、接口方法名、位圖偏移、Cookie、返回值
if (bRet == VARIANT_FALSE) { *OnConnection = VARIANT_FALSE; return S_OK; }
if (bFirstTime == VARIANT_TRUE) {
VERIFY_OK(pApplication->AddCommandBarButton(dsGlyph, bszCmdName, m_dwCookie));
}
AddCommand 建立命令字符串與接口方法的映射;AddCommandBarButton 將命令標識放入工具欄。多按鈕重複此流程。
COM 增益開發看似繁瑣,實則遵循固定模式:定義接口 → 實現類 → OnConnection 掛載 UI → 部署 DLL。掌握此流程,即可將任意功能集成至 VC IDE,極大提升開發效率。