| 
       
  | 
   
      ![]()  | 
      
       | 
   ||
| 
       | 
      |||
         
  | 
   ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 
       
 | 
   ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 
          
  | 
      ||
| Visual Basic System Services GetGuiThreadInfo: Active Application GUI Information  | 
   ||
| Posted: | Sunday January 05, 2003 | |
| Updated: | Monday December 26, 2011 | |
| Applies to: | VB4-32, VB5, VB6 | |
| Developed with: | VB6, Windows XP | |
| OS restrictions: | None | |
| Author: | VBnet - Randy Birch | |
| 
          Related:  | 
      EnumWindows: Enumerate Windows via a Callback EnumChildWindows: Enumeration of Parent and Child Windows via Callbacks GetWindow: Find Applications of a Specific Class or Window Title  | 
   |
| Prerequisites | 
| None. | 
| 
          | 
   
        The 
       GetGUIThreadInfo function retrieves information about the active window, 
       or a specified graphical user interface (GUI) thread. The call's idThread 
       parameter identifies the thread for which information is to be retrieved, 
       a value that can be obtained by calling GetWindowThreadProcessId. When 
       idThread is null the function returns information for the foreground 
       thread. This makes it handy to monitor ongoing GUI information for the 
       currently active application as shown in this demo.
         The data for the GUI is returned through the lpgui member of the call, which identifies a GUITHREADINFO structure, and in addition to the requisite cbSize member contains: 
 The flags member returns a bit mask providing the active window status information, such as: 
 The demo is fairly straightforward. A timer fires at the interval selected calling GetActiveWindowGuiInfo(), the main application method. GetActiveWindowGuiInfo in turn calls GetGuiThreadInfo and loads a listbox with the GUI information pertaining to the active window's thread. Helper routines GetActiveWindowTitle() and GetCaretWindowText() returns the titlebar caption for the active window, and the text in edit or rich text controls supporting the WM_GETTEXT message, respectively. A counter variable is also used (shown as the first line in the list block (175 in the illustration above) as a visual aid in determining each call is successful and the data being viewed is current.  | 
   
| BAS Module Code | 
| None. | 
| 
          | 
   
| Form Code | 
| 
       
 | 
   
| To a form add a timer control (Timer1), a list box (List1), a combo (Combo1), and two command buttons (Command1/Command2), along with the following code: | 
| 
          | 
   
         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. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Const GUI_CARETBLINKING  As Long = &H1
Private Const GUI_INMOVESIZE     As Long = &H2
Private Const GUI_INMENUMODE     As Long = &H4
Private Const GUI_SYSTEMMENUMODE As Long = &H8
Private Const GUI_POPUPMENUMODE  As Long = &H10
Private Const GUI_16BITTASK      As Long = &H20 'winver >= 5.01
Private Const LB_SETTABSTOPS As Long = &H192
Private Const WM_GETTEXT As Long = &HD
Private Const WM_GETTEXTLENGTH As Long = &HE
Private Type RECT
   Left As Long
   Top As Long
   Right As Long
   Bottom As Long
End Type
Private Type GUITHREADINFO
   cbSize As Long
   flags As Long
   hwndactive As Long
   hwndFocus As Long
   hwndCapture As Long
   hwndMenuOwner As Long
   hwndMoveSize As Long
   hwndcaret As Long
   rcCaret As RECT
End Type
Private Declare Function GetGuiThreadInfo Lib "user32" _
  Alias "GetGUIThreadInfo" (ByVal idThread As _
   Long, lpgui As GUITHREADINFO) As Long
Private Declare Function SendMessage Lib "user32" _
   Alias "SendMessageA" _
  (ByVal hwnd As Long, _
   ByVal wMsg As Long, _
   ByVal wParam As Long, _
   lParam As Any) As Long
Private Declare Function GetWindowTextLength Lib "user32" _
   Alias "GetWindowTextLengthA" _
  (ByVal hwnd As Long) As Long
  
Private Declare Function GetWindowText Lib "user32" _
   Alias "GetWindowTextA" _
  (ByVal hwnd As Long, _
   ByVal lpString As String, _
   ByVal cch As Long) As Long
Private Sub Form_Load()
  'set up list tabstops 
   ReDim TabArray(0 To 0) As Long
   
   TabArray(0) = 107
   Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 0&, ByVal 0&)
   Call SendMessage(List1.hwnd, LB_SETTABSTOPS, 1&, TabArray(0))
   
  'set up timer intervals 
   With Combo1
      .AddItem "100 milliseconds"
      .ItemData(.NewIndex) = 100
      .AddItem "1/2 second"
      .ItemData(.NewIndex) = 500
      .AddItem "1 second"
      .ItemData(.NewIndex) = 1000
      .AddItem "2 seconds"
      .ItemData(.NewIndex) = 2000
      .AddItem "3 seconds"
      .ItemData(.NewIndex) = 3000
      .AddItem "5 seconds"
      .ItemData(.NewIndex) = 5000
      .ListIndex = 2  '1 second
   End With
   Command1.Caption = "Start"
   Command2.Caption = "Done"
   
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
   Timer1.Enabled = False
   
End Sub
Private Sub Combo1_Click()
  'if timer running, this will
  'change its update frequency
   Timer1.Interval = Combo1.ItemData(Combo1.ListIndex)
