391 lines
14 KiB
VB.net
391 lines
14 KiB
VB.net
Imports System.Drawing
|
|
Imports System.Runtime.InteropServices
|
|
Imports System.Text
|
|
Imports System.Windows.Forms
|
|
Imports DigitalData.Modules.Logging
|
|
|
|
Public Class Window
|
|
Private _Logger As Logger
|
|
|
|
Public Enum Anchor
|
|
TopLeft
|
|
BottomLeft
|
|
TopRight
|
|
BottomRight
|
|
End Enum
|
|
|
|
Public Class RectangleInfo
|
|
Public Top As Integer = 0
|
|
Public Left As Integer = 0
|
|
Public Right As Integer = 0
|
|
Public Bottom As Integer = 0
|
|
|
|
Public Overrides Function ToString() As String
|
|
Return String.Format("Top:{0},Left:{1},Bottom:{2},Right:{3}", Top, Left, Bottom, Right)
|
|
End Function
|
|
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 = IntPtr.Zero
|
|
End Class
|
|
|
|
Public Sub New(LogConfig As LogConfig)
|
|
_Logger = LogConfig.GetLogger()
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Returns Information about the currently focused window
|
|
''' </summary>
|
|
Public Function GetWindowInfo() As WindowInfo
|
|
Try
|
|
Dim hWnd As IntPtr = NativeMethods.GetForegroundWindow()
|
|
Return GetWindowInfo(hWnd)
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetWindowInfo/0")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns Information about the Window with `hWnd`
|
|
''' </summary>
|
|
Public Function GetWindowInfo(ByVal hWnd As IntPtr) As WindowInfo
|
|
Try
|
|
Dim oPID As Integer = 0
|
|
Dim oTitleLength As Int32 = NativeMethods.GetWindowTextLength(hWnd)
|
|
Dim oWindowTitle As String = StrDup(oTitleLength + 1, "*")
|
|
Dim oClassBuilder As New StringBuilder(64)
|
|
|
|
NativeMethods.GetWindowText(hWnd, oWindowTitle, oTitleLength + 1)
|
|
NativeMethods.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
|
|
|
|
NativeMethods.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)
|
|
}
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetWindowInfo/1")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns the currently focused control
|
|
''' </summary>
|
|
''' <param name="WindowHandle">Current window handle; can be obtained from Me.Handle</param>
|
|
Public Function GetFocusedControl(WindowHandle As IntPtr) As WindowInfo
|
|
Try
|
|
Dim oWindow = GetWindowInfo()
|
|
|
|
If oWindow Is Nothing Then
|
|
_Logger.Debug("Could not get Window Info!")
|
|
Return Nothing
|
|
End If
|
|
|
|
Dim oThreadId As IntPtr = NativeMethods.GetWindowThreadProcessId(oWindow.hWnd, 0)
|
|
Dim oMyThreadId As IntPtr = NativeMethods.GetWindowThreadProcessId(WindowHandle, 0)
|
|
|
|
If NativeMethods.AttachThreadInput(oThreadId, oMyThreadId, True) Then
|
|
Try
|
|
Dim oControlhWnd = NativeMethods.GetFocus()
|
|
Dim oControl As WindowInfo = GetWindowInfo(oControlhWnd)
|
|
|
|
If oControl Is Nothing Then
|
|
_Logger.Debug("Could not get Control Info!")
|
|
Return Nothing
|
|
End If
|
|
|
|
Dim oName = Utils.GetWinFormsId(oControlhWnd)
|
|
oControl.ControlName = oName
|
|
|
|
|
|
Return oControl
|
|
Catch ex As Exception
|
|
_Logger.Error(ex)
|
|
Finally
|
|
NativeMethods.AttachThreadInput(oThreadId, oMyThreadId, False)
|
|
End Try
|
|
End If
|
|
|
|
Return Nothing
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetFocusedControl/1")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns Bounds of `ControlHandle`. Relative to `WindowHandle` and `Anchor` value.
|
|
''' </summary>
|
|
Public Function GetControlLocation(ControlHandle As IntPtr, WindowHandle As IntPtr, Optional Anchor As Anchor = Anchor.TopLeft) As RectangleInfo
|
|
Dim oWindowRect As New NativeMethods.RectangleAPI
|
|
Dim oControlRect As New NativeMethods.RectangleAPI
|
|
Dim oResult As New RectangleInfo
|
|
|
|
_Logger.Debug("Getting Control Location")
|
|
|
|
Try
|
|
_Logger.Debug("Trying to get Window Rectangle")
|
|
If NativeMethods.GetWindowRect(New HandleRef(Me, WindowHandle), oWindowRect) = False Then
|
|
Return Nothing
|
|
End If
|
|
|
|
_Logger.Debug("Trying to get Control Rectangle")
|
|
If NativeMethods.GetWindowRect(New HandleRef(Me, ControlHandle), oControlRect) = False Then
|
|
Return Nothing
|
|
End If
|
|
|
|
Dim oRect As New NativeMethods.RectangleAPI
|
|
|
|
' Calculate Coordinates relative to parent window
|
|
oRect = GetRelativeRectangle(oControlRect, oWindowRect, Anchor)
|
|
|
|
_Logger.Debug("Control Location for Anchor {0}: {1}", Anchor, oRect)
|
|
|
|
oResult.Left = oRect.Left
|
|
oResult.Right = oRect.Right
|
|
oResult.Top = oRect.Top
|
|
oResult.Bottom = oRect.Bottom
|
|
|
|
Return oResult
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetControlLocation/3")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
Public Function GetControlLocations(ControlHandle As IntPtr, WindowHandle As IntPtr) As Dictionary(Of String, RectangleInfo)
|
|
Dim oWindowRect As New NativeMethods.RectangleAPI
|
|
Dim oControlRect As New NativeMethods.RectangleAPI
|
|
Dim oResults As New Dictionary(Of String, RectangleInfo)
|
|
|
|
_Logger.Debug("Getting Control Locations")
|
|
|
|
Try
|
|
_Logger.Debug("Trying to get Window Rectangle")
|
|
If NativeMethods.GetWindowRect(New HandleRef(Me, WindowHandle), oWindowRect) = False Then
|
|
Return Nothing
|
|
End If
|
|
|
|
_Logger.Debug("Trying to get Control Rectangle")
|
|
If NativeMethods.GetWindowRect(New HandleRef(Me, ControlHandle), oControlRect) = False Then
|
|
Return Nothing
|
|
End If
|
|
|
|
|
|
For Each oAnchor As Anchor In [Enum].GetValues(GetType(Anchor))
|
|
Dim oRect As NativeMethods.RectangleAPI = GetRelativeRectangle(oControlRect, oWindowRect, oAnchor)
|
|
|
|
_Logger.Debug("Control Location for Anchor {0}: {1}", oAnchor, oRect)
|
|
|
|
oResults.Add(oAnchor.ToString, New RectangleInfo() With {
|
|
.Left = oRect.Left,
|
|
.Right = oRect.Right,
|
|
.Top = oRect.Top,
|
|
.Bottom = oRect.Bottom
|
|
})
|
|
Next
|
|
|
|
Return oResults
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetControlLocations/2")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns Bounds of the focused control. Relative to current form and `Anchor` value.
|
|
''' </summary>
|
|
Public Function GetFocusedControlLocation(WindowHandle As IntPtr, Anchor As Anchor) As RectangleInfo
|
|
Dim oForegroundWindow As WindowInfo
|
|
Dim oFocusedControl As WindowInfo
|
|
|
|
Try
|
|
oForegroundWindow = GetWindowInfo()
|
|
oFocusedControl = GetFocusedControl(WindowHandle)
|
|
|
|
If IsNothing(oForegroundWindow) Then
|
|
_Logger.Debug("Foreground Window is nothing!")
|
|
End If
|
|
|
|
If IsNothing(oFocusedControl) Then
|
|
_Logger.Debug("Focused Contol is nothing!")
|
|
End If
|
|
|
|
_Logger.Debug("Control Handle: {0}", oFocusedControl.hWnd)
|
|
_Logger.Debug("Window Handle: {0}", oForegroundWindow.hWnd)
|
|
|
|
Return GetControlLocation(oFocusedControl.hWnd, oForegroundWindow.hWnd, Anchor)
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetFocusedControlLocation/2")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
Public Function GetFocusedControlLocation(WindowHandle As IntPtr) As Dictionary(Of String, RectangleInfo)
|
|
Dim oForegroundWindow As WindowInfo
|
|
Dim oFocusedControl As WindowInfo
|
|
|
|
Try
|
|
oForegroundWindow = GetWindowInfo()
|
|
oFocusedControl = GetFocusedControl(WindowHandle)
|
|
|
|
If oForegroundWindow Is Nothing Then
|
|
_Logger.Warn("Foreground Window is Nothing!")
|
|
End If
|
|
|
|
If oFocusedControl Is Nothing Then
|
|
_Logger.Warn("Focused Control is Nothing!")
|
|
End If
|
|
|
|
Dim oDict As Dictionary(Of String, RectangleInfo) = GetControlLocations(oFocusedControl.hWnd, oForegroundWindow.hWnd)
|
|
|
|
Return oDict
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetFocusedControlLocation/1")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns Bounds of the control under the cursor. Relative to current form and `Anchor` value.
|
|
''' </summary>
|
|
Public Function GetHoveredControlLocation(Optional Anchor As Anchor = Anchor.TopLeft) As RectangleInfo
|
|
Dim oPoint As New NativeMethods.PointAPI
|
|
Dim oWindowRect As New NativeMethods.RectangleAPI
|
|
Dim oControlRect As New NativeMethods.RectangleAPI
|
|
Dim oForegroundWindow As IntPtr
|
|
Dim oControlUnderCursor As IntPtr
|
|
Dim oResult As New RectangleInfo
|
|
|
|
Try
|
|
If NativeMethods.GetCursorPos(oPoint) = False Then
|
|
Return Nothing
|
|
End If
|
|
|
|
oForegroundWindow = NativeMethods.GetForegroundWindow()
|
|
oControlUnderCursor = NativeMethods.WindowFromPoint(oPoint)
|
|
|
|
Return GetControlLocation(oControlUnderCursor, oForegroundWindow, Anchor)
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetHoveredControlLocation/1")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
Public Function GetWindowRect(Handle As IntPtr)
|
|
Try
|
|
Dim oWindowRect As New NativeMethods.RectangleAPI
|
|
|
|
If NativeMethods.GetWindowRect(New HandleRef(Me, Handle), oWindowRect) = False Then
|
|
Return Nothing
|
|
End If
|
|
|
|
Return oWindowRect
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetWindowRect/1")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
Private Function GetRelativeRectangle(ControlRect As NativeMethods.RectangleAPI, WindowRect As NativeMethods.RectangleAPI, Anchor As Anchor) As NativeMethods.RectangleAPI
|
|
Try
|
|
Dim oScreenRect As Rectangle = Screen.PrimaryScreen.Bounds
|
|
Dim oLeft, oBottom, oTop, oRight As Integer
|
|
|
|
_Logger.Debug("Calculating Rectangle for Anchor {0}", Anchor.ToString)
|
|
|
|
Select Case Anchor
|
|
Case Anchor.TopLeft
|
|
oLeft = ControlRect.Left - WindowRect.Left
|
|
oTop = ControlRect.Top - WindowRect.Top
|
|
Case Anchor.BottomLeft
|
|
oLeft = ControlRect.Left - WindowRect.Left
|
|
oBottom = ControlRect.Bottom - WindowRect.Bottom
|
|
Case Anchor.TopRight
|
|
oRight = ControlRect.Right - WindowRect.Right
|
|
oTop = ControlRect.Top - WindowRect.Top
|
|
Case Anchor.BottomRight
|
|
oRight = ControlRect.Right - WindowRect.Right
|
|
oBottom = ControlRect.Bottom - WindowRect.Bottom
|
|
End Select
|
|
|
|
_Logger.Debug("Done Calculating Rectangle for Anchor {0}", Anchor.ToString)
|
|
|
|
Return New NativeMethods.RectangleAPI() With {
|
|
.Top = oTop,
|
|
.Bottom = oBottom,
|
|
.Left = oLeft,
|
|
.Right = oRight
|
|
}
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetRelativeRectangle/3")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
Private Function GetRect(Rect As NativeMethods.RectangleAPI, ParentRect As NativeMethods.RectangleAPI) As Rectangle
|
|
Try
|
|
Dim oX, oY, oWidth, oHeight As Integer
|
|
|
|
oWidth = Rect.Right - Rect.Left
|
|
oHeight = Rect.Bottom - Rect.Top
|
|
oX = Rect.Left - ParentRect.Left
|
|
oY = Rect.Top - ParentRect.Top
|
|
|
|
Return New Rectangle(oX, oY, oWidth, oHeight)
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetRect/2")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
|
|
Private Function GetRect(Rect As NativeMethods.RectangleAPI, ParentRect As Rectangle) As Rectangle
|
|
Try
|
|
Dim oX, oY, oWidth, oHeight As Integer
|
|
|
|
oWidth = Rect.Right - Rect.Left
|
|
oHeight = Rect.Bottom - Rect.Top
|
|
oX = Rect.Left - ParentRect.X
|
|
oY = Rect.Top - ParentRect.Y
|
|
|
|
Return New Rectangle(oX, oY, oWidth, oHeight)
|
|
Catch ex As Exception
|
|
_Logger.Debug("Error in GetRect/2")
|
|
_Logger.Error(ex)
|
|
Throw ex
|
|
End Try
|
|
End Function
|
|
End Class
|