8.2 Make Slow Forms Run Faster

11.8 Check to See if an Application Is Already Running

11.8.1 Problem

You need to start up other Windows programs from within your Access application for instance, to send data to Excel or to format a report in Word. If you just use the Shell command to start these programs, you may end up with multiple instances of the application. How can you tell if an application is already running before you attempt to start it?

11.8.2 Solution

There are a number of solutions to this problem, and none, unfortunately, are as easy as you might like. To ask Windows whether Excel is currently running and receive an answer, you must know the Windows class name for the main window of the application. This solution explains the format of the question and how to ask it. In addition, it demonstrates how to switch to a running application from your Access application.

If you have code that interacts with applications external to Access, it is often useful to be able to determine whether the application is running. The sample form, frmAppsRunning (Figure 11-10), asks Windows the question, "Is this app running?" for each of six predefined window classes, and you can add one more of your own. For each application that frmAppsRunning finds, it fills in the window handle (hWnd) column and the window caption column on the form. The AppActivate command in Access requires that you know the exact title of the window, so this form uses code from Chapter 4 (in basAccessCaption) to retrieve the caption for each running application. Finally, you can click on any of the enabled buttons in the righthand column to switch to the running application.

Try the sample form with Microsoft applications you have installed. Press F1 to bring up Help, and then switch back to Access and click on the Search button on the sample form. This will reinitiate the search for active applications, and it will find WINHELP.EXE running. Click on the question-mark icon to switch back to WinHelp.

Figure 11-10. frmAppsRunning shows the state of certain applications

figs/acb_1110.gif

Follow these steps to include this functionality in your own applications:

  1. Import the modules listed in Table 11-9 into your application.

     

    Table 11-9. Modules to import from 11-08.MDB

    Module

    Contains

    basCaption

    acbGetAccessCaption, acbGetWindowCaption, acbSetAccessCaption

    basUsage

    acbIsAppLoaded

     

  2. To be able to ask Windows the question, "Is some application running?", you'll need to know the Windows class name for the main window of the application. Table 11-10 lists the names for several Windows applications.

     

    Table 11-10. Windows application class names

    Application

    Class name

    Access

    OMain

    Excel

    XLMain

    Explorer

    ExploreWClass

    Outlook 2002

    rrctrl_renwnd32

    Notepad

    Notepad

    PowerPoint 2002

    PP10FrameClass

    WordPad

    WordPadClass

    Microsoft Word

    OpusApp

     

    The class names are somewhat arbitrary. Because they're assigned by the development staff, not by the marketing or documentation departments, class names often reflect the project's code name or the state of mind of the developer.

     

    Finding Class Names

    There are many ways to find the class names for applications' main windows. The simplest is to use the sample form for Section 11.9.2, which displays a list of open windows and their class names. If you want to know the class name for a specific application, open it and run the sample form. The second column will list the class name for you.

     

  3. To check whether a given application is currently running, use the acbIsAppLoaded function in basUsage. Pass a class name to this function as a parameter, and it returns the window handle of the application if it's running, or 0 if it's not. For example, this will return a nonzero value if Microsoft Word is currently running (note that the class names are not case-sensitive):

    hWnd = acbIsAppRunning("opusapp")
  4. Once you know the window handle for the application, you can use the AppActivate command in Access to make that application active. To do this, you'll need to know the exact window caption. To make that easier, you can call the acbGetWindowCaption function in basCaption before attempting to activate the application. For example, this code will switch to Excel, if it's running:

    Dim hWnd as Integer hWnd = acbIsAppLoaded("XLMain") If hWnd <> 0 Then    AppActivate acbGetWindowCaption(hWnd) End If
  5. If the application you want to activate isn't currently running (acbIsAppLoaded returned 0), use the Shell command to start it. In this case, you'll need to know the DOS executable filename for the given application (EXCEL.EXE, for example). The example form doesn't attempt to load the applications if they aren't already loaded, but your own application can load the program as needed.

11.8.3 Discussion

The acbIsAppLoaded function couldn't be simpler: It calls a single Windows API function. The entire routine looks like this:

Function acbIsAppLoaded (ByVal varClassName As Variant) As Long    If IsNull(varClassName) Then       acbIsAppLoaded = 0    Else       acbIsAppLoaded = acb_apiFindWindow(CStr(varClassName), 0&)    End If End Function

This routine allows you to pass in a class name. If the class name isn't null, the function calls the FindWindow API function (aliased as acb_apiFindWindow), which takes a class name and returns the window handle of the first instance of that class it finds. acbIsAppLoaded returns that handle to its caller.

This example uses the following code from basCaption to determine the caption of a window, given its window handle. Although this code isn't the focus of this section, you'll need to include it if you want to find a window's caption.

Declare Function acb_apiSetWindowText Lib "user32" _  Alias "SetWindowTextA" (ByVal hwnd As Long, _  ByVal lpString As String) As Long Declare Function acb_apiGetWindowText _  Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, _  ByVal lpString As String, ByVal aint As Long) As Long Public Function acbGetWindowCaption(ByVal hwnd As Long) As Variant    ' Get any window's caption, given its hWnd.    Dim strBuffer As String    Dim intLen As Integer    Const acbcMaxLen = 128    If hwnd <> 0 Then       strBuffer = Space(acbcMaxLen)       intLen = acb_apiGetWindowText(hwnd, strBuffer, acbcMaxLen)       acbGetWindowCaption = Left(strBuffer, intLen)    End If End Function

Don't expect acbIsAppLoaded to distinguish between multiple copies of the same application. That is, if you have two copies of Notepad running, you can't count on acbIsAppLoaded to return the handle to a specific instance of Notepad: it will return the handle of the first instance it comes across. But that shouldn't bother you, as you're simply trying to find out if any copy of the application is currently running.



Access Cookbook
Access Data Analysis Cookbook (Cookbooks)
ISBN: 0596101228
EAN: 2147483647
Year: 2005
Pages: 174

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net