How To Obtain the Window Handle for an Office Automation Server with MFC (261997)



The information in this article applies to:

  • Microsoft Office PowerPoint 2003
  • Microsoft PowerPoint 2002
  • Microsoft PowerPoint 2000
  • Microsoft PowerPoint 97 for Windows
  • Microsoft Office Excel 2003
  • Microsoft Excel 2002
  • Microsoft Excel 2000
  • Microsoft Excel 97 for Windows
  • Microsoft Visual C++, 32-bit Professional Edition 5.0
  • Microsoft Visual C++, 32-bit Professional Edition 6.0
  • The Microsoft Foundation Classes (MFC)
  • Microsoft Office Access 2003
  • Microsoft Access 2002
  • Microsoft Access 2000
  • Microsoft Access 97
  • Microsoft Office Word 2003
  • Microsoft Word 2000
  • Microsoft Word 97 for Windows

This article was previously published under Q261997

SUMMARY

This article demonstrates how to obtain the window handle of an Office application with Microsoft Foundation Classes (MFC) while automating that application from Visual C++.

MORE INFORMATION

The object models for most Microsoft Office applications do not expose properties for retrieving the application window handles. To determine the window handle of an Office application that you are automating, you can use the FindWindow API function with the class name for the application's top-most window. If the application can have multiple instances running at the same time, then you may need to account for this so that you retrieve the correct window handle. The sections below illustrate techniques that you can use for retrieving the window handle for both single and multiple instance applications.

Note The Microsoft Access object model exposes the function hWndAccessApp for the _Application object for determining the window handle for the application. Additionally, Microsoft Excel 2002 is the first version of Excel to introduce an hWnd property for its Application object. With respect to Microsoft Excel 2002 and Microsoft Access versions 97 and later, because these Office applications provide a means through their respective object models to retrieve the window handle for the application, the FindWindow approach discussed in this article is not necessary.

Find the Window Handle for an Application That Is Single Instance

The following steps illustrate how you can use the FindWindow function with a Visual C++ Automation client to determine the window handle for an out-of-process Automation server that can have only a single instance. This is the technique you would employ when using Microsoft PowerPoint as your Automation server.

Step-by-step example
  1. Create a new dialog-based MFC EXE project.
  2. Add a button to your dialog box and a BN_CLICKED-handler for it.
  3. Open ClassWizard (CTRL+W), click the Automation tab, click Add Class, and select From a type library.
  4. Go to the directory where you installed Office (for example, C:\Program Files\Microsoft Office\Office) and choose Msppt9.olb.
  5. Select all the classes that ClassWizard finds, and click OK to get back to your project. ClassWizard has generated some automation wrapper classes from the PowerPoint type library and created the files Msppt9.h and Msppt9.cpp.
  6. Add the following code to your button handler:
    	
    // Start PowerPoint
    _Application app;
    COleException e;
    if(!app.CreateDispatch("PowerPoint.Application", &e)) {
    	CString str;
    	str.Format("CreateDispatch() failed w/err 0x%08lx", e.m_sc),
    		AfxMessageBox(str, MB_SETFOREGROUND);
    	return;
    }
    	
    // Get Presentations collection and add a new presentation.
    Presentations presSet(app.GetPresentations());
    _Presentation pres(presSet.Add(TRUE));
    	
    // Get Slides collection and add a new slide.
    Slides slideSet(pres.GetSlides());
    _Slide slide1(slideSet.Add(1, 2));
    	
    // Add text to slide, by navigating the slide as follows:
    // slide1.shapes(#).TextFrame.TextRange.Text
    {
    	Shapes shapes(slide1.GetShapes());
    	Shape shape(shapes.Item(COleVariant((long)1)));
    	TextFrame textFrame(shape.GetTextFrame());
    	TextRange textRange(textFrame.GetTextRange());
    	textRange.SetText("Window Handle of PowerPoint Application");
    	}
    
    // Get the Window Handle
    HWND hWndPpt = ::FindWindow ("PP9FrameClass", NULL);
    
    ::ShowWindow (hWndPpt, SW_SHOWNORMAL);
    // You can make the application visible using:
    // app.SetVisible(TRUE);
    // Here ShowWindow API is used to demonstrate the use of 
    // the Window Handle got from FindWindow<BR/>
           ::MessageBox(NULL, "Now displaying PPT using the ShowWindow API", "", MB_SETFOREGROUND);
    
    {
    
    		Shapes shapes(slide1.GetShapes());
    		Shape shape(shapes.Item(COleVariant((long)2)));
    		TextFrame textFrame(shape.GetTextFrame());
    		TextRange textRange(textFrame.GetTextRange());
    		textRange.SetText("hWndPpt contains the Window Handle of the PowerPoint application.  You can "
    					"use this Window Handle in various Win 32 APIs, such as SetForeGroundWindow, "
    					"which require a Window Handle parameter to be supplied.\r\n"
    					"This example uses the Window Handle in the ShowWindow API.\r\n\r\n"
    
    					"All done.  PowerPoint will close in 15 seconds.");
    	}
    
    
    // Prepare and run a slide show.
    {
    	 SlideShowSettings sss(pres.GetSlideShowSettings());
    	 sss.SetShowType(3); // Kiosk.
    	 sss.SetLoopUntilStopped(TRUE);
             sss.SetRangeType(1); // Show all.
    	 sss.SetAdvanceMode(2); // Use slide timings.
    	 SlideShowWindow ssw(sss.Run()); // Run show.
    }
    
    // Sleep so user can watch slide show.
    ::Sleep(15000);
    
    // Tell PowerPoint to quit.
    app.Quit(); 	
    					
  7. Add the following lines just before implementing your button handler:
    #include "msppt9.h"
    
    // Ole initialization class.
    class OleInitClass {
    public:
       OleInitClass() {
    	  OleInitialize(NULL);
       }
       ~OleInitClass() {
    	  OleUninitialize();
       }
    };
    // This global class calls OleInitialize() at
    // application startup, and calls OleUninitialize()
    // at application exit.
    OleInitClass g_OleInitClass; 
    					
  8. Compile and run the program. Click the button and note that PowerPoint starts a single slide presentation and closes down in 15 seconds.

