You are currently offline, waiting for your internet to reconnect

How To Get a Window Handle Without Specifying an Exact Title

This article was previously published under Q147659
SUMMARY
The Visual Basic AppActivate command can only activate a window if you knowthe exact window title. Similarly, the Windows FindWindow function can onlyfind a window handle if you know the exact window title.

This article demonstrates how to search for a window that has a title thatis like the title you specify -- but not an exact match. The sample codesearches through the available windows, comparing the window titles to apattern by using the Visual Basic Like operator. You can also use thesample code to find a window based on its class name or ID. This can beextremely helpful when you need to send keystrokes to other Applications.
MORE INFORMATION

FindWindowLike Function

The sample code provides a find window function named FindWindowLike.FindWindowLike does a recursive search for windows matching the descriptionyou give it. After completing the search, FindWindow returns the number ofwindows it found that match your description. It also returns the windowhandles in an array that you pass to it. Once you have a window handle, youcan call many Windows API functions to manipulate it. For example, youcould set the focus to it, or move it. The example in this article showshow to set the focus.

Parameters Passed to FindWindowLike Function

The FindWindowLike function searches for windows based on the fourparameters you pass it:

  • The hWndStart parameter specifies the handle of the window you want to search under. For example, if you gave the handle to a Visual Basic form, FindWindowLike would search through all the controls on that form. If you pass 0 for hWndStart, FindWindowLike searches through all available windows.
  • The WindowText parameter specifies the pattern used to compare window text. The Caption property of a Visual Basic Form is the same as the window text. The pattern is any string following the guidelines for the Visual Basic Like operator.
  • The ClassName parameter specifies a pattern used to compare a window class name. A window's class name identifies the type of window. You can find out a window's class name by using the utility SPY.EXE that comes with Microsoft Visual C/C++, or you can use the example given in the following article in the Microsoft Knowledge Base:
    112649 How To Get a Window's Class Name and Other Attributes
FindWindowLike uses the Visual Basic Like operator when comparing classnames.

  • The ID parameter specifies a specific child ID. This parameter is very useful for finding specific controls in a window. A window's ID can also be found by using SPY.EXE or the technique described in the following article in the Microsoft Knowledge Base:
    112649 How to Get a Window's Class Name and Other Attributes
    The ID parameter can be a decimal number or a hexadecimal string. If you use a hexadecimal string, prefix the hexadecimal number with &H. If you do not want to search for a specific ID, specify Null for the ID parameter.

FindWindowLike Examples and Their Results

Here are several example calls to FindWindowLike and the results it shouldreturn:

  1. r = FindWindowLike(hWnds(), 0, "*", "*", Null)
    Returns: All the available windows.
  2. r = FindWindowLike(hWnds(), 0, "*Excel*", "*", Null)
    Returns: All the windows with "Excel" in the window text.
  3. r = FindWindowLike(hWnds(), 0, "Microsoft Excel*", "XLMAIN", Null)
    Returns: All the windows having window text that begins with "Microsoft Excel" and that contains class name "XLMAIN"
  4. r = FindWindowLike(hWnds(), Form1.Hwnd, "*", "*", "&HA1")
    Returns: The child window of the Form1 window that has an ID of hexadecimal A1.
  5. r = FindWindowLike(hWnds(), Form1.Hwnd, "*", "*", 2)
    Returns: The child window of the Form1 window that has an ID of 2.

Uses for FindWindowLike



The FindWindowLike function can be especially powerful when used in aseries of searches. For example, you can search once to find an openinstance of the PIF Editor that comes with Microsoft Windows. Then once youhave the handle to the PIF Editor window, you can search again for aspecific control's window handle by using the PIF Editor's window handleand the ID of the control's window. Here is an example:
r = FindWindowLike(hWnds(), 0, "PIF Editor*", "Pif", Null)
' Assuming the previous returned at least one handle
r = FindWindowLike(hWnds(), hWnds(1), "*", "*", 103)
After you have the control's window handle, you can give it the focus andsend it keystrokes. In addition, there are a lot of other things you can doonce you have a window's handle.

