在 Office 2000 開發體系中,內部 COM 增益集是擴展應用程式功能的核心技術。本文承接先前關於 Word、Excel、PowerPoint 與 Outlook 內部增益集開發的探討,專注於 Access 2000 的獨特實作細節。完整範例程式碼可至 code.cnblogs.com 下載。下圖展示範例執行後的效果:在 Access 視窗中動態新增一個自訂工具列,並包含帶有圖示與提示文字的按鈕。

AccessAddin。AcceAddin 完成物件插入。CAcceAddin 類別右鍵選 Implement Interface,點擊 Add Typelib,選取 Microsoft Add-in Designer (1.0),匯入 _IDTExtensibility2 介面。系統將自動產生五個必要的介面函式骨架。Access 的增益集登錄路徑位於 HKCU\Software\Microsoft\Office\Access\Addins。在 AcceAddin.rgs 檔案末尾加入下列內容:
HKCU
{
Software
{
Microsoft
{
Office
{
Access
{
Addins
{
'AccessAddin.AcceAddin'
{
val FriendlyName = s 'Access2000增益集'
val Description = s '使用ATL開發的Access2000內部增益集'
val LoadBehavior = d '00000003'
val CommandLineSafe = d '00000000'
}
}
}
}
}
}
}
因 Access 物件模型不同,需匯入 ADO、DAO、VBE、Office 及 Access 專屬型別程式庫。請依實際安裝路徑修改:
#pragma warning(disable:4146)
#import "D:\\Program Files\\Common Files\\system\\ado\\msado21.tlb" no_namespace \
rename("EOF", "adoEOF")
#import "D:\\Program Files\\Common Files\\Microsoft Shared\\DAO\\DAO360.DLL" \
rename("EOF","EndOfFile") rename("BOF","BegOfFile")
#import "E:\\Program Files\\Microsoft Office\\Office\\mso9.dll" rename_namespace("Office")
using namespace Office;
#import "D:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.olb" rename_namespace("VBE6")
using namespace VBE6;
#import "E:\\Program Files\\Microsoft Office\\Office\\MSACC9.OLB" named_guids,rename_namespace("MSACCESS")
using namespace MSACCESS;
#pragma warning(default:4146)
Access 沒有 ActiveExplorer 物件,可直接從 _Application 介面取得 CommandBars。核心程式碼如下:
STDMETHOD(OnConnection)(IDispatch * Application, ext_ConnectMode ConnectMode,
IDispatch * AddInInst, SAFEARRAY * * custom)
{
CComPtr< Office::_CommandBars> spCmdBars;
CComQIPtr<MSACCESS::_Application> spApp(Application);
ATLASSERT(spApp);
HRESULT hr = spApp->get_CommandBars(&spCmdBars);
if(FAILED(hr)) return hr;
ATLASSERT(spCmdBars);
// 建立工具列
CComVariant vName(L"Access2000 自訂工具列");
CComPtr<Office::CommandBar> spNewCmdBar;
CComVariant vPos(1); // 位置:頂端
CComVariant vTemp(VARIANT_TRUE);
CComVariant vEmpty(DISP_E_PARAMNOTFOUND, VT_ERROR);
spNewCmdBar = spCmdBars->Add(vName, vPos, vEmpty, vTemp);
// 新增按鈕
CComPtr< Office::CommandBarControls> spBarControls;
spBarControls = spNewCmdBar->GetControls();
ATLASSERT(spBarControls);
CComVariant vToolBarType(1); // msoControlButton
CComVariant vShow(VARIANT_TRUE);
CComPtr< Office::CommandBarControl> spNewBar;
spNewBar = spBarControls->Add(vToolBarType, vEmpty, vEmpty, vEmpty, vShow);
ATLASSERT(spNewBar);
CComQIPtr< Office::_CommandBarButton> spCmdButton(spNewBar);
ATLASSERT(spCmdButton);
// 設定按鈕圖示 (32x32 位圖)
HBITMAP hBmp = (HBITMAP)::LoadImage(_Module.GetResourceInstance(),
MAKEINTRESOURCE(IDB_BITMAP), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
::OpenClipboard(NULL);
::EmptyClipboard();
::SetClipboardData(CF_BITMAP, (HANDLE)hBmp);
::CloseClipboard();
::DeleteObject(hBmp);
spCmdButton->PutStyle(Office::msoButtonIconAndCaption);
hr = spCmdButton->PasteFace();
if (FAILED(hr)) return hr;
spCmdButton->PutVisible(VARIANT_TRUE);
spCmdButton->PutCaption(OLESTR(L"按鈕1"));
spCmdButton->PutEnabled(VARIANT_TRUE);
spCmdButton->PutTooltipText(OLESTR(L"按鈕1提示訊息"));
spCmdButton->PutTag(OLESTR(L"按鈕1標記"));
spNewCmdBar->PutVisible(VARIANT_TRUE);
m_spButton = spCmdButton;
m_spApp = spApp;
hr = CommandButton1Events::DispEventAdvise((IDispatch*)m_spButton);
if(FAILED(hr)) return hr;
::EmptyClipboard();
return S_OK;
}
工具列按鈕事件回應 (CommandBarButton 發送介面)、連接與斷開連接點的處理等,與 Word/Excel/PowerPoint/Outlook 版本大同小異,詳見先前文章。掌握上述三點差異,即可順利完成 Access 2000 內部 COM 增益集開發。