|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. |