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- Create a new dialog-based MFC EXE project.
- Add a button to your dialog box and a BN_CLICKED-handler
for it.
- Open ClassWizard (CTRL+W), click the Automation tab, click Add Class, and select From a type library.
- Go to the directory where you installed Office (for
example, C:\Program Files\Microsoft Office\Office) and choose Msppt9.olb.
- 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.
- 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();
- 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;
- 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- Create a new dialog-based MFC EXE project.
- Add a button to your dialog box and a BN_CLICKED-handler
for it.
- Open ClassWizard (CTRL+W), click the Automation tab, click Add Class, and select From a type library.
- Go to the directory where you installed Office (for
example, C:\Program Files\Microsoft Office\Office) and choose Excel9.olb.
- 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.
- 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();
- 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;
- 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.