Что я хочу сделать:
Написать приложение, которое прослушивает события Office. Я хочу слушать события из любого экземпляра, открытого на машине. Например, если я слушаю BeforeDocumentSave в Word, я хочу, чтобы мой приемник для этого метода активировался всякий раз, когда любой экземпляр Word на хосте сохраняет документ.
Еще одно требование - я пишу на C ++ без MFC или ATL.
Что я сделал:
Я ' Я написал программу, которая должна прослушивать события Word. См. Код ниже.
Проблема:
Это не работает - обработчики событий никогда не вводятся, хотя я открываю приложение Word и выполняю действия, которые должны запускать события.
У меня есть некоторые конкретные вопросы, и, конечно, приветствуется любой другой ввод!
Вопросы:
Можно ли прослушивать события из приложения, которое было запущено не мной? Во всех найденных мною примерах прослушивающее приложение запускает офисное приложение, которое оно хочет прослушивать.
В инструкции по Microsoft (http://support.microsoft.com/kb/183599/EN-US/) я обнаружил следующий комментарий:
Однако большинство событий, таких как t работают - обработчики событий никогда не вводятся, хотя я открываю приложение Word и выполняю действия, которые должны запускать события.
У меня есть некоторые конкретные вопросы, и, конечно, любой другой ввод будет очень приветствоваться!
Вопросы :
Можно ли прослушивать события из приложения, которое было запущено не мной? Во всех найденных мною примерах прослушивающее приложение запускает офисное приложение, которое оно хочет прослушивать.
В инструкции по Microsoft (http://support.microsoft.com/kb/183599/EN-US/) я обнаружил следующий комментарий:
Однако большинство событий, таких как t работают - обработчики событий никогда не вводятся, хотя я открываю приложение Word и выполняю действия, которые должны запускать события.
У меня есть некоторые конкретные вопросы, и, конечно, любой другой ввод будет очень приветствоваться!
Вопросы :
Можно ли прослушивать события из приложения, которое было запущено не мной? Во всех найденных мною примерах прослушивающее приложение запускает офисное приложение, которое оно хочет прослушивать.
В инструкции по Microsoft (http://support.microsoft.com/kb/183599/EN-US/) я обнаружил следующий комментарий:
Однако большинство событий, таких как
Можно ли прослушивать события из приложения, запущенного не мной? Во всех найденных мною примерах прослушивающее приложение запускает офисное приложение, которое оно хочет прослушивать.
В инструкции по Microsoft (http://support.microsoft.com/kb/183599/EN-US/) я обнаружил следующий комментарий:
Однако большинство событий, таких как
Можно ли прослушивать события из приложения, запущенного не мной? Во всех найденных мною примерах прослушивающее приложение запускает офисное приложение, которое оно хочет прослушивать.
В инструкции по Microsoft (http://support.microsoft.com/kb/183599/EN-US/) я обнаружил следующий комментарий:
Однако большинство событий, таких как События книги Microsoft Excel, делать не запускать с DISPID 1. В таком случаях вы должны явно изменить отправить карту в MyEventSink.cpp в сопоставьте DISPID с правильными methods.
How do I modify the dispatch map?
- For now I've defined only Startup, Quit and DocumentChange, which take no arguments. The methods I really need do take arguments, specifically one of type Document. How do I define parameters of this type if I'm not using MFC?
Code:
Here's the header file for my project, followed by the C file:
#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_
The C file:
#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" ); }