COM Events


Events

They are used to send notifications between two objects in COM. In order to receive notifications, it is necessary to:
  1. Get a IConnectionPointContainer interface
  2. Call the method IConnectionPointContainer.FindConnectionPoint to get a IConnectionPoint interface
  3. To receive events, you must call IConnectionPoint.Advise
  4. To stop receiving events, you must call IConnectionPoint.Unadvise

Estos son usados para enviar notificaciones entre dos objetos en COM. A fin de recibir notificaciones es necesario:
  • Conserguir una interface IConnectionPointContainer
  • Llamar el método IConnectionPointContainer.FindConnectionPoint para conseguir una interface IConnectionPoint
  • Para recibir eventos, usted debe llamar IConnectionPoint.Advise
  • Para dejar de recibir eventos, usted debe llamar IConnectionPoint.Unadvise

  • Microsoft Word Events

    You can use the Object Browser to explore Microsoft Word events as shown below. If you are using #import, you can use Class View to explore Microsoft Word events (see figure below).
    Usted puede usar el Explorador de Objetos para explorar los eventos de Microsoft Word como se muestra debajo. Si usted está usando #import, usted puede usar la Vista de Clases para explorar los eventos de Microsoft Word (vea la figura below).

    MsWordEventObjBrowser

    MsEventClassView

    Problem 1
    Create a program so called MsWait to display in a MessageBox the name of the Microsoft Word Document using the DocumentBeforePrint event.
    Cree un programa llamado MsWait para mostrar en una Caja de Mensaje el nombre del documento de Microsoft Word usando el evento DocumentBeforePrint.

    Step A
    Create Wintempla dialog application called MsWait.
    Cree una aplicación de diálogo de Wintempla llamada MsWait.

    Step B
    Use the command #import to create the files: mso.tlh, mso.tli and msword.tlh. If you have created these files in another project, you may just copy these files from that project (after copying the files, do not forget to add these files to your project in Microsoft Visual Studio).
    Use el comando #import para crear los archivos: mso.tlh, mso.tli y msword.tlh. Si usted ya ha creado estos archivos en otro proyecto, usted puede solo copiar estos archivos desde este proyecto (después de copiar estos archivos, no se olvide de agregar estos archivos a su proyecto de Microsoft Visual Studio).

    MsWaitImport

    MsWaitClassView

    Step C
    From the menu: Tools > Add Wintempla Item... add an IUnknown class called EventListener as shown. Then edit the files: EventListener.h and EventListener.cpp.
    Desde el menú: Tools > Add Wintempla Item... agregue una clase IUnknown llamada EventListener como se muestra. Entonces edite los archivos: EventListener.h y EventListener.cpp.

    AddEventListener

    EventListener.h
    #pragma once //_____________________________________________ EventListener.h
    #include "resource.h"
    #include "msword.tlh"
    #include "mso.tlh"

    // You can get the interface ID (IID) from the msword.tlh file
    const IID IID_IApplicationEvents2 ={0x000209fe,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};

    class EventListener : public IDispatch
    {
    public:
         EventListener();
         ~EventListener();
         HWND hWnd;
         //____________________________________________________ IUnknown
         IUNKNOWN_BEGIN (IDispatch)
              QUERY_INTERFACE(IID_IDispatch, IDispatch)
              QUERY_INTERFACE(IID_IApplicationEvents2, Word::IApplicationEvents2)
         IUNKNOWN_END
         //_______________________________________________________ IDispatch
         STDMETHOD (GetTypeInfoCount) (UINT *pctinfo);
         STDMETHOD (GetTypeInfo) (UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
         STDMETHOD (GetIDsOfNames) (REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
         STDMETHOD (Invoke) (DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
         //_______________________________________________________Word::ApplicationEvents2
         STDMETHOD (Startup)();
         STDMETHOD (Quit)();
         STDMETHOD (DocumentChange)();
         STDMETHOD (DocumentOpen)(/*[in]*/ IDispatch* document);
         STDMETHOD (DocumentBeforeClose)(/*[in]*/ IDispatch* document, /*[in]*/ VARIANT_BOOL* Cancel);
         STDMETHOD (DocumentBeforePrint)(/*[in]*/ IDispatch* document, /*[in]*/ VARIANT_BOOL* Cancel);
         STDMETHOD (DocumentBeforeSave)(/*[in]*/ IDispatch* document, /*[in]*/ VARIANT_BOOL* SaveAsUI, /*[in]*/ VARIANT_BOOL * Cancel);
         STDMETHOD (NewDocument)(/*[in]*/ IDispatch* document);
         STDMETHOD (WindowActivate)(/*[in]*/ IDispatch* document, /*[in]*/ IDispatch* window);
         STDMETHOD (WindowDeactivate)(/*[in]*/ IDispatch* document, /*[in]*/ IDispatch* window);
         STDMETHOD (WindowSelectionChange)(/*[in]*/ IDispatch* selection);
         STDMETHOD (WindowBeforeRightClick)(/*[in]*/ IDispatch* selection, /*[in]*/ VARIANT_BOOL* Cancel);
         STDMETHOD (WindowBeforeDoubleClick)(/*[in]*/ IDispatch* selection, /*[in]*/ VARIANT_BOOL* Cancel);
    };

    EventListener.cpp
    #include "stdafx.h" //_____________________________________________ EventListener.cpp
    #include "EventListener.h"

    EventListener::EventListener()
    {
         hWnd = NULL;
    }

    EventListener::~EventListener()
    {
    }

    //_______________________________________________________ IDispatch
    STDMETHODIMP EventListener::GetTypeInfoCount(UINT *pctinfo)
    {
         *pctinfo = 0;
         return S_OK;
    }

    STDMETHODIMP EventListener::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
    {
         return E_NOTIMPL;
    }

    STDMETHODIMP EventListener::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
    {
         return E_NOTIMPL;
    }

    STDMETHODIMP EventListener::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
         DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
    {
         if (riid != IID_NULL) return E_INVALIDARG;

         switch (dispIdMember)
         {
         case 0x00000001: // Startup()
              return Startup();
         case 0x00000002: // Quit()
              return Quit();
         case 0x00000003: // DocumentChange()
              return DocumentChange();
         case 0x00000004: //DocumentOpen(/*[in]*/ struct Word::_Document * Doc)
              if (pDispParams->cArgs != 1) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              return DocumentOpen(pDispParams->rgvarg[0].pdispVal);
         case 0x00000006: // DocumentBeforeClose(/*[in]*/ struct Word::_Document * Doc, /*[in]*/ VARIANT_BOOL * Cancel)
              if (pDispParams->cArgs != 2) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != (VT_BOOL | VT_BYREF)) return E_INVALIDARG;
              return DocumentBeforeClose(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].pboolVal);
         case 0x00000007: // DocumentBeforePrint();
              if (pDispParams->cArgs != 2) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != (VT_BOOL | VT_BYREF)) return E_INVALIDARG;
              return DocumentBeforePrint(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].pboolVal);
         case 0x00000008: // DocumentBeforeSave
              if (pDispParams->cArgs != 3) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != (VT_BOOL | VT_BYREF)) return E_INVALIDARG;
              if (pDispParams->rgvarg[2].vt != (VT_BOOL | VT_BYREF)) return E_INVALIDARG;
              return DocumentBeforeSave(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].pboolVal, pDispParams->rgvarg[2].pboolVal);
         case 0x00000009: // NewDocument
              if (pDispParams->cArgs != 1) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              return NewDocument(pDispParams->rgvarg[0].pdispVal);
         case 0x0000000a: // WindowActivate
              if (pDispParams->cArgs != 2) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != VT_DISPATCH) return E_INVALIDARG;
              return WindowActivate(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].pdispVal);
         case 0x0000000b: // WindowDeactivate
              if (pDispParams->cArgs != 2) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != VT_DISPATCH) return E_INVALIDARG;
              return WindowDeactivate(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].pdispVal);
         case 0x0000000c: // WindowSelectionChange
              if (pDispParams->cArgs != 1) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              return WindowSelectionChange(pDispParams->rgvarg[0].pdispVal);
         case 0x0000000d: // WindowBeforeRightClick
              if (pDispParams->cArgs != 2) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != (VT_BOOL | VT_BYREF)) return E_INVALIDARG;
              return WindowBeforeRightClick(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].pboolVal);
         case 0x0000000e: // WindowBeforeDoubleClick
              if (pDispParams->cArgs != 2) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != (VT_BOOL | VT_BYREF)) return E_INVALIDARG;
              return WindowBeforeDoubleClick(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].pboolVal);
         }
         return S_OK;
    }

    //_______________________________________________________Word::ApplicationEvents2
    STDMETHODIMP EventListener::Startup()
    {
         return S_OK;
    }

    STDMETHODIMP EventListener::Quit()
    {
         return S_OK;
    }

    STDMETHODIMP EventListener::DocumentChange()
    {
         return S_OK;
    }

    STDMETHODIMP EventListener::DocumentOpen(IDispatch* document)
    {
         return S_OK;
    }

    STDMETHODIMP EventListener::DocumentBeforeClose(IDispatch* document, VARIANT_BOOL * Cancel)
    {
         //Com::Object Document(document);
         //*Cancel = -1; // To prevent closing the document
         return S_OK;
    }
    STDMETHODIMP EventListener::DocumentBeforePrint(IDispatch* document, VARIANT_BOOL * Cancel)
    {
         Com::Object Document(document);
         _variant_t fullname;
         Document.Get(L"Fullname", fullname);
         ::MessageBox(hWnd, fullname.bstrVal, L"Microsoft Word is Printing", MB_OK | MB_ICONINFORMATION);
         return S_OK;
    }

    STDMETHODIMP EventListener::DocumentBeforeSave(IDispatch* document, VARIANT_BOOL * SaveAsUI, VARIANT_BOOL * Cancel)
    {
         //Com::Object Document(document);
         return S_OK;
    }

    STDMETHODIMP EventListener::NewDocument(IDispatch* document)
    {
         //Com::Object Document(document);
         return S_OK;
    }

    STDMETHODIMP EventListener::WindowActivate(IDispatch* document, IDispatch* dindow)
    {
         //Com::Object Document(document);
         //Com::Object Window(window);
         return S_OK;
    }

    STDMETHODIMP EventListener::WindowDeactivate(IDispatch* Document, IDispatch* Window)
    {
         //Com::Object Document(document);
         //Com::Object Window(window);
         return S_OK;
    }

    STDMETHODIMP EventListener::WindowSelectionChange(IDispatch* selection)
    {
         //Com::Object Selection(selection);
         return S_OK;
    }

    STDMETHODIMP EventListener::WindowBeforeRightClick(IDispatch* Selection, VARIANT_BOOL * Cancel)
    {
         //Com::Object Selection(selection);
         return S_OK;
    }

    STDMETHODIMP EventListener::WindowBeforeDoubleClick(IDispatch* Selection, VARIANT_BOOL * Cancel)
    {
         //Com::Object Selection(selection);
         return S_OK;
    }


    Step D
    Edit the files: MsWait.h and MsWait.cpp.
    Edit the files: MsWait.h y MsWait.cpp.

    MsWait.h
    #pragma once //______________________________________ MsWait.h
    #include "Resource.h"
    #include "msword.tlh"
    #include "mso.tlh"
    #include "EventListener.h"

    class MsWait: public Win::Dialog
    {
    public:
         MsWait()
         {
              ::CoInitialize(NULL);
              listenerCookie = 0;
              connectionPoint = NULL;
         }
         ~MsWait()
         {
              if (connectionPoint != NULL) connectionPoint = NULL;
              ::CoUninitialize();
         }
         DWORD listenerCookie;
         EventListener eventListener;
         IConnectionPointPtr connectionPoint;
    protected:
         ...
    };

    MsWait.cpp
    ...
    void MsWait::Window_Open(Win::Event& e)
    {
         eventListener.hWnd = hWnd;

         Word::_ApplicationPtr Application = NULL;
         Word::DocumentsPtr Documents = NULL;
         Word::_DocumentPtr Document = NULL;
         _variant_t vtTemplate(L"Normal");
         _variant_t vtTrue(true);
         _variant_t vtVisible(true);
         _variant_t vtFalse(false);
         _variant_t newBlankDocument((short)Word::WdNewDocumentType::wdNewBlankDocument);
         HRESULT hr;
         Com::Exception ex;
         IConnectionPointContainerPtr connectionPointContainer = NULL;

         try
         {
              //_____________________________________________Open MS Word
              hr = Application.CreateInstance(L"Word.Application");
              ex.ok(L"Application.CreateInstance", hr);
              //_____________________________________________ Application->put_Visible
              hr = Application->put_Visible(vtTrue);
              ex.ok(L"Application->put_Visible", hr);
              //_____________________________________________ Application->get_Documents
              hr = Application->get_Documents(&Documents);
              ex.ok(L"Application->get_Documents", hr);
              //_____________________________________________ Documents->Add
              hr = Documents->Add(&vtTemplate, &vtFalse, &newBlankDocument, &vtVisible, &Document);
              ex.ok(L"Documents->Add", hr);
              //
              //_bstr_t fullname;
              //hr = Document->get_FullName(&fullname.GetBSTR());
              //ex.ok(L"Documents->Add", hr);
              //_____________________________________________ IConnectionPointContainer provides access to one or more IConnectionPoint
              connectionPointContainer = Application;
              if (connectionPointContainer == NULL) ex.ThrowNullPointer(L"connectionPointContainer");
              //_____________________________________________ Find the IConnectionPoint for Microsoft events
              connectionPointContainer->FindConnectionPoint(IID_IApplicationEvents2, &connectionPoint);
              if (connectionPoint == NULL) ex.ThrowNullPointer(L"connectionPoint");
              //______________________________________________ We would like to receive Microsoft Word events!
              hr = connectionPoint->Advise(&eventListener, &listenerCookie);
              ex.ok(L"connectionPoint->Advise", hr);
              eventListener.AddRef();
         }
         catch (Com::Exception& excep)
         {
              excep.Display(hWnd, L"MsWait");
         }
         catch (_com_error excep)
         {
              Com::Exception::Display(hWnd, excep, L"MsWait");
         }
    }

    void MsWait::btShutdowListener_Click(Win::Event& e)
    {
         if (connectionPoint == NULL) return;

         HRESULT hr;
         Com::Exception ex;

         try
         {
              // We do not want to receive Microsoft Word events any longer!
              // If Microsoft Word is closed, you cannot longer call Unadvise, thus
              // you must call Unadvise while Microsoft Word is open.
              // Note that closing the last document, will close Microsoft Word
              hr = connectionPoint->Unadvise(listenerCookie);
              ex.ok(L"connectionPoint->UnAdvise", hr);
              listenerCookie = 0;
         }
         catch (Com::Exception& excep)
         {
              excep.Display(hWnd, L"MsWait");
         }
         catch (_com_error excep)
         {
              Com::Exception::Display(hWnd, excep, L"MsWait");
         }
         connectionPoint = NULL;
    }


    Step E
    To test the program:
    1. Run the program: Microsoft Word will open
    2. Type some text in the Microsoft Word document
    3. Print the document, a message box with the name of the Document will be shown
    4. Cancel the printing of the document
    5. Press the Shutdown Listener button
    6. Close Microsoft Word
    7. Close the MsWait program

    Para probar el programa:
    1. Ejecute el programa: Microsoft Word se abrirá
    2. Escriba algún texto en el documento de Microsoft Word
    3. Imprima el documento, una caja de mensaje con el nombre del Documento se mostrará
    4. Cancele la impresión del documento
    5. Presiona el botón de Shutdown Listener
    6. Cierre Microsoft Word
    7. Cierre el programa MsWait

    MsWaitRun

    Word::DocumentEvents

    Methods of Word::DocumentEvents2 (you may use the Object Browser to know more about the events of the Word::Document):
    1. BuildingBlockInsert: When a building block is inserted in the document
    2. Close(): When a document is closed
    3. ContentControlAfterAdd: After adding a content control to a document
    4. ContentControlBeforeContentUpdate: Before updating the content in a content control, only when the content comes from the Office XML data store
    5. ContentControlBeforeDelete: Before removing a content control from a document
    6. ContentControlBeforeStoreUpdate: Before updating the XML data store of the document with the value of a content control
    7. ContentControlOnEnter: When the user enters a content control
    8. ContentControlOnExit: When a user leaves a content control
    9. New(): When a new document based on a template is created (The program must be stored in the template)
    10. Open(): When a document is opened
    11. Sync: When the local copy of a document that is part of a document workspace is synchronized with the copy on the server
    12. XMLAfterInsert: When the user adds a new XML element to a document (When using Microsoft Word to edit an XML file)
    13. XMLBeforeDelete: When a user deletes an XML element from a document (When using Microsoft Word to edit an XML file)

    Métodos de Word::DocumentEvents2 (usted puede usar el Explorador de Objetos para conocer más sobre los eventos del Word::Document):
    1. BuildingBlockInsert: Cuando un Building Block es insertado en el documento
    2. Close(): Cuando un documento es cerrado
    3. ContentControlAfterAdd: Después de agregar un Content Control al documento
    4. ContentControlBeforeContentUpdate: Antes de actualizar el contenido en Content Control, solamente cuando el contenido viene de una almacén de datos de Office XML
    5. ContentControlBeforeDelete: Antes de eliminar un Content Control de un documento
    6. ContentControlBeforeStoreUpdate: Antes de actualizar el almacén de datos XML del documento con un valor de un Content Control
    7. ContentControlOnEnter: Cuando el usuario entra en un Content Control
    8. ContentControlOnExit: Cuando un usuario abandona un Content Control
    9. New(): Cuando un nuevo documento usando una Plantilla es creado (El programa debe estar almacenado en la plantilla)
    10. Open(): Cuando un documento se abre
    11. Sync: Cuando la copia local que es parte de un Workspace Document se sincroniza con la copia en el servidor
    12. XMLAfterInsert: Cuando el usuario agrega un elemento de XML al documento (Cuando se usar Microsoft Word para editar una archivo de XML)
    13. XMLBeforeDelete: Cuando el usuario elimina un elemento de XML del documento (Cuando se usar Microsoft Word para editar una archivo de XML)

    Content Controls

    They allow designing Microsoft Word documents than can have a user interface (GUI: check box, radio button, drop-down list, etc.). Content Controls can be also used to prevent users from editing part of a document. Content Controls can be used to connect Microsoft Word to a database. By default the Developer Tab is hidden in Microsoft Word; you can customize Microsoft Word to make the Developer Tab visible as shown below.
    Estos permiten diseñar documentos de Microsoft Word que pueden tener una interface para el usuario (GUI: check box, radio button, drop-down list, etc.). Los Controles de Contenido también pueden ser usados para evitar que los usuarios editen parte del documento. Los Controles de Contenido pueden ser usados para conectar Microsoft Word a una base de datos. Por defecto la Pestaña del Programador (Ficha del Programador) está escondida en Microsoft Word; usted puede personalizar Microsoft Word para hacer visible la Pestaña del Programador como se muestra debajo.

    DeveloperTabAdd

    DeveloperTab

    Word 2016

    Use File > Options > Customize Ribbon and on the second column, check Developer.
    Use Archivo > Opciones > Personalizar Cinta de Opciones y en la segunda columna, marque Desarrollador.

    Building Blocks

    They are predefined pieces of document content that can be saved for future use. They can contain: text, tables, paragraphs, etc. They can be used for headers, or parts of a document that are frequently required.
    Estas son piezas predefinidas con el contenido de un documento que pueden ser almacenadas para usarlas más tarde. Estas puede contener: texto, tablas, párrafos, etc. Estos pueden ser usados para encabezados, o partes de un documento que son requeridas con frecuencia.

    BuildingBlock

    Problem 2
    Create a program so called MsAlert to test Word.Document.DocumentEvents. Please review the steps of the previous problem before working on this problem. You will need the files: mso.tlh, mso.tli and msword.tlh.
    Cree un programa llamado MsAlert para probar Word.Document.DocumentEvents. Por favor, repase los pasos del problema previo antes de trabajar en este problema. Usted necesitará los archivos: mso.tlh, mso.tli y msword.tlh.

    MsAlertRun

    DocEventListener.h
    #pragma once //_____________________________________________ DocEventListener.h
    #include "resource.h"
    #include "msword.tlh"
    #include "mso.tlh"

    // You can get the interface ID (IID) from the msword.tlh file
    const IID IID_DocumentEvents2 ={0x00020a02,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};

    class DocEventListener : public IDispatch
    {
    public:
         DocEventListener();
         ~DocEventListener();
         Win::Textbox* textbox;
         //____________________________________________________ IUnknown
         IUNKNOWN_BEGIN (IDispatch)
              QUERY_INTERFACE(IID_IDispatch, IDispatch)
              QUERY_INTERFACE(IID_DocumentEvents2, Word::DocumentEvents2)
         IUNKNOWN_END
         //_______________________________________________________ IDispatch
         STDMETHOD (GetTypeInfoCount) (UINT *pctinfo);
         STDMETHOD (GetTypeInfo) (UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
         STDMETHOD (GetIDsOfNames) (REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
         STDMETHOD (Invoke) (DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
         //_______________________________________________________Word::DocumentEvents2
         STDMETHOD (Close)();
         STDMETHOD (ContentControlAfterAdd)(/*[in]*/ IDispatch* newContentControl, /*[in]*/ VARIANT_BOOL* UndoRedo);
         STDMETHOD (ContentControlBeforeDelete)(/*[in]*/ IDispatch* newContentControl, /*[in]*/ VARIANT_BOOL UndoRedo);
         STDMETHOD (ContentControlOnExit)(/*[in]*/ IDispatch* contentControl, /*[in]*/ VARIANT_BOOL* Cancel);
         STDMETHOD (ContentControlOnEnter)(/*[in]*/ IDispatch* contentControl);
         STDMETHOD (BuildingBlockInsert)(IDispatch* range, BSTR name, BSTR category, BSTR blockType, BSTR templatex);
         // ...
    };


    DocEventListener.cpp
    #include "stdafx.h" //_____________________________________________ DocEventListener.cpp
    #include "DocEventListener.h"

    DocEventListener::DocEventListener()
    {
         textbox = NULL;
    }

    DocEventListener::~DocEventListener()
    {
    }

    //_______________________________________________________ IDispatch
    STDMETHODIMP DocEventListener::GetTypeInfoCount(UINT *pctinfo)
    {
         *pctinfo = 0;
         return S_OK;
    }

    STDMETHODIMP DocEventListener::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
    {
         return E_NOTIMPL;
    }

    STDMETHODIMP DocEventListener::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
    {
         return E_NOTIMPL;
    }

    STDMETHODIMP DocEventListener::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
         DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
    {
         if (riid != IID_NULL) return E_INVALIDARG;

         switch (dispIdMember)
         {
         case 0x00000006: // Close()
              return Close();
         case 0x0000000C: // ContentControlAfterAdd
              if (pDispParams->cArgs != 2) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != (VT_BOOL | VT_BYREF)) return E_INVALIDARG;
              return ContentControlAfterAdd(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].pboolVal);
         case 0x0000000D: // ContentControlBeforeDelete
              if (pDispParams->cArgs != 2) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != (VT_BOOL)) return E_INVALIDARG;
              return ContentControlBeforeDelete(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].boolVal);
         case 0x0000000E: //ContentControlOnExit
              if (pDispParams->cArgs != 2) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != (VT_BOOL | VT_BYREF)) return E_INVALIDARG;
              return ContentControlOnExit(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].pboolVal);
         case 0x0000000F: // ContentControlOnEnter
              if (pDispParams->cArgs != 1) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              return ContentControlOnEnter(pDispParams->rgvarg[0].pdispVal);
         case 0x00000012: // BuildingBlockInsert
              if (pDispParams->cArgs != 5) return E_INVALIDARG;
              if (pDispParams->rgvarg[0].vt != VT_DISPATCH) return E_INVALIDARG;
              if (pDispParams->rgvarg[1].vt != VT_BSTR) return E_INVALIDARG;
              if (pDispParams->rgvarg[2].vt != VT_BSTR) return E_INVALIDARG;
              if (pDispParams->rgvarg[3].vt != VT_BSTR) return E_INVALIDARG;
              if (pDispParams->rgvarg[4].vt != VT_BSTR) return E_INVALIDARG;
              return BuildingBlockInsert(pDispParams->rgvarg[0].pdispVal, pDispParams->rgvarg[1].bstrVal,
                   pDispParams->rgvarg[2].bstrVal, pDispParams->rgvarg[3].bstrVal, pDispParams->rgvarg[4].bstrVal);
         // ...
         }
         return S_OK;
    }

    //_______________________________________________________Word::DocumentEvents2
    STDMETHODIMP DocEventListener::Close()
    {
         textbox->AppendText(L"Close\r\n");
         return S_OK;
    }

    STDMETHODIMP DocEventListener::ContentControlAfterAdd(IDispatch* newContentControl, VARIANT_BOOL* UndoRedo)
    {
         //Com::Object NewContentControl(newContentControl);
         textbox->AppendText(L"ContentControlAfterAdd\r\n");
         return S_OK;
    }

    STDMETHODIMP DocEventListener::ContentControlBeforeDelete(IDispatch* newContentControl, VARIANT_BOOL UndoRedo)
    {
         //Com::Object NewContentControl(newContentControl);
         textbox->AppendText(L"ContentControlBeforeDelete\r\n");
         return S_OK;
    }

    STDMETHODIMP DocEventListener::ContentControlOnExit(IDispatch* contentControl, VARIANT_BOOL* Cancel)
    {
         //Com::Object ContentControl(contentControl);
         textbox->AppendText(L"ContentControlOnExit\r\n");
         return S_OK;
    }

    STDMETHODIMP DocEventListener::ContentControlOnEnter(IDispatch* contentControl)
    {
         //Com::Object ContentControl(contentControl);
         textbox->AppendText(L"ContentControlOnEnter\r\n");
         return S_OK;
    }

    STDMETHODIMP DocEventListener::BuildingBlockInsert(IDispatch* range, BSTR name, BSTR category, BSTR blockType, BSTR templatex)
    {
         //Com::Object Range(range);
         textbox->AppendText(L"BuildingBlockInsert\r\n");
         return S_OK;
    }


    MsAlert.h
    #pragma once //______________________________________ MsAlert.h
    #include "Resource.h"
    #include "msword.tlh"
    #include "mso.tlh"
    #include "DocEventListener.h"
    class MsAlert: public Win::Dialog
    {
    public:
         MsAlert()
         {
              ::CoInitialize(NULL);
              listenerCookie = 0;
              connectionPoint = NULL;
         }
         ~MsAlert()
         {
              if (connectionPoint != NULL) connectionPoint = NULL;
              ::CoUninitialize();
         }
         DWORD listenerCookie;
         DocEventListener docEventListener;
         IConnectionPointPtr connectionPoint;
    protected:
         //______ Wintempla GUI manager section begin: DO NOT EDIT AFTER THIS LINE
         Win::Button btShutdownListener;
         Win::Textbox tbxOutput;
    protected:
         ...
    };


    MsAlert.cpp
    ...
    void MsAlert::Window_Open(Win::Event& e)
    {
         docEventListener.textbox = &tbxOutput;

         Word::_ApplicationPtr Application = NULL;
         Word::DocumentsPtr Documents = NULL;
         Word::_DocumentPtr Document = NULL;
         _variant_t vtTemplate(L"Normal");
         _variant_t vtTrue(true);
         _variant_t vtVisible(true);
         _variant_t vtFalse(false);
         _variant_t newBlankDocument((short)Word::WdNewDocumentType::wdNewBlankDocument);
         HRESULT hr;
         Com::Exception ex;
         IConnectionPointContainerPtr connectionPointContainer = NULL;

         try
         {
              //_____________________________________________Open MS Word
              hr = Application.CreateInstance(L"Word.Application");
              ex.ok(L"Application.CreateInstance", hr);
              //_____________________________________________ Application->put_Visible
              hr = Application->put_Visible(vtTrue);
              ex.ok(L"Application->put_Visible", hr);
              //_____________________________________________ Application->get_Documents
              hr = Application->get_Documents(&Documents);
              ex.ok(L"Application->get_Documents", hr);
              //_____________________________________________ Documents->Add
              hr = Documents->Add(&vtTemplate, &vtFalse, &newBlankDocument, &vtVisible, &Document);
              ex.ok(L"Documents->Add", hr);
              //_____________________________________________ IConnectionPointContainer provides access to one or more IConnectionPoint
              connectionPointContainer = Document;
              if (connectionPointContainer == NULL) ex.ThrowNullPointer(L"connectionPointContainer");
              //_____________________________________________ Find the IConnectionPoint for Document events
              connectionPointContainer->FindConnectionPoint(IID_DocumentEvents2, &connectionPoint);
              if (connectionPoint == NULL) ex.ThrowNullPointer(L"connectionPoint");
              //______________________________________________ We would like to receive Document events!
              hr = connectionPoint->Advise(&docEventListener, &listenerCookie);
              ex.ok(L"connectionPoint->Advise", hr);
              docEventListener.AddRef();
         }
         catch (Com::Exception& excep)
         {
              excep.Display(hWnd, L"MsAlert");
         }
         catch (_com_error excep)
         {
              Com::Exception::Display(hWnd, excep, L"MsAlert");
         }
    }


    void MsAlert::btShutdownListener_Click(Win::Event& e)
    {
         if (connectionPoint == NULL) return;
         HRESULT hr;
         Com::Exception ex;
         try
         {
              // We do not want to receive Document events any more
              hr = connectionPoint->Unadvise(listenerCookie);
              ex.ok(L"connectionPoint->UnAdvise", hr);
              listenerCookie = 0;
         }
         catch (Com::Exception& excep)
         {
              excep.Display(hWnd, L"MsAlert");
         }
         catch (_com_error excep)
         {
              Com::Exception::Display(hWnd, excep, L"MsAlert");
         }
         connectionPoint = NULL;
    }


    © Copyright 2000-2021 Wintempla selo. All Rights Reserved. Jul 22 2021. Home