You are currently offline, waiting for your internet to reconnect

How To Enumerate Windows Using the WIN32 API

This article was previously published under Q183009
SUMMARY
You can list Windows, including Child Windows, using the GetWindow API.However, an application that calls GetWindow to perform this task risksbeing caught in an infinite loop or referencing a handle to a window thathas been destroyed. Using EnumWindows for top-level Windows andEnumChildWindows for Child Windows or EnumThreadWindows for all non-childwindows associated with a thread is a preferred method and is demonstratedin this article.
MORE INFORMATION
EnumWindows enumerates all top-level Windows, but not Child Windows. TheEnumChildWindows function does not enumerate top-level windows owned by thespecified window nor does it enumerate any other owned windows. TheEnumThreadWindows function enumerates all non-child windows associated witha thread. This sample uses all three to list the Class and Title of Windowsit finds. Note that while all Windows have a Class, not all have a Title.

Step-by-Step Example

  1. Start a new project in Visual Basic. Form1 is created by default.
  2. Add two CommandButtons and a TextBox.
  3. Copy the following code into the Form's module:
          Option Explicit      Private Sub Command1_Click()         Dim lRet As Long, lParam As Long         Dim lhWnd As Long         lhWnd = Me.hwnd  ' Find the Form's Child Windows         ' Comment the line above and uncomment the line below to         ' enumerate Windows for the DeskTop rather than for the Form         'lhWnd = GetDesktopWindow()  ' Find the Desktop's Child Windows         ' enumerate the list         lRet = EnumChildWindows(lhWnd, AddressOf EnumChildProc, lParam)      End Sub      Private Sub Command2_Click()         Dim lRet As Long         Dim lParam As Long         'enumerate the list         lRet = EnumWindows(AddressOf EnumWinProc, lParam)         ' How many Windows did we find?         Debug.Print TopCount; " Total Top level Windows"         Debug.Print ChildCount; " Total Child Windows"         Debug.Print ThreadCount; " Total Thread Windows"         Debug.Print "For a grand total of "; TopCount + _         ChildCount + ThreadCount; " Windows!"      End Sub					
  4. Add a Module with the following code:
          Option Explicit      Type RECT         Left As Long         Top As Long         Right As Long         Bottom As Long      End Type      Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, _         lpRect As RECT) As Long      Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, _         ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, _         ByVal nHeight As Long, ByVal bRepaint As Long) As Long      Declare Function GetDesktopWindow Lib "user32" () As Long      Declare Function EnumWindows Lib "user32" _         (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long      Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent _         As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long      Declare Function EnumThreadWindows Lib "user32" (ByVal dwThreadId _         As Long, ByVal lpfn As Long, ByVal lParam As Long) As Long      Declare Function GetWindowThreadProcessId Lib "user32" _         (ByVal hwnd As Long, lpdwProcessId 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 TopCount As Integer     ' Number of Top level Windows      Public ChildCount As Integer   ' Number of Child Windows      Public ThreadCount As Integer  ' Number of Thread Windows      Function EnumWinProc(ByVal lhWnd As Long, ByVal lParam As Long) _         As Long         Dim RetVal As Long, ProcessID As Long, ThreadID As Long         Dim WinClassBuf As String * 255, WinTitleBuf As String * 255         Dim WinClass As String, WinTitle As String         RetVal = GetClassName(lhWnd, WinClassBuf, 255)         WinClass = StripNulls(WinClassBuf)  ' remove extra Nulls & spaces         RetVal = GetWindowText(lhWnd, WinTitleBuf, 255)         WinTitle = StripNulls(WinTitleBuf)         TopCount = TopCount + 1         ' see the Windows Class and Title for each top level Window         Debug.Print "Top level Class = "; WinClass; ", Title = "; WinTitle         ' Usually either enumerate Child or Thread Windows, not both.         ' In this example, EnumThreadWindows may produce a very long list!         RetVal = EnumChildWindows(lhWnd, AddressOf EnumChildProc, lParam)         ThreadID = GetWindowThreadProcessId(lhWnd, ProcessID)         RetVal = EnumThreadWindows(ThreadID, AddressOf EnumThreadProc, _         lParam)         EnumWinProc = True      End Function      Function EnumChildProc(ByVal lhWnd As Long, ByVal lParam As Long) _         As Long         Dim RetVal As Long         Dim WinClassBuf As String * 255, WinTitleBuf As String * 255         Dim WinClass As String, WinTitle As String         Dim WinRect As RECT         Dim WinWidth As Long, WinHeight As Long         RetVal = GetClassName(lhWnd, WinClassBuf, 255)         WinClass = StripNulls(WinClassBuf)  ' remove extra Nulls & spaces         RetVal = GetWindowText(lhWnd, WinTitleBuf, 255)         WinTitle = StripNulls(WinTitleBuf)         ChildCount = ChildCount + 1         ' see the Windows Class and Title for each Child Window enumerated         Debug.Print "   Child Class = "; WinClass; ", Title = "; WinTitle         ' You can find any type of Window by searching for its WinClass         If WinClass = "ThunderTextBox" Then    ' TextBox Window            RetVal = GetWindowRect(lhWnd, WinRect)  ' get current size            WinWidth = WinRect.Right - WinRect.Left ' keep current width            WinHeight = (WinRect.Bottom - WinRect.Top) * 2 ' double height            RetVal = MoveWindow(lhWnd, 0, 0, WinWidth, WinHeight, True)            EnumChildProc = False         Else            EnumChildProc = True         End If      End Function      Function EnumThreadProc(ByVal lhWnd As Long, ByVal lParam As Long) _         As Long         Dim RetVal As Long         Dim WinClassBuf As String * 255, WinTitleBuf As String * 255         Dim WinClass As String, WinTitle As String         RetVal = GetClassName(lhWnd, WinClassBuf, 255)         WinClass = StripNulls(WinClassBuf)  ' remove extra Nulls & spaces         RetVal = GetWindowText(lhWnd, WinTitleBuf, 255)         WinTitle = StripNulls(WinTitleBuf)         ThreadCount = ThreadCount + 1         ' see the Windows Class and Title for top level Window         Debug.Print "Thread Window Class = "; WinClass; ", Title = "; _         WinTitle         EnumThreadProc = True      End Function      Public Function StripNulls(OriginalStr As String) As String         ' This removes the extra Nulls so String comparisons will work         If (InStr(OriginalStr, Chr(0)) > 0) Then            OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)         End If         StripNulls = OriginalStr      End Function					
  5. Run the project and click on Command1. This enumerates the Form's child Windows until it finds the TextBox, then doubles the height of the TextBox and moves it to position 0, 0 (upper-left of the Form.)
  6. Click on Command2. It now lists the Class and Title (if there is one) for all top-level Windows, for their Child Windows, and any non-child Windows associated with their threads, to the Immediate Window. Note that this can be a very long list and may take a minute to complete.
  7. From the Run Menu, choose End, or click the END button to stop the program. Change the code in Sub Command1_Click according to the comments to pass the handle from GetDesktopWindow. Run the project and click on Command1 to enumerate all child Windows of the DeskTop. Note that this procedure can take some time to complete.
REFERENCES
For more information, please search on the following topics in either theWin32 Programmer's Reference or the Microsoft Developer Network (MSDN)Library CD-ROM:

  • EnumWindows
  • EnumChildWindows
  • EnumThreadWindows
  • GetDesktopWindow
  • GetClassName
  • GetWindowRect
  • GetWindowText
  • GetWindowThreadProcessId
  • MoveWindow
find locate Callback
Properties

Article ID: 183009 - Last Review: 07/01/2004 17:45:00 - Revision: 2.1

  • Microsoft Visual Basic 6.0 Learning Edition
  • Microsoft Visual Basic 6.0 Professional Edition
  • Microsoft Visual Basic 6.0 Enterprise Edition
  • 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
  • kbhowto kbapi KB183009
Feedback