Microsoft KB Archive/309309

From BetaArchive Wiki

Article ID: 309309

Article Last Modified on 8/23/2005



APPLIES TO

  • Microsoft Visual C++ .NET 2002 Standard Edition
  • Microsoft PowerPoint 2000 Standard Edition
  • Microsoft PowerPoint 2002 Standard Edition
  • Microsoft Visual C++ .NET 2003 Standard Edition
  • Microsoft Foundation Class Library 4.2



This article was previously published under Q309309


For a Microsoft Visual C# .NET version of this article, see 308825.
For a Microsoft Visual Basic .NET version of this article, see 308330.

IN THIS TASK

SUMMARY

REFERENCES

Note Microsoft Visual C++ .NET (2002) supports both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code.

SUMMARY

This article describes how to handle Microsoft PowerPoint 2000 events or PowerPoint 2002 events by using Microsoft Visual C++ .NET 2002 or Visual C++ .NET 2003 and Microsoft Foundation Classes.

back to the top

PowerPoint Events

PowerPoint fires events in response to user actions or in response to some methods that are called through Automation. The Application object in the PowerPoint object model fires these events on its outgoing interface, EApplication.

To view this interface and its methods, you can use the OLE/COM Object Viewer, as follows:

  1. On the Tools menu in Visual Studio .NET, select OLE/COM Object Viewer.
  2. Expand the node for Type Libraries and select Microsoft PowerPoint Object Library in the list.
  3. On the Object menu, select View to open the library in the ITypeLib Viewer.
  4. Expand the node for coclass Application and select EApplication.

Note that EApplication is derived from IDispatch and is not the dispinterface that is commonly used as a source interface. If the source interface is a dispinterface, you can determine the dispatch identifiers (DISPIDs) for its methods by using the OLE/COM Object Viewer. However, because EApplication is not a dispinterface, you cannot determine the DISPIDs for PowerPoint events by examining the type library.

The following table lists DISPIDs for the events that the PowerPoint 2000 and PowerPoint 2002 object models expose:

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



You can sink a PowerPoint event in your C++ application by calling IConnectionPointContainer::FindConnectionPoint to find the connection point for the desired event interface, and then IConnectionPoint::Advise with the IUnknown interface of your implementation for that event.

back to the top