End Sub
Private Sub Command1_Click()
   Timer1.Interval = Combo1.ItemData(Combo1.ListIndex)
   Timer1.Enabled = True
   
End Sub
Private Sub Command2_Click()
   Unload Me
   
End Sub
Private Sub Timer1_Timer()
  'nuke the list if 250 or more entries
   If List1.ListCount > 250 Then List1.Clear
   
  'update with info from the active window
   Call GetActiveWindowGuiInfo
   
End Sub
Private Sub GetActiveWindowGuiInfo()
   Dim gui As GUITHREADINFO
   Static numcalls As Long
   
  'idThread identifies the thread for which
  'information is to be retrieved. Where the
  'purpose is to monitor a specific form or
  'application, GetWindowThreadProcessId()
  'provides the thread ID required.
  '
  'Conveniently for this demo, when idThread
  'is null, GetGUIThreadInfo returns information
  'for the foreground thread, thus allowing
  'us to move between applications and view
  'the activities therein.
  
  'cbSize must be set before calling
   gui.cbSize = Len(gui)
   If GetGuiThreadInfo(0&, gui) <> 0 Then
   
     'numcalls is just a counter to increment
     'a line in the list to show the code is
     'working when you rest in one window
      numcalls = numcalls + 1
   
      With List1
      
         .AddItem CStr(numcalls)
         
         .AddItem "active window hwnd:" & vbTab & gui.hwndactive
         .AddItem "   active window title:" & vbTab & GetActiveWindowTitle(gui.hwndactive)
         .AddItem "mouse capture hwnd:" & vbTab & gui.hwndCapture
         .AddItem "showing caret hwnd:" & vbTab & gui.hwndcaret
         .AddItem "    caret window text:" & vbTab & GetCaretWindowText(gui.hwndcaret)
         .AddItem "keyboard focus hwnd:" & vbTab & gui.hwndFocus
         .AddItem "active menu owner hwnd:" & vbTab & gui.hwndMenuOwner
         .AddItem "move or size loop hwnd:" & vbTab & gui.hwndMoveSize
   
         .AddItem "caret rect (l/r t/b):" & vbTab & _
                   gui.rcCaret.Left & "/" & _
                   gui.rcCaret.Right & " " & _
                   gui.rcCaret.Top & "/" & _
                   gui.rcCaret.Bottom
   
        'AND the flags to return the
        'possible GUI states
         .AddItem "returned flags:" & vbTab & gui.flags
         
         If gui.flags And GUI_CARETBLINKING Then .AddItem "caret is visible"
         If gui.flags And GUI_INMOVESIZE Then .AddItem "thread is in a move or size loop"
         If gui.flags And GUI_INMENUMODE Then .AddItem "thread is in menu mode"
         If gui.flags And GUI_SYSTEMMENUMODE Then .AddItem "thread is in system menu mode"
         If gui.flags And GUI_POPUPMENUMODE Then .AddItem "thread has active popup menu"
         If gui.flags And GUI_16BITTASK Then .AddItem "thread's app is 16-bits"
         
         'add a blank line and ensure the
         'last-added entry is in view
         .AddItem ""
         .TopIndex = .NewIndex
         
   End With  'with list1
   Else
   
      With List1
         .AddItem "Error " & Err.LastDllError
         .AddItem "Error " & Err.Description
         .AddItem ""
         .TopIndex = .NewIndex
      End With  'with list1
      
   End If
   
End Sub
Private Function GetActiveWindowTitle(ByVal hwndactive As Long) As String
   Dim nLength As Long
   Dim res As Long
   Dim buff As String
   
  'GetWindowText returns the title
  'of the window specified as hwndactive
   If hwndactive <> 0 Then
   
      nLength = GetWindowTextLength(hwndactive)
      
      If nLength <> 0 Then
         
         buff = Space$(nLength + 1)
         
         res = GetWindowText(hwndactive, buff, nLength + 1)
         
         If res <> 0 Then
            GetActiveWindowTitle = Left$(buff, res)
            Exit Function
         End If  'if res
         
      End If  'if nlength
   
   End If  'if hwndactive
   
   GetActiveWindowTitle = "(not available)"
   
End Function
Private Function GetCaretWindowText(ByVal hwndcaret As Long) As String
   Dim nLength As Long
   Dim res As Long
   Dim buff As String
   
  'WM_GETTEXT retrieves the text
  'from edit and rich text controls
   If hwndcaret <> 0 Then
   
      nLength = SendMessage(hwndcaret, WM_GETTEXTLENGTH, 0&, ByVal 0&)
      
      If nLength <> 0 Then
         
         buff = Space$(nLength + 1)
         
         res = SendMessage(hwndcaret, WM_GETTEXT, nLength + 1, ByVal buff)
         
         If res <> 0 Then
            GetCaretWindowText = Left$(buff, res)
            Exit Function
         End If  'if res
         
      End If  'if nlength
   
   End If  'if hwndcaret
   
   GetCaretWindowText = "(not available)"
   
End Function
       | 
   
| Comments | 
| 
          | 
   
  | 
      
| 
          | 
         |||||
  				
                     			
  | 
         |||||
| 
          | 
         |||||
| 
             
            	
            	Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved.  | 
         
          ![]()  |