Wednesday, August 15, 2007

SNTT - the Win32 API series - Finding an open window by caption

I already posted how you can find an application by its class name or if you know the full text of the titlebar. But what if you don't know the class name, or the text in the titlebar changes (such as Domino Designer)? Here is a way to search on partial matches in the titlebar.
(Declarations)
Declare Function GetForegroundWindow Lib "user32" () As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (Byval hwnd As Long, Byval lpString As String, Byval cch As Long) As Long
Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (Byval hwnd As Long) As Long
Declare Function GetWindow Lib "user32" (Byval hwnd As Long, Byval wCmd As Long) As Long

Const GW_HWNDNEXT = 2

Function API_GetHandleFromPartialCaption(sCaption As String) As Long
Dim lhWnd As Long
Dim sStr As String
API_GetHandleFromPartialCaption = False
'start with the current application
lhWnd = GetForegroundWindow
Do While lhWnd <> 0
sStr = String$(GetWindowTextLength(lhWnd) + 1, Chr$(0)) 'set the buffer to the length of the and fill it with null characters
GetWindowText lhWnd, sStr, Len(sStr) 'get the window title
sStr = Left$(sStr, Len(sStr) - 1) 'strip off the null chars
If Instr(1, sStr, sCaption) > 0 Then 'found it!
API_GetHandleFromPartialCaption = lhWnd
Exit Do
End If
'try again
lhWnd = GetWindow(lhWnd, GW_HWNDNEXT)
Loop
End Function
To use this, call API_GetHandleFromPartialCaption and you'll get back the hWnd of that application, or 0 if it's not found. What can you do with that? Well, you could close the application:
(Declarations)
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (Byval hwnd As Long, Byval wMsg As Long, Byval wParam As Long, lParam As Long) As Long
Const WM_CLOSE = &H10

Function CloseDesigner
Dim hWnd As Long

hWnd = API_GetHandleFromPartialCaption("IBM Lotus Domino Designer")
If hWnd > 0 Then
Call SendMessage(hWnd, WM_CLOSE, 0, 0)
End If
End Function
Or bring it to the foreground...
(Declarations)
Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long

Function SwitchToDesigner
Dim hWnd As Long

hWnd = API_GetHandleFromPartialCaption("IBM Lotus Domino Designer")
If hWnd > 0 Then
Call SetForegroundWindow(hWnd)
End If
End Function
(Note: this particular example could also be achieved with @LaunchApp("Designer").

This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.

1 comment:

  1. This code worked like a charm. It was exactly what I needed for my LN form. Thanks!

    ReplyDelete