Sample Code

The sample code listed in the example below uses several Windows APIfunctions to accomplish what was described above. Here are the key onesincluding descriptions of their uses:

  • GetDeskTopWindow gets the handle to the DeskTop window when 0 (zero) is passed as the hWndStart, so you can use it as a starting point for the recursive search.
  • GetWindow gets a window handle based on a relationship to another window handle, so you can use it to get child windows and their siblings.
  • GetWindowText gets the text of a window for comparison to the passed WindowText.
  • GetClassName gets a window's class name, which you can compare to the passed ClassName.
  • GetWindowLong gets information about a window. The sample code uses it to get the ID number of a window for comparison with the passed ID.

Step-by-Step Example

  1. Start a new Standard EXE project. Form1 is created by default.
  2. Add three Text boxes (Text1, Text2, and Text3) to Form1.
  3. Put the following code in the Form1 click event:
          Private Sub Form_Click()      Static hWnds() As Variant      ' Find window with title "Form1":      r = FindWindowLike(hWnds(), 0, "Form1", "*", Null)      If r = 1 Then      Debug.Print "Found "; Hex(hWnds(1))      ' Find a child window of "Form1" with ID=2:      ' Notice that the handle from the first search is used.      r = FindWindowLike(hWnds(), hWnds(1), "*", "*", "&H00000002")      If r = 1 Then      Debug.Print "Found child "; Hex(hWnds(1))      Debug.Print "Setting focus to child ..."      ' Set the focus to the child window with ID=2:      hw = hWnds(1)      r = SetFocusAPI(hw)      ElseIf r > 1 Then      ' This should not happen.      Debug.Print "Found more than one child ID=2"      Else      Debug.Print "Did not find child ID=2"      End If      ElseIf r > 1 Then      Debug.Print "Found "; r; " Windows"      End If      End Sub						
  4. From the Insert Menu select Module to add a new module to the project.
  5. Put the following code in the new module:
       Declare Function SetFocusAPI Lib "user32" Alias "SetForegroundWindow" _    (ByVal hwnd As Long) As Long   Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, _    ByVal wCmd As Long) As Long   Declare Function GetDesktopWindow Lib "user32" () As Long   Declare Function GetWindowLW Lib "user32" Alias "GetWindowLongA" _    ByVal hwnd As Long, ByVal nIndex As Long) As Long   Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long   Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _    (ByVal hwnd As Long, ByVal lpClassName As String, _     ByVal nMaxCount As Long) As Long   Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _    (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) _     As Long   Public Const GWL_ID = (-12)   Public Const GW_HWNDNEXT = 2   Public Const GW_CHILD = 5   'FindWindowLike   ' - Finds the window handles of the windows matching the specified   '   parameters   '   'hwndArray()   ' - An integer array used to return the window handles   '   'hWndStart   ' - The handle of the window to search under.   ' - The routine searches through all of this window's children and their   '   children recursively.   ' - If hWndStart = 0 then the routine searches through all windows.   '   'WindowText   ' - The pattern used with the Like operator to compare window's text.   '   'ClassName   ' - The pattern used with the Like operator to compare window's class   '   name.   '   'ID   ' - A child ID number used to identify a window.   ' - Can be a decimal number or a hex string.   ' - Prefix hex strings with "&H" or an error will occur.   ' - To ignore the ID pass the Visual Basic Null function.   '   'Returns   ' - The number of windows that matched the parameters.   ' - Also returns the window handles in hWndArray()   '   '----------------------------------------------------------------------   'Remove this next line to use the strong-typed declarations   #Const WinVar = True   #If WinVar Then   Function FindWindowLike(hWndArray() As Variant, _    ByVal hWndStart As Variant, WindowText As String, _     Classname As String, _  ID) As Integer Dim hwnd   Dim r   Static level   Static iFound   #ElseIf Win32 Then   Function FindWindowLike(hWndArray() As Long, ByVal hWndStart As Long, _    WindowText As String, Classname As String, ID) As Long   Dim hwnd As Long   Dim r As Long   ' Hold the level of recursion:   Static level As Long   ' Hold the number of matching windows:   Static iFound As Long   #ElseIf Win16 Then   Function FindWindowLike(hWndArray() As Integer, _    ByVal hWndStart As Integer, WindowText As String, _    Classname As String, ID) As Integer   Dim hwnd As Integer   Dim r As Integer   ' Hold the level of recursion:   Static level As Integer   Hold the number of matching windows:   Static iFound As Integer   #End If   Dim sWindowText As String   Dim sClassname As String   Dim sID   ' Initialize if necessary:   If level = 0 Then   iFound = 0   ReDim hWndArray(0 To 0)   If hWndStart = 0 Then hWndStart = GetDesktopWindow()   End If   ' Increase recursion counter:   level = level + 1   ' Get first child window:   hwnd = GetWindow(hWndStart, GW_CHILD)   Do Until hwnd = 0   DoEvents ' Not necessary   ' Search children by recursion:   r = FindWindowLike(hWndArray(), hwnd, WindowText, Classname, ID)   ' Get the window text and class name:   sWindowText = Space(255)   r = GetWindowText(hwnd, sWindowText, 255)   sWindowText = Left(sWindowText, r)   sClassname = Space(255)   r = GetClassName(hwnd, sClassname, 255)   sClassname = Left(sClassname, r)   ' If window is a child get the ID:   If GetParent(hwnd) <> 0 Then   r = GetWindowLW(hwnd, GWL_ID)   sID = CLng("&H" & Hex(r))   Else   sID = Null   End If   ' Check that window matches the search parameters:   If sWindowText Like WindowText And sClassname Like Classname Then   If IsNull(ID) Then   ' If find a match, increment counter and   '  add handle to array:   iFound = iFound + 1   ReDim Preserve hWndArray(0 To iFound)   hWndArray(iFound) = hwnd   ElseIf Not IsNull(sID) Then   If CLng(sID) = CLng(ID) Then   ' If find a match increment counter and   '  add handle to array:   iFound = iFound + 1   ReDim Preserve hWndArray(0 To iFound)   hWndArray(iFound) = hwnd   End If   End If   Debug.Print "Window Found: "   Debug.Print "  Window Text  : " & sWindowText   Debug.Print "  Window Class : " & sClassname   Debug.Print "  Window Handle: " & CStr(hwnd)   End If   ' Get next child window:   hwnd = GetWindow(hwnd, GW_HWNDNEXT)   Loop   ' Decrement recursion counter:   level = level - 1   ' Return the number of windows found:   FindWindowLike = iFound   End Function
  6. Save the Project.
  7. Run the code, and then click the form.
First, the program searches for Form1. If Form1 is found, the programsearches Form1 for a control with an ID of 2. It should find one becauseVisual Basic numbers the IDs as you add controls. With three text boxes onForm1, one should have an ID of 2. After finding the control, the code setsthe focus to the window by calling SetFocusAPI.

If you set the focus to one of your controls before clicking the Form, youshould see the focus shift, always to the same control, when you click theform.
REFERENCES
Microsoft Developers Network Library. January 1997. Platform SDKReference.

"Visual Basic Programmer's Guide to the Windows API," Daniel Appleman,Ziff-Davis Press, 1993
Common API APIs
Properties

Article ID: 147659 - Last Review: 10/11/2006 18:40:47 - Revision: 2.4

  • Microsoft Visual Basic 5.0 Control Creation Edition
  • Microsoft Visual Basic 5.0 Learning Edition
  • Microsoft Visual Basic 5.0 Professional Edition
  • Microsoft Visual Basic 5.0 Enterprise Edition
  • Microsoft Visual Basic 4.0 Standard Edition
  • Microsoft Visual Basic 4.0 Professional Edition
  • Microsoft Visual Basic 4.0 32-Bit Enterprise Edition
  • kb32bitonly kbhowto kbprogramming KB147659
Feedback