Jonathan Jenne 16a6febb34 jj
2019-08-09 17:12:34 +02:00

235 lines
8.8 KiB
VB.net

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 = ""
''' <summary>
''' Get all top-level window information
''' </summary>
''' <returns>List of window information objects</returns>
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
''' <summary>
''' Get all child windows for the specific windows handle (hwnd).
''' </summary>
''' <returns>List of child windows for parent window</returns>
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
''' <summary>
''' Callback function that does the work of enumerating top-level windows.
''' </summary>
''' <param name="hwnd">Discovered Window handle</param>
''' <returns>1=keep going, 0=stop</returns>
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
''' <summary>
''' Callback function that does the work of enumerating child windows.
''' </summary>
''' <param name="hwnd">Discovered Window handle</param>
''' <returns>1=keep going, 0=stop</returns>
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
''' <summary>
''' Returns Information about the Window with `hWnd`
''' </summary>
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
''' <summary>
''' Returns Information about the currently focused window
''' </summary>
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
''' <summary>
'''
''' </summary>
''' <param name="WindowHandle">Current window handle; can be obtained from Me.Handle</param>
''' <returns></returns>
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
End Class