Create a C++ Application to Handle PowerPoint Events

  1. Create a new dialog box-based application by using the Microsoft Foundation Classes (MFC) Application Wizard in Visual C++ .NET. Name your project PPTEventsDemo, and then accept the default settings. The dialog box is created by default, along with the corresponding Ppteventsdemodlg.cpp and Ppteventsdemodlg.h files.
  2. Add three buttons to your dialog box, and then name the buttons Launch PowerPoint, Establish Connection Point and Register Sink, and UnRegister Sink and Do Clean Up, respectively. Add a list box to the dialog box. The list box displays the names of the events as they occur.
  3. In the Project explorer window in Class View, right-click PPTEventsDemo, point to Add, and then click Add Class. In the Add Class dialog box, select MFC class from TypeLibrary and then click Open. This starts the Add Class from TypeLib wizard.
  4. Select Microsoft PowerPoint 10.0 object library (for PowerPoint 2002) or Microsoft PowerPoint 9.0 object library (for PowerPoint 2000) from the Available TypeLibraries drop-down list. The Interfaces list box displays all of the interfaces that the type library exposes. Select _Application and then click the > button. Accept the defaults and then click Finish. This generates the CApplication wrapper class, which is derived from COleDispatchDriver. The implementation and definition of this class is available in the Capplication.h file.
  5. In Visual Studio .NET, click Resource View on the View menu to show the PPTEventsDemo dialog box. Double-click Launch PowerPoint to show the Code View window for Ppteventsdemodlg.cpp, where an empty event handler has been inserted for the Click event of that button. Add the following code to the handler for the Launch PowerPoint button:

      if(!pptapp.CreateDispatch("Powerpoint.Application"))
      {
             AfxMessageBox("Could not create Powerpoint object.");
             return;
      }
    
      pptapp.put_Visible((long) 1);
    
                        
  6. Add the following code to the handler for the Establish Connection Point and Register Sink button:

    ///*********************** Start of code to get connection point **************
          //  Declare the events that you want to catch.
          // 
          //  Look for the coclass for Application in the Msppt9.olb typelib,
          //  then look for the word "source." The EApplication interface
          //  is the next search target. When you find it, you will see the 
          //  following GUID for the event interface.
          //  914934C2-5A91-11CF-8700-00AA0060263B
         static const GUID IID_IEApplication =
         {0x914934C2,0x5A91,0x11CF, {0x87,0x00,0x00,0xAA,0x00,0x60,0x26,0x3b}};
    
          //  Steps for setting up events.
          // 1. Get the IConnectionPointContainer interface of the server.
          // 2. Call IConnectionPointContainer::FindConnectionPoint()
          //    to find the event that you want to catch.
          // 3. Call IConnectionPoint::Advise() with the IUnknown
          //    interface of your implementation of the events.
    
          HRESULT hr;
    
          // Get the (PPT) IConnectionPointContainer interface of the server.
          IConnectionPointContainer *pConnPtContainer;
          hr = pptapp.m_lpDispatch->QueryInterface(
             IID_IConnectionPointContainer,
             (void **)&pConnPtContainer
          );
          if(FAILED(hr)) AfxMessageBox("Couldn't get IConnectionPointContainer interface.");
          ASSERT(!FAILED(hr));
    
          // Find a connection point for the events that you are interested in.
          hr = pConnPtContainer->FindConnectionPoint(
             IID_IEApplication,
             &m_pConnectionPoint
          );
          if(FAILED(hr)) AfxMessageBox("Couldn't find connection point via event GUID.");
          ASSERT(!FAILED(hr));
    
          //Instantiate the sink object.
          m_sink = new CMyPPTEventsHandler();
    
          //Update the list box when you obtain the events in the event handler.
          m_sink->m_pListBox = m_listBox;
    
         // Get the IUnknown interface of your event implementation.
          LPUNKNOWN pUnk = NULL;
          pUnk = m_sink->GetInterface(&IID_IUnknown);
          ASSERT(pUnk);
    
          // Setup advisory connection.
          hr = m_pConnectionPoint->Advise(pUnk, &m_sink->cookie);  
          ASSERT(!FAILED(hr));  
    
          // Release the IConnectionPointContainer interface.
          pConnPtContainer->Release();
    // *********************** End of code to get connection point ******************
    
                        
  7. Add the following code to a handler for the UnRegister Sink and Do Clean Up button:

    //Use the cookie to unregister the sink.
            m_pConnectionPoint->Unadvise(m_sink->cookie);
        m_pConnectionPoint->Release();
    //Detach the application object from the server.
        pptapp.DetachDispatch();
    
    
                        
  8. Add the following code to the bottom of the constructor in the CPPTEventsDemoDlg class:

        m_pConnectionPoint = NULL;
        pptapp = NULL;
                        
  9. Before you return from CPPTEventsDemoDlg::OnInitDialog, add the following line of code:

          //Get the MFC class pointer for the list box on the dialog box.
          m_listBox = (CListBox*) GetDlgItem(IDC_LIST1);
                        
  10. Be sure that you place the following #include statements at the beginning of the Ppteventsdemodlg.cpp file:

    #include "stdafx.h"
    #include "CApplication.h"
    #include "MyPPTEventsHandler.h"
    #include "PPTEventsDemo.h"
    #include "PPTEventsDemoDlg.h"
                        
  11. Forward declare the following classes in the Ppteventsdemodlg.h file:

    class CMyPPTEventsHandler;
    class CApplication;
                        
  12. Add the following declarations as private members to CPPTEventsDemoDlg:

            IConnectionPoint* m_pConnectionPoint;
        CApplication pptapp;
        CMyPPTEventsHandler* m_sink;
        CListBox* m_listBox; 
                        
  13. In Class View in Project Explorer, right-click PPTEventsDemo, point to Add, and then click Add Class. In the AddClass dialog box, select MFC class under Templates, and then click Open. Type CMyPPTEventsHandler for the class name, select CCmdTarget for the base class, and then select Automation. For other fields, accept the defaults. Click Finish. This creates a new CMyPPTEventsHandler MFC class that is derived from CCmdTarget. This class is defined in the Myppteventshandler.h file and is implemented in Myppteventshandler.cpp. This is the Event Handler class that contains methods that are called in response to the PowerPoint events.

  14. This creates a new In the Myppteventshandler.h file, forward declare the following class:

    class CPresentation;
                        
  15. This creates a new In the Myppteventshandler.h file, add the following members to the public declarations in the CMyPPTEventsHandler class:

    DWORD cookie;   
    CListBox* m_pListBox; 
                        
  16. This creates a new Add the following methods to the protected declarations in the CMyPPTEventsHandler class:

            void WindowSelectionChange(LPDISPATCH Pres);
        void WindowBeforeRightClick(LPDISPATCH Pres, VARIANT_BOOL* Cancel);
        void WindowBeforeDoubleClick(LPDISPATCH Pres, VARIANT_BOOL* Cancel);
        void PresentationClose ( LPDISPATCH Pres);
        void PresentationSave( LPDISPATCH Pres);
        void PresentationOpen( LPDISPATCH Pres);
        void NewPresentation( LPDISPATCH Pres);
        void PresentationNewSlide( LPDISPATCH Pres);
        void WindowActivate( LPDISPATCH Pres,LPDISPATCH Wn);
        void WindowDeactivate(LPDISPATCH Pres, LPDISPATCH Wn);
        void SlideShowBegin(LPDISPATCH Wn);
        void SlideShowNextBuild( LPDISPATCH Wn);
        void SlideShowNextSlide( LPDISPATCH Wn);
        void SlideShowEnd( LPDISPATCH Pres);
        void PresentationPrint(LPDISPATCH Pres);
        void SlideSelectionChanged(LPDISPATCH SldRange);
        void ColorSchemeChanged(LPDISPATCH SldRange);
        void PresentationBeforeSave(LPDISPATCH Pres, VARIANT_BOOL * Cancel);
        void SlideShowNextClick(LPDISPATCH Wn, LPDISPATCH nEffect);
        void PresentationPrint(LPDISPATCH Pres);
    
                        

    These are the PowerPoint event handlers.

    NOTE: The following 4 event handlers are not available in PowerPoint 2000, and are not called if the client has PowerPoint 2000:

        void SlideSelectionChanged(LPDISPATCH SldRange);
        void ColorSchemeChanged(LPDISPATCH SldRange);
        void PresentationBeforeSave(LPDISPATCH Pres, VARIANT_BOOL * Cancel);
        void SlideShowNextClick(LPDISPATCH Wn, LPDISPATCH nEffect);
                        
  17. This creates a new Replace the entire contents of Myppteventshandler.cpp with the following:

    // MyPPTEventsHandler.cpp : implementation file.
    // 
    
    #include "stdafx.h"
    #include "PPTEventsDemo.h"
    #include "MyPPTEventsHandler.h"
    
    
    // CMyPPTEventsHandler.
    
    IMPLEMENT_DYNAMIC(CMyPPTEventsHandler, CCmdTarget)
    CMyPPTEventsHandler::CMyPPTEventsHandler()
    {
        EnableAutomation();
    }
    
    CMyPPTEventsHandler::~CMyPPTEventsHandler()
    {
    }
    
    
    void CMyPPTEventsHandler::OnFinalRelease()
    {
        // When the last reference for an Automation object is released,
        // OnFinalRelease is called. The base class automatically
        // deletes the object. Add additional cleanup required for your
        // object before you call the base class.
    
        CCmdTarget::OnFinalRelease();
    }
    
    
    BEGIN_MESSAGE_MAP(CMyPPTEventsHandler, CCmdTarget)
    END_MESSAGE_MAP()
    
    
    BEGIN_DISPATCH_MAP(CMyPPTEventsHandler, CCmdTarget)
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"WindowSelectionChange",2001,WindowSelectionChange,VT_EMPTY, VTS_DISPATCH)
        DISP_FUNCTION_ID(CMyPPTEventsHandler , "WindowBeforeRightClick", 2002 ,WindowBeforeRightClick, VT_EMPTY , VTS_DISPATCH VTS_BOOL)
        DISP_FUNCTION_ID(CMyPPTEventsHandler , "WindowBeforeDoubleClick", 2003 ,WindowBeforeDoubleClick, VT_EMPTY, VTS_DISPATCH VTS_BOOL)
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"PresentationClose",2004,PresentationClose,VT_EMPTY, VTS_DISPATCH)
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"PresentationSave",2005,PresentationSave,VT_EMPTY, VTS_DISPATCH)
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"PresentationOpen",2006,PresentationOpen,VT_EMPTY, VTS_DISPATCH)
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"NewPresentation",2007,NewPresentation,VT_EMPTY, VTS_DISPATCH)
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"PresentationNewSlide",2008,PresentationNewSlide,VT_EMPTY, VTS_DISPATCH)
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"WindowActivate",2009,WindowActivate,VT_EMPTY, VTS_DISPATCH VTS_DISPATCH)
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"WindowDeactivate",2010,WindowDeactivate,VT_EMPTY, VTS_DISPATCH VTS_DISPATCH)
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"SlideShowBegin",2011,SlideShowBegin,VT_EMPTY, VTS_DISPATCH )
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"SlideShowNextBuild",2012,SlideShowNextBuild,VT_EMPTY, VTS_DISPATCH )
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"SlideShowNextSlide",2013,SlideShowNextSlide,VT_EMPTY, VTS_DISPATCH )
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"SlideShowEnd",2014,SlideShowEnd,VT_EMPTY, VTS_DISPATCH )
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"PresentationPrint",2015,PresentationPrint,VT_EMPTY, VTS_DISPATCH )
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"SlideSelectionChanged",2016,SlideSelectionChanged,VT_EMPTY, VTS_DISPATCH )
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"ColorSchemeChanged",2017,ColorSchemeChanged,VT_EMPTY, VTS_DISPATCH )
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"PresentationBeforeSave",2018,PresentationBeforeSave,VT_EMPTY, VTS_DISPATCH VTS_BOOL)
        DISP_FUNCTION_ID(CMyPPTEventsHandler,"SlideShowNextClick",2019,SlideShowNextClick,VT_EMPTY, VTS_DISPATCH VTS_DISPATCH )
        
    END_DISPATCH_MAP()
    
    //The GUUID is different from the one originally generated by Class Wizard. This GUUID is the same as the one for the EApplication outgoing event interface.
    static const IID IID_IMyPPTEventsHandler =
    {0x914934C2,0x5A91,0x11CF, {0x87,0x00,0x00,0xAA,0x00,0x60,0x26,0x3b}};
    
    
    BEGIN_INTERFACE_MAP(CMyPPTEventsHandler, CCmdTarget)
        INTERFACE_PART(CMyPPTEventsHandler, IID_IMyPPTEventsHandler, Dispatch)
    END_INTERFACE_MAP()
    
    
    // CMyPPTEventsHandler message handlers.
    
    void CMyPPTEventsHandler::WindowSelectionChange(LPDISPATCH Pres)
    {
        m_pListBox->AddString("WindowSelectionChange");
        return ; 
    }
    void CMyPPTEventsHandler::WindowBeforeRightClick(LPDISPATCH Pres, VARIANT_BOOL* Cancel)
    {
        m_pListBox->AddString("WindowBeforeRightClick");
        return ;
    }
    
    void CMyPPTEventsHandler::WindowBeforeDoubleClick(LPDISPATCH Pres, VARIANT_BOOL* Cancel)
    {
        m_pListBox->AddString("WindowBeforeDoubleClick");
        return;
    }
    
    void CMyPPTEventsHandler::PresentationClose ( LPDISPATCH Pres)
    {
        m_pListBox->AddString("PresentationClose");
        return ;
    }
    
    void CMyPPTEventsHandler::PresentationSave( LPDISPATCH Pres)
    {
        m_pListBox->AddString("PresentationSave");
        return ;
    }
    
    
    
    void CMyPPTEventsHandler::PresentationOpen( LPDISPATCH Pres)
    {
        m_pListBox->AddString("PresentationOpen");
        return ;
    }
    void CMyPPTEventsHandler::NewPresentation( LPDISPATCH Pres)
    {
        m_pListBox->AddString("NewPresentation");
        return ;
    }
    
    void CMyPPTEventsHandler::PresentationNewSlide( LPDISPATCH Pres)
    {
        m_pListBox->AddString("PresentationNewSlide");
        return ;
    }
    
    
    void CMyPPTEventsHandler::WindowActivate( LPDISPATCH Pres,LPDISPATCH Wn)
    {
        m_pListBox->AddString("WindowActivate");
        return ;
    }
    
    
    void CMyPPTEventsHandler::WindowDeactivate(LPDISPATCH Pres, LPDISPATCH Wn)
    {
        m_pListBox->AddString("WindowDeactivate");
        return ;
    }
    
    
    void  CMyPPTEventsHandler::SlideShowBegin(LPDISPATCH Wn)
    {
        m_pListBox->AddString("SlideShowBegin");
        return;
    }
    
    
    void  CMyPPTEventsHandler::SlideShowNextBuild( LPDISPATCH Wn)
    {
        m_pListBox->AddString("SlideShowNextBuild");
        return ;
    
    }
    
    
    void CMyPPTEventsHandler::SlideShowNextSlide( LPDISPATCH Wn)
    {
        m_pListBox->AddString("SlideShowNextSlide");
        return ;
    }
    
    void CMyPPTEventsHandler::SlideShowEnd( LPDISPATCH Pres)
    {
        m_pListBox->AddString("SlideShowEnd");
        return;
    }
    
    void CMyPPTEventsHandler::PresentationPrint(LPDISPATCH Pres)
    {
        m_pListBox->AddString("PresentationPrint");
        return;
    }
    
    //The following events are not available for PowerPoint 2000.
    void CMyPPTEventsHandler::SlideSelectionChanged(LPDISPATCH SldRange)
    {
        m_pListBox->AddString("SlideSelectionChanged");
        return ;
    }
    
    void CMyPPTEventsHandler::ColorSchemeChanged(LPDISPATCH SldRange)
    {
        m_pListBox->AddString("ColorSchemeChanged");
        return ;
    }
    
    void CMyPPTEventsHandler::PresentationBeforeSave(LPDISPATCH Pres, VARIANT_BOOL * Cancel)
    {
        m_pListBox->AddString("PresentationBeforeSave");
        return;
    }
    
    void CMyPPTEventsHandler::SlideShowNextClick(LPDISPATCH Wn, LPDISPATCH nEffect)
    {
        m_pListBox->AddString("SlideShowNextClick");
        return ;
    }
    
                        

    Note that the value of the IID_IMyPPTEventsHandler static constant is changed from the value that the Class Wizard originally generated. The value is changed to the following:

    static const IID IID_IMyPPTEventsHandler =
    {0x914934C2,0x5A91,0x11CF, {0x87,0x00,0x00,0xAA,0x00,0x60,0x26,0x3b}};
                        

    This is the GUID for the EApplication outgoing event interface for the PowerPoint Application class. Also, note that the dispatch map for this class maps the DISPIDs of the events to the event handler methods.

  18. This creates a new In the Ppteventsdemo.cpp file, add the following #include statement

    #include "CApplication.h"
                        

    before the following:

    #include "PPTEventsDemoDlg.h" 
                        
  19. This creates a new Add the following lines of code at the top of the InitInstance method of the Ppteventsdemoapp.cpp file:

    if(!AfxOleInit())
        {
            AfxMessageBox("Unable to initialize COM");
            return FALSE;
        }

