Imports System.Text Public Class ClassWindowAPI Const WM_GETTEXT As Int32 = &HD Const WM_GETTEXTLENGTH As Int32 = &HE Public Class ApiWindow Public MainWindowTitle As String = "" Public ClassName As String = "" Public hWnd As Int32 End Class Public Class WindowInfo Public WindowTitle As String = "" Public ProcessName As String = "" Public ClassName As String = "" Public ProcessId As Integer = 0 Public ControlName As String = "" Public hWnd As IntPtr End Class Private Delegate Function EnumCallBackDelegate(ByVal hwnd As Integer, ByVal lParam As Integer) As Integer Private Declare Function GetCurrentThreadId Lib "kernel32.dll" Alias "GetCurrentThreadId" () As IntPtr Private Declare Function AttachThreadInput Lib "user32.dll" Alias "AttachThreadInput" (ByVal idAttach As IntPtr, ByVal idAttachTo As IntPtr, fAttach As Boolean) As Boolean Private Declare Function GetFocus Lib "user32.dll" Alias "GetFocus" () As IntPtr Private Declare Function GetForegroundWindow Lib "user32.dll" Alias "GetForegroundWindow" () As IntPtr Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpdwProcessID As Integer) As Integer Private Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hWnd As IntPtr, ByVal WinTitle As String, ByVal MaxLength As Integer) As Integer Private Declare Function GetWindowTextLength Lib "user32.dll" Alias "GetWindowTextLengthA" (ByVal hwnd As Int32) As Integer ' Top-level windows. Private Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As Integer ' Child windows. Private Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Integer, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As Integer ' Get the window class. Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Integer, ByVal lpClassName As StringBuilder, ByVal nMaxCount As Integer) As Integer ' Test if the window is visible--only get visible ones. Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Integer) As Integer ' Test if the window's parent--only get the one's without parents. Private Declare Function GetParent Lib "user32" (ByVal hwnd As Integer) As Integer ' Get window text length signature. Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As Int32) As Int32 ' Get window text signature. Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As StringBuilder) As Int32 Private _listChildren As New List(Of WindowInfo) Private _listTopLevel As New List(Of WindowInfo) Private _topLevelClass As String = "" Private _childClass As String = "" ''' ''' Get all top-level window information ''' ''' List of window information objects Public Overloads Function GetTopLevelWindows() As List(Of WindowInfo) EnumWindows(AddressOf EnumWindowProc, &H0) Return _listTopLevel End Function Public Overloads Function GetTopLevelWindows(ByVal className As String) As List(Of WindowInfo) _topLevelClass = className Return GetTopLevelWindows() End Function ''' ''' Get all child windows for the specific windows handle (hwnd). ''' ''' List of child windows for parent window Public Overloads Function GetChildWindows(ByVal hwnd As Int32) As List(Of WindowInfo) ' Clear the window list. _listChildren = New List(Of WindowInfo) ' Start the enumeration process. EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, &H0) ' Return the children list when the process is completed. Return _listChildren End Function Public Overloads Function GetChildWindows(ByVal hwnd As Int32, ByVal childClass As String) As List(Of WindowInfo) ' Set the search _childClass = childClass Return GetChildWindows(hwnd) End Function ''' ''' Callback function that does the work of enumerating top-level windows. ''' ''' Discovered Window handle ''' 1=keep going, 0=stop Private Function EnumWindowProc(ByVal hwnd As Int32, ByVal lParam As Int32) As Int32 ' Eliminate windows that are not top-level. If GetParent(hwnd) = 0 AndAlso CBool(IsWindowVisible(hwnd)) Then ' Get the window title / class name. Dim oWindow As WindowInfo = GetWindowInfo(hwnd) ' Match the class name if searching for a specific window class. If _topLevelClass.Length = 0 OrElse oWindow.ClassName.ToLower() = _topLevelClass.ToLower() Then _listTopLevel.Add(oWindow) End If End If ' To continue enumeration, return True (1), and to stop enumeration ' return False (0). ' When 1 is returned, enumeration continues until there are no ' more windows left. Return 1 End Function ''' ''' Callback function that does the work of enumerating child windows. ''' ''' Discovered Window handle ''' 1=keep going, 0=stop Private Function EnumChildWindowProc(ByVal hwnd As Int32, ByVal lParam As Int32) As Int32 Dim oWindow As WindowInfo = GetWindowInfo(hwnd) ' Attempt to match the child class, if one was specified, otherwise ' enumerate all the child windows. If _childClass.Length = 0 OrElse oWindow.ClassName.ToLower() = _childClass.ToLower() Then _listChildren.Add(oWindow) End If Return 1 End Function ''' ''' Returns Information about the Window with `hWnd` ''' Public Shared Function GetWindowInfo(ByVal hWnd As Integer) As WindowInfo Dim oPID As Integer = 0 Dim oTitleLength As Int32 = GetWindowTextLength(hWnd) Dim oWindowTitle As String = StrDup(oTitleLength + 1, "*") Dim oClassBuilder As New StringBuilder(64) GetWindowText(hWnd, oWindowTitle, oTitleLength + 1) GetWindowThreadProcessId(hWnd, oPID) If oPID = 0 Then Return Nothing End If Dim oProcess As Process = Process.GetProcessById(oPID) If oProcess Is Nothing Then Return Nothing End If GetClassName(hWnd, oClassBuilder, 64) Return New WindowInfo With { .hWnd = hWnd, .ClassName = oClassBuilder.ToString, .ProcessId = oProcess.Id, .ProcessName = oProcess.ProcessName, .WindowTitle = oWindowTitle.Replace(vbNullChar, String.Empty) } End Function ''' ''' Returns Information about the currently focused window ''' Public Shared Function GetWindowInfo() As WindowInfo Dim hWnd As IntPtr = GetForegroundWindow() If hWnd = IntPtr.Zero Then Return Nothing End If Return GetWindowInfo(hWnd) End Function ''' ''' ''' ''' Current window handle; can be obtained from Me.Handle ''' Public Shared Function GetFocusedControl(WindowHandle As IntPtr) As WindowInfo Try Dim oWindow = GetWindowInfo() If oWindow Is Nothing Then Return Nothing End If Dim oThreadId As IntPtr = GetWindowThreadProcessId(oWindow.hWnd, IntPtr.Zero) Dim oMyThreadId As IntPtr = GetWindowThreadProcessId(WindowHandle, IntPtr.Zero) If AttachThreadInput(oThreadId, oMyThreadId, True) Then Try Dim oControlhWnd = GetFocus() Dim oControl As WindowInfo = GetWindowInfo(oControlhWnd) If oControl Is Nothing Then Return Nothing End If Dim oUtils As New ClassWindowAPIUtils() Dim oName = oUtils.GetWinFormsId(oControlhWnd) oControl.ControlName = oName Return oControl Catch ex As Exception Logger.Error(ex) Finally AttachThreadInput(oThreadId, oMyThreadId, False) End Try End If Return Nothing Catch ex As Exception Logger.Error(ex) Return Nothing End Try End Function Public Shared Function FocusedControlinActiveWindow(WindowHandle As IntPtr) As IntPtr Try Dim activewindowhandle As IntPtr = GetForegroundWindow Dim activewindowThread As IntPtr = GetWindowThreadProcessId(activewindowhandle, IntPtr.Zero) Dim thiswindowthread As IntPtr = GetWindowThreadProcessId(WindowHandle, IntPtr.Zero) AttachThreadInput(activewindowThread, thiswindowthread, True) Dim focusedControlHandle As IntPtr = GetFocus() AttachThreadInput(activewindowThread, thiswindowthread, False) Return focusedControlHandle Catch ex As Exception Return Nothing End Try End Function End Class