Find the Window Handle for an Application That Can Have Multiple Instances

Some applications, such as Microsoft Excel or Microsoft Word, can have multiple instances running at the same time. To retrieve the handle to the application instance that you are automating, you can first use Automation to change the title of an application to a unique value and then use FindWindow to retrieve its window handle. The following steps illustrate this technique by using Microsoft Excel as the Automation server.

Step-by-Step example
  1. Create a new dialog-based MFC EXE project.
  2. Add a button to your dialog box and a BN_CLICKED-handler for it.
  3. Open ClassWizard (CTRL+W), click the Automation tab, click Add Class, and select From a type library.
  4. Go to the directory where you installed Office (for example, C:\Program Files\Microsoft Office\Office) and choose Excel9.olb.
  5. Select all the classes that ClassWizard finds, and then click OK to get back to your project. ClassWizard has generated some automation wrapper classes from the Excel type library and created the files excel9.h and excel9.cpp.
  6. Add the following code to your button handler:
    COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
    	
    _Application app;
    
    Workbooks books;
    _Workbook book;
    Worksheets sheets;
    _Worksheet sheet;
    	
    // Start Excel and get Application object.
    if(!app.CreateDispatch("Excel.Application"))
    {
    	AfxMessageBox("Couldn't start Excel and get Application object.");
    		return;
    }
    	
    
    //Get a new workbook.
    books = app.GetWorkbooks();
    book = books.Add (covOptional);
    	
    app.SetCaption ("New Caption Supplied by Program");
    	
    // Get the Window Handle
    HWND hWndXL = ::FindWindow ("XLMAIN", app.GetCaption ());
    	
    // Set the original caption back
    app.SetCaption ("");
    	
    ::ShowWindow (hWndXL, SW_SHOWNORMAL);
    // You can make the application visible using:
    // app.SetVisible(TRUE);
    // Here ShowWindow API is used to demonstrate the use of 
    // the Window Handle got from FindWindow
    	
    AfxMessageBox ("hWndXL contains the Window Handle of the Excel application.  You can use\n"
    	"this Window Handle in various Win 32 APIs, such as SetForeGroundWindow,\n"
    	"which require a Window Handle parameter to be supplied.\n\n"
    	"This example uses the Window Handle in the ShowWindow API.\n\n"
    	"All done.  Press OK to close Excel.", MB_SETFOREGROUND);
    	
    // Tell Excel to quit.
    app.Quit();
    					
  7. Add the following lines just before implementing your button handler:
    #include "excel9.h"
    
    // Ole initialization class.
    class OleInitClass {
    public:
    	  OleInitClass() {
    		 OleInitialize(NULL);
    	  }
    	  ~OleInitClass() {
    		  OleUninitialize();
    	  }
    };
    // This global class calls OleInitialize() at
    // application startup, and calls OleUninitialize()
    // at application exit.
    OleInitClass g_OleInitClass; 
    					
  8. Compile and run the program. Click the button and note that Excel starts and a message box appears indicating that the window handle obtained is used in the ShowWindow API as an example. Click OK to dismiss the message box, and then quit Excel.

REFERENCES

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

178749 How To Create automation project using MFC and a type library

183009 How To Enumerate Windows using the WIN32 API

175030 How To Enumerate applications using Win32 APIs

179706 How To Use MFC to automate Excel and create/format a new workbook


Modification Type:MinorLast Reviewed:8/19/2004
Keywords:kbAutomation kbhowto KB261997