簡介
在這裡,我們仍然使用VC6中的ATL來實現Access2000下的內部COM插件,至於其基本原理和詳細的實現方法及步驟,可以參看前面我的文章< Office2000下內部COM插件的編程實現>等,這裡只重點說明它和其它Office2000中內部COM插件(如:Word2000、Excel2000、PowerPoint2000、Outlook2000)實現的不同之處,文章及示例代碼都可以在http://code.cnblogs.com網站中找到。下面是Access2000內部COM插件示例代碼運行後的效果圖:
具體實現
打開VC6.0,在新建工程中選中ATL COM Appwizard,在右側工程名中輸入AccessAddin,點擊Finish(完成)按鈕完成工程創建。接著,選取菜單Insert->New ATL Objec項,在彈出的ATL對象向導對話框中選中相應Objects對應右側的Simple Object選項,點擊下一步,在彈出的對話框中ShortName中輸入AcceAddin,點OK完成插入ATL對象。
接著通過導入類型庫來實現_IDTExtensibility2接口,編釋好上面所建工程後,在ClassView中的CAcceAddin類上點鼠標右鍵,在彈出的右鍵菜單中選Implement Interface項。在彈出的實現接口對話框中點擊Add Typelib,在彈出的Browse Type Libraries對話框中,向下滾動選取Microsoft Add-in Designer(1.0)子項,點OK按鈕。在彈出的接口列表對話框中選中_IDTExtensibility2接口,點OK按鈕完成導入。系統會自動為你生成空的上面所提到的五個所需接口函數。
下面來看看它們之間實現的不同點。
第一點:注冊類型信息有所不同(*.rgs),在文件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''
}
}
}
}
}
}
}
第二點:在文件中Stdafx.h中的類型的導入庫部分源碼將有所不同,可在Stdafx.h中添加下面代碼。
#pragma warning(disable:4146) // 暫時屏蔽編譯時4146警告信息
導入Access2000所需類型庫ADO、DAO、VBE、OFFICE及ACCESS庫(具體路徑可根據實際情況自行設定,jingzhou xu)
#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) // 恢復編譯時4146警告信息
第三點:Access2000中沒有ActiveExplorer對象,所以不必象Outlook2000一樣要經過它來獲取CommandBars,可以直接從_Application中獲得CommandBars對象進行操作。修改部分如下面源碼所示:
// 裝缷插件時處理, jingzhou xu
STDMETHOD(OnConnection)(IDispatch * Application, ext_ConnectMode ConnectMode, IDispatch * AddInInst, SAFEARRAY * * custom)
{
CComPtr < Office::_CommandBars> spCmdBars;
// Access應用接口_Application
CComQIPtr<MSACCESS::_Application> spApp(Application);
ATLASSERT(spApp);
// 獲取CommandBars接口
HRESULT hr = spApp->get_CommandBars(&spCmdBars);
if(FAILED(hr))
return hr;
ATLASSERT(spCmdBars);
// 新增一個工具條及其上一個位圖按鈕
CComVariant vName("新增Access2000工具條插件");
CComPtr <Office::CommandBar> spNewCmdBar;
// 新增工具條位置
CComVariant vPos(1);
CComVariant vTemp(VARIANT_TRUE); // 臨時
CComVariant vEmpty(DISP_E_PARAMNOTFOUND, VT_ERROR);
// 用Add方法在指定位置新增一工具條並讓spNewCmdBar指向它
spNewCmdBar = spCmdBars->Add(vName, vPos, vEmpty, vTemp);
// 獲取新增工具條的CommandBarControls,從而在其上添加按鈕
CComPtr < Office::CommandBarControls> spBarControls;
spBarControls = spNewCmdBar->GetControls();
ATLASSERT(spBarControls);
// MsoControlType::msoControlButton = 1
CComVariant vToolBarType(1);
// 顯示工具條
CComVariant vShow(VARIANT_TRUE);
CComPtr < Office::CommandBarControl> spNewBar;
// 用CommandBarControls中的Add方法新增第一個按鈕,並讓spNewBar指向它
spNewBar = spBarControls->Add(vToolBarType, vEmpty, vEmpty, vEmpty, vShow);
ATLASSERT(spNewBar);
// 為每一個按鈕指定_CommandBarButton接口,從面可以指定按鈕的顯示風格等
CComQIPtr < Office::_CommandBarButton> spCmdButton(spNewBar);
ATLASSERT(spCmdButton);
// 設置位圖按鈕風格,位圖為32x32大小,將其放入剪切板中,用PasteFace()貼在指定按鈕上
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("按鈕1"));
spCmdButton->PutEnabled(VARIANT_TRUE);
spCmdButton->PutTooltipText(OLESTR("按鈕1提示信息"));
spCmdButton->PutTag(OLESTR("按鈕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派發接口的響應事件、打開或斷開與接口的連接方法等都沒有太大變化,其具體實現前面的文章已經介紹過了,有興趣的朋友可以參看下面參考文獻中的幾篇有關Office2000下內部COM插件的編程實現文章,然後再看這篇文章及示例源碼一定會倍感輕松。
參考文獻:
Office2000下內部COM插件的編程實現 -- 徐景周
Word2000/XP中內部COM插件的編程實現 -- 徐景周
Excel2000/XP和PowerPoint2000/XP下內部COM插件的實現 -- 徐景周
ATL開發指南(第二版) -- Tom Armstrong & Ron Patton