Access Cookbook - Ken Getz [237]
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")
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
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.
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.
11.9. Retrieve a List of All Top-Level Windows
Problem
You know you can determine if specific applications are currently running (as shown in the Solution in Recipe 11.8), but now you'd like to obtain a list of all the running applications. That way, you could decide, as part of your application, what to present to your users. Is there a way to walk through all the open main windows and build up a list?
Solution
Windows includes API functions that allow you to walk down and around the tree of open windows, starting with the main desktop window. This solution provides a function that will do that for you, filling an array with information on each