开发OFFICE插件总结

前段时间做了个关于PPT的插件开发,简单总结一下。

1. VC6.0中使用VBA
    在VC6.0中,可以使用导入类型库功能,即可连接到所需的OLB文件,并且可以选择导入的类。然后可以直接声明对象,如_Application m_app。需要注意的是,导入的类只能是实体类,包含虚函数的类都无法包含进来。

2. VS2005中使用VBA
    VS2005中,由于没有导入类型库功能,可以使用VC6.0中生成的.H文件,并连接到OLB文件。使用方法和VC6.0中基本相同。

3. VS2005中开发插件
    VS2005中,可以直接利用Project Wizard来开发OFFICE插件程序。
    生成的程序框架包含Connect.h,Connect.cpp,类CConnect中包含插件的加载事件处理函数。
    需要导入文件:
 

1  #import  " mso9.dll "  rename_namespace( " Office " ) \
2  rename( " RGB " , " OfficeRGB " ) \
3  rename( " DocumentProperties " , " OfficeDocumentProperties " )
4  using   namespace  Office;
5  #import  " VBE6EXT.olb "  rename_namespace( " VBE6 " )
6  using   namespace  VBE6;
7  #import  " MSPPT9.OLB "  named_guids,rename_namespace( " MSPPT " ) \
8  rename( " RGB " , " PPTRGB " )
9  using   namespace  MSPPT;

    VBA对象的使用和前两点有些不同,例如:
 

1  CComPtr < IDispatch >  m_pApplication;
2  pApplication -> QueryInterface(__uuidof(IDispatch), (LPVOID * ) & m_pApplication);
3  MSPPT::_ApplicationPtr pApp;
4  m_pApplication -> QueryInterface(__uuidof(MSPPT::_ApplicationPtr),(LPVOID * ) & pApp);

    该调用方法缺点是调用比较麻烦,但是优点是可以使用虚函数。例如_Application类中的get_HWND方法。
 
4. VS2005中开发插件-事件的加入
   
PPT中的提供的事件及注册消息号如下表(详细请参见MSDN文章How to handle PowerPoint 2000 events or PowerPoint 2002 events by using Visual C++ .NET 2002 or Visual C++ .NET 2003 and Microsoft Foundation Classes):

DISPIDMethod NamePowerPoint 2002 Only
2001WindowSelectionChange 
2002WindowBeforeRightClick 
2003WindowBeforeDoubleClick 
2004PresentationClose 
2005PresentationSave 
2006PresentationOpen 
2007NewPresentation 
2008PresentationNewSlide 
2009WindowActivate 
2010WindowDeactivate 
2011SlideShowBegin 
2012SlideShowNextBuild 
2013SlideShowNextSlide 
2014SlideShowEnd 
2015PresentationPrint 
2016SlideSelectionChangedx
2017ColorSchemeChangedx
2018PresentationBeforeSavex
2019SlideShowNextClickx

    首先在OnConnection函数中连接到事件源(establish a connection with the event source represented by pUnk),如下:
 
1  pApplication -> QueryInterface(__uuidof(IDispatch), (LPVOID * ) & m_pApplication);
2 pAddInInst -> QueryInterface(__uuidof(IDispatch), (LPVOID * ) & m_pAddInInstance);
3 EApplicationEvents::DispEventAdvise(m_pApplication);

    同样,OnDisconnection中断开事件的连接:
 

1  EApplicationEvents::DispEventUnadvise(m_pApplication)

    注册事件函数,以PRESENTATIONOPEN事件为例,Connect.h中的代码如下:
 

 1  _ATL_FUNC_INFO OnPresentationOpenInfo  = {CC_STDCALL,VT_EMPTY, 1 ,VT_DISPATCH};
 2  #define  PPTADDIN_PRESENTATIONOPEN        2006
 3  class  ATL_NO_VTABLE CConnect : 
 4       public  CComObjectRootEx < CComSingleThreadModel > ,
 5       public  CComCoClass < CConnect,  & CLSID_Connect > ,
 6       public  IDispatchImpl < AddInDesignerObjects::_IDTExtensibility2,  & AddInDesignerObjects::IID__IDTExtensibility2,  & AddInDesignerObjects::LIBID_AddInDesignerObjects,  1 0 > ,
 7       public  IDispEventSimpleImpl < 1 ,CConnect, & __uuidof(MSPPT::EApplication) >
 8  {
 9  public :
10      typedef IDispEventSimpleImpl < 1 ,CConnect, & __uuidof(MSPPT::EApplication) >  EApplicationEvents;
11      CConnect()
12      {
13      }
14 
15  DECLARE_REGISTRY_RESOURCEID(IDR_ADDIN)
16  DECLARE_NOT_AGGREGATABLE(CConnect)
17 
18  BEGIN_COM_MAP(CConnect)
19      COM_INTERFACE_ENTRY(IDispatch)
20      COM_INTERFACE_ENTRY(AddInDesignerObjects::IDTExtensibility2)
21  END_COM_MAP()
22 
23  BEGIN_SINK_MAP(CConnect)
24      SINK_ENTRY_INFO( 1 , __uuidof(MSPPT::EApplication), /* dispid */   2006 , OnPresentationOpen,  & OnPresentationOpenInfo)
25      
26  END_SINK_MAP()
27 
28      DECLARE_PROTECT_FINAL_CONSTRUCT()
29 
30      HRESULT FinalConstruct()
31      {
32           return  S_OK;
33      }
34 
35       void  FinalRelease() 
36      {
37      }
38 
39  public :
40       // IDTExtensibility2 implementation:
41      STDMETHOD(OnConnection)(IDispatch  *  Application, AddInDesignerObjects::ext_ConnectMode ConnectMode, IDispatch  * AddInInst, SAFEARRAY  ** custom);
42      STDMETHOD(OnDisconnection)(AddInDesignerObjects::ext_DisconnectMode RemoveMode, SAFEARRAY  ** custom );
43      STDMETHOD(OnAddInsUpdate)(SAFEARRAY  ** custom );
44      STDMETHOD(OnStartupComplete)(SAFEARRAY  ** custom );
45      STDMETHOD(OnBeginShutdown)(SAFEARRAY  ** custom );
46  private :
47      CComPtr < IDispatch >  m_pApplication;
48      CComPtr < IDispatch >  m_pAddInInstance;
49 
50  protected :
51      typedef IDispEventSimpleImpl < /* nID = */   1 ,CConnect,  & __uuidof(MSPPT::EApplication) >  ApplicationEvents;
52       void  __stdcall OnPresentationOpen(IDispatch  *  pres);
53  };


    Connect.cpp中添加OnPresentationOpen的源代码。
    需要注意的是OnPresentationOpen函数的调用方式是__stdcall,否则编译会出错。