Visual Basic Enumeration/Callback Routines
EnumWindows: Enumerate Windows via a Callback
     
Posted:   Wednesday June 17, 1998
Updated:   Monday December 26, 2011
     
Applies to:   VB5, VB6
Developed with:   VB6, Windows 98
OS restrictions:   None
Author:   VBnet - Randy Birch
     
 Prerequisites
VB5 / VB6.

Windows offers VB programmers the 'EnumXXX' APIs providing callback data for specific tasks.

This page demonstrates using the EnumWindows() API to enumerate all windows on the system, and populate a listbox with their class name, hwnd and window text if available.

I didn't get fancy in using the lParam member of the callback ... the MSDN identifies it as "an application-defined value given in EnumWindows or EnumDesktopWindows".  In the Font callback example, we used this to pass the listbox to the callback for populating ... here we'll just refer to the listbox directly.

 

 BAS Module Code
Place the following code into the general declarations area of a bas module:

Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Const MAX_PATH As Long = 260
Public Const LB_SETTABSTOPS As Long = &H192

Public Declare Function EnumWindows Lib "user32" _
   (ByVal lpEnumFunc As Long, _
    ByVal lParam As Long) As Long

Public Declare Function GetClassName Lib "user32" _
    Alias "GetClassNameA" _
   (ByVal hWnd As Long, _
    ByVal lpClassName As String, _
    ByVal nMaxCount As Long) As Long

Public Declare Function GetWindowText Lib "user32" _
    Alias "GetWindowTextA" _
   (ByVal hWnd As Long, _
    ByVal lpString As String, _
    ByVal cch As Long) As Long

Public Declare Function GetWindowTextLength Lib "user32" _
    Alias "GetWindowTextLengthA" (ByVal hWnd As Long) As Long

Public Declare Function SendMessage Lib "user32" _
    Alias "SendMessageA" _
    (ByVal hWnd As Long, _
    ByVal wMsg As Long, _
    ByVal wParam As Long, _
    lParam As Any) As Long


Public Function EnumWindowProc(ByVal hWnd As Long, _
                               ByVal lParam As Long) As Long
   
  'working vars
   Dim nSize As Long
   Dim sTitle As String
   Dim sClass As String
   Dim pos As Integer
   
  'set up the strings to receive the class and
  'window text. You could use GetWindowTextLength,
  'but I'll cheat and use MAX_PATH instead.
   sTitle = Space$(MAX_PATH)
   sClass = Space$(MAX_PATH)
   
   Call GetClassName(hWnd, sClass, MAX_PATH)
   Call GetWindowText(hWnd, sTitle, MAX_PATH)

  'strip the trailing chr$(0)'s from the strings
  'returned above and add the window data to the list
   Form1.List1.AddItem TrimNull(sClass) & vbTab & _
                       hWnd & vbTab & TrimNull(sTitle)
                       
  'to continue enumeration, we must return True
  '(in C that's 1).  If we wanted to stop (perhaps
  'using if this as a specialized FindWindow method,
  'comparing a known class and title against the
  'returned values, and a match was found, we'd need
  'to return False (0) to stop enumeration. When 1 is
  'returned, enumeration continues until there are no
  'more windows left.
   EnumWindowProc = 1

End Function


Private Function TrimNull(item As String)

  'remove string before the terminating null(s)
   Dim pos As Integer
   
   pos = InStr(item, Chr$(0))
   
   If pos Then
      TrimNull = Left$(item, pos - 1)
   Else
      TrimNull = item
   End If
   
End Function
 Form Code
To a form, add two command buttons, a label, and a listbox. Add the following code to the form:

Option Explicit

Private Sub Form_Load()

   ReDim TabArray(0 To 2) As Long
   
   TabArray(0) = 0
   TabArray(1) = -142
   TabArray(2) = 154
   
  'clear any existing tabs
   Call SendMessage(List1.hWnd, LB_SETTABSTOPS, 0&, ByVal 0&)
   
  'set list tabstops
   Call SendMessage(List1.hWnd, LB_SETTABSTOPS, 3&, TabArray(0))
   
End Sub


Private Sub Command2_Click()

   Unload Me

End Sub


Private Sub Command1_Click()

   List1.Clear

  'enumerate the windows passing the AddressOf the
  'callback function.  This example doesn't use the 
  'lParam member.
   Call EnumWindows(AddressOf EnumWindowProc, &H0)

  'show the window count
   Label1.Caption = List1.ListCount & " windows found."

End Sub
 Comments
Not much to say.  Clicking the Enum button will fill the list with the windows on the system. Further APIs and logic could be added to the Enum proc sub to restrict the listing to specialized or specific windows.

To obtain my tabstop-designing utility, checkout the CoolTabs page.


 
 

PayPal Link
Make payments with PayPal - it's fast, free and secure!

 
 
 
 

Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy

 

Hit Counter