back to the top

Test the Application

  1. Press F5 to build and run the program. The dialog box appears.
  2. Click Launch PowerPoint. PowerPoint starts and becomes visible.
  3. Click Establish Connection Point and Register Sink to set up the event sinks.
  4. Create a new presentation in PowerPoint. The WindowActivate, NewPresentation, PresentationNewSlide, SlideSelectionChange, and WindowSelectionChange events fire.
  5. Start the slide show and play it through the end. The SlideShowBegin, SlideShowNextSlide, and SlideShowEnd events fire.
  6. Save the presentation. The PresentationBeforeSave and PresentationSave events fire.
  7. Close the presentation. The PresentationClose event fires, and the events that were triggered by PowerPoint 2002 and handled by the program appear in the list box.


NOTE: These are the events that PowerPoint 2002 fires. You may not see some of these events in PowerPoint 2000.

  1. Click UnRegister Sink and Do Clean Up to disconnect the event sinks.
  2. Close the dialog box.

back to the top

REFERENCES

For additional information, click the article numbers below to view the articles in the Microsoft Knowledge Base:

254009 INFO: PowerPoint 2000 Event Demonstration Available for Download


308336 HOWTO: Use Automation to Create and Show a PowerPoint Presentation with Visual C++ .NET and MFC


For more information on Office Automation, see the following Microsoft Office Development support site:

Office Development Support Center
http://support.microsoft.com/ofd


back to the top


Additional query words: Power Point NET events C++ MFC connection powerpoint

Keywords: kbhowtomaster kbautomation _ik11561 kbgrpdso KB309309