我想要做的事:如何从独立启动的Office应用程序侦听COM事件?
编写一个监听Office事件的应用程序。我想收听机器上打开的任何实例的事件。例如。如果我在Word中收听BeforeDocumentSave,那么只要主机上的任何Word实例保存文档,我都希望我的接收器可用于此方法。
另一个要求是我用C++编写而没有MFC或ATL。
我所做的:
我写的是应该听字事件的程序。请参阅下面的代码。
问题:
它不工作 - 事件处理程序从未进入过,虽然我打开一个Word应用程序,并做到这一点应该触发事件的动作。
我有一些具体的问题,当然任何其他的输入将非常欢迎!
问题:
是否有可能听取不是由我启动的应用程序的事件?在我发现的所有例子中,侦听应用程序启动它想要听的办公应用程序。
在Microsoft HOWTO(http://support.microsoft.com/kb/183599/EN-US/)我发现了以下评论:
然而,大多数事件,比如作为 微软Excel的工作簿事件,不 不与DISPID 1开始。在这种情况下 ,你必须明确修改MyEventSink.cpp的 调度映射到 用正确的方法 匹配的DISPID。
如何修改调度映射?
- 现在我只定义了Startup,Quit和DocumentChange,它们不带任何参数。我真正需要的方法需要参数,特别是一种类型的文档。如果我不使用MFC,我该如何定义这种类型的参数?
代码:
下面是我的项目的头文件,接着是C文件:
#ifndef _OFFICEEVENTHANDLER_H_
#define _OFFICEEVENTHANDLER_H_
// 000209FE-0000-0000-C000-000000000046
static const GUID IID_IApplicationEvents2 =
{0x000209FE,0x0000,0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
struct IApplicationEvents2 : public IDispatch // Pretty much copied from typelib
{
/*
* IDispatch methods
*/
STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj) = 0;
STDMETHODIMP_(ULONG) AddRef() = 0;
STDMETHODIMP_(ULONG) Release() = 0;
STDMETHODIMP GetTypeInfoCount(UINT *iTInfo) = 0;
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) = 0;
STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames,
UINT cNames, LCID lcid, DISPID *rgDispId) = 0;
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams,
VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
UINT* puArgErr) = 0;
/*
* IApplicationEvents2 methods
*/
STDMETHODIMP Startup();
STDMETHODIMP Quit();
STDMETHODIMP DocumentChange();
};
class COfficeEventHandler : IApplicationEvents2
{
public:
DWORD m_dwEventCookie;
COfficeEventHandler
(
) :
m_cRef(1),
m_dwEventCookie(0)
{
}
STDMETHOD_(ULONG, AddRef)()
{
InterlockedIncrement(&m_cRef);
return m_cRef;
}
STDMETHOD_(ULONG, Release)()
{
InterlockedDecrement(&m_cRef);
if (m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObj)
{
if (riid == IID_IUnknown){
*ppvObj = static_cast<IApplicationEvents2*>(this);
}
else if (riid == IID_IApplicationEvents2){
*ppvObj = static_cast<IApplicationEvents2*>(this);
}
else if (riid == IID_IDispatch){
*ppvObj = static_cast<IApplicationEvents2*>(this);
}
else
{
char clsidStr[256];
WCHAR wClsidStr[256];
char txt[512];
StringFromGUID2(riid, (LPOLESTR)&wClsidStr, 256);
// Convert down to ANSI
WideCharToMultiByte(CP_ACP, 0, wClsidStr, -1, clsidStr, 256, NULL, NULL);
sprintf_s(txt, 512, "riid is : %s: Unsupported Interface", clsidStr);
*ppvObj = NULL;
return E_NOINTERFACE;
}
static_cast<IUnknown*>(*ppvObj)->AddRef();
return S_OK;
}
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
{
return E_NOTIMPL;
}
STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
return E_NOTIMPL;
}
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgdispid)
{
return E_NOTIMPL;
}
STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
return E_NOTIMPL;
}
// IApplicationEvents2 methods
void Startup();
void Quit();
void DocumentChange();
protected:
LONG m_cRef;
};
#endif // _OFFICEEVENTHANDLER_H_
的C文件:
#include <windows.h>
#include <stdio.h>
#include "OfficeEventHandler.h"
#include "OCIdl.h"
int main()
{
CLSID clsid; // CLSID of automation object
HRESULT hr;
LPUNKNOWN punk = NULL; // IUnknown of automation object
LPDISPATCH pdisp = NULL; // IDispatch of automation object
IConnectionPointContainer *pConnPntCont;
IConnectionPoint *pConnPoint;
IUnknown *iu;
IID id;
COfficeEventHandler *officeEventHandler = new COfficeEventHandler;
CoInitialize(NULL);
hr = CLSIDFromProgID(OLESTR("Word.Application"), &clsid);
hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER,
IID_IUnknown, (void FAR* FAR*)&punk);
hr = punk->QueryInterface(IID_IConnectionPointContainer, (void FAR* FAR*)&pConnPntCont);
// IID for ApplicationEvents2
hr = IIDFromString(L"{000209FE-0000-0000-C000-000000000046}",&id);
hr = pConnPntCont->FindConnectionPoint(id, &pConnPoint);
hr = officeEventHandler->QueryInterface(IID_IUnknown, (void FAR* FAR*)&iu);
hr = pConnPoint->Advise(iu, &officeEventHandler->m_dwEventCookie);
Sleep(360000);
hr = pConnPoint->Unadvise(officeEventHandler->m_dwEventCookie);
if (punk) punk->Release();
if (pdisp) pdisp->Release();
CoUninitialize();
return hr;
}
// IApplicationEvents2 methods
void COfficeEventHandler::Startup()
{
printf("In Startup\n");
}
void COfficeEventHandler::Quit()
{
printf("In Quit\n");
}
void COfficeEventHandler::DocumentChange()
{
printf("In DocumentChnage\n");
}