开发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):

DISPID Method Name PowerPoint 2002 Only
2001 WindowSelectionChange  
2002 WindowBeforeRightClick  
2003 WindowBeforeDoubleClick  
2004 PresentationClose  
2005 PresentationSave  
2006 PresentationOpen  
2007 NewPresentation  
2008 PresentationNewSlide  
2009 WindowActivate  
2010 WindowDeactivate  
2011 SlideShowBegin  
2012 SlideShowNextBuild  
2013 SlideShowNextSlide  
2014 SlideShowEnd  
2015 PresentationPrint  
2016 SlideSelectionChanged x
2017 ColorSchemeChanged x
2018 PresentationBeforeSave x
2019 SlideShowNextClick x

    首先在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,否则编译会出错。