diff --git a/Windows/Drawing.vb b/Windows/Drawing.vb new file mode 100644 index 00000000..b3f3286e --- /dev/null +++ b/Windows/Drawing.vb @@ -0,0 +1,27 @@ +Imports System.Drawing +Imports DigitalData.Modules.Logging + +Public Class Drawing + Private _Logger As Logger + + Public Sub New(LogConfig As LogConfig) + _Logger = LogConfig.GetLogger() + End Sub + + Public Sub DrawRectangle(Bounds As Rectangle) + Dim oContext As IntPtr + oContext = NativeMethods.GetDC(IntPtr.Zero) + + Try + Dim g As Graphics + g = Graphics.FromHdc(oContext) + Try + g.DrawRectangle(Pens.Red, Bounds) + Finally + g.Dispose() + End Try + Finally + NativeMethods.ReleaseDC(IntPtr.Zero, oContext) + End Try + End Sub +End Class diff --git a/Windows/NativeMethods.vb b/Windows/NativeMethods.vb index 80f17716..1a42dcd1 100644 --- a/Windows/NativeMethods.vb +++ b/Windows/NativeMethods.vb @@ -2,6 +2,15 @@ Imports System.Text Public Class NativeMethods + + Public Shared Function GetDC(ByVal hwnd As IntPtr) As IntPtr + End Function + + Public Shared Function ReleaseDC(ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As IntPtr + End Function + + Public Shared Function GetWindowRect(ByVal hWnd As HandleRef, ByRef lpRect As RectangleAPI) As Boolean + End Function Public Shared Function AttachThreadInput(ByVal idAttach As IntPtr, ByVal idAttachTo As IntPtr, fAttach As Boolean) As Boolean End Function @@ -9,6 +18,9 @@ Public Class NativeMethods Public Shared Function GetFocus() As IntPtr End Function + Public Shared Function WindowFromPoint(ByVal p As PointAPI) As IntPtr + End Function + Public Shared Function GetForegroundWindow() As IntPtr End Function @@ -63,6 +75,9 @@ Public Class NativeMethods Public Shared Function RegisterWindowMessage(ByVal lpString As String) As Integer End Function + + Public Shared Function GetCursorPos(ByRef lpPoint As PointAPI) As Boolean + End Function Public Const STANDARD_RIGHTS_REQUIRED As Integer = &HF0000 Public Const SECTION_QUERY As Short = &H1 @@ -99,4 +114,29 @@ Public Class NativeMethods NoCache = &H200 WriteCombine = &H400 End Enum + + Public Enum ChildWindowFromPointFlags As UInteger + CWP_ALL + CWP_SKIPINVISIBLE + CWP_SKIPDISABLED + CWP_SKIPTRANSPARENT + End Enum + + Public Structure RectangleAPI + Public Left As Integer + Public Top As Integer + Public Right As Integer + Public Bottom As Integer + End Structure + + + Public Structure PointAPI + Public X As Integer + Public Y As Integer + + Public Sub New(ByVal X As Integer, ByVal Y As Integer) + Me.X = X + Me.Y = Y + End Sub + End Structure End Class diff --git a/Windows/Window.vb b/Windows/Window.vb index 270c6f03..01f7158f 100644 --- a/Windows/Window.vb +++ b/Windows/Window.vb @@ -1,9 +1,30 @@ -Imports System.Text +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 = "" @@ -14,7 +35,7 @@ Public Class Window End Class Public Sub New(LogConfig As LogConfig) - _Logger = LogConfig.getLogger() + _Logger = LogConfig.GetLogger() End Sub ''' @@ -62,20 +83,6 @@ Public Class Window } End Function - Public Function FocusedControlinActiveWindow(WindowHandle As IntPtr) As IntPtr - Try - Dim oActiveWindowHandle As IntPtr = NativeMethods.GetForegroundWindow - Dim oActiveWindowThread As IntPtr = NativeMethods.GetWindowThreadProcessId(oActiveWindowHandle, 0) - Dim oThisWindowThread As IntPtr = NativeMethods.GetWindowThreadProcessId(WindowHandle, 0) - NativeMethods.AttachThreadInput(oActiveWindowThread, oThisWindowThread, True) - Dim oFocusedControlHandle As IntPtr = NativeMethods.GetFocus() - NativeMethods.AttachThreadInput(oActiveWindowThread, oThisWindowThread, False) - Return oFocusedControlHandle - Catch ex As Exception - Return Nothing - End Try - End Function - ''' ''' Returns the currently focused control ''' @@ -118,4 +125,144 @@ Public Class Window End Try End Function + + ''' + ''' Returns Bounds of `ControlHandle`. Relative to `WindowHandle` and `Anchor` value. + ''' + 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 + + Try + If NativeMethods.GetWindowRect(New HandleRef(Me, WindowHandle), oWindowRect) = False Then + Return Nothing + End If + + 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) + + oResult.Left = oRect.Left + oResult.Right = oRect.Right + oResult.Top = oRect.Top + oResult.Bottom = oRect.Bottom + + Return oResult + Catch ex As Exception + _Logger.Error(ex) + Return Nothing + End Try + End Function + + ''' + ''' Returns Bounds of the focused control. Relative to current form and `Anchor` value. + ''' + Public Function GetFocusedControlLocation(Optional Anchor As Anchor = Anchor.TopLeft) As RectangleInfo + Dim oWindowRect As New NativeMethods.RectangleAPI + Dim oControlRect As New NativeMethods.RectangleAPI + Dim oForegroundWindow As IntPtr + Dim oFocusedControl As IntPtr + Dim oResult As New RectangleInfo + + Try + oForegroundWindow = NativeMethods.GetForegroundWindow() + oFocusedControl = NativeMethods.GetFocus() + + Return GetControlLocation(oFocusedControl, oForegroundWindow, Anchor) + Catch ex As Exception + _Logger.Error(ex) + Return Nothing + End Try + End Function + + ''' + ''' Returns Bounds of the control under the cursor. Relative to current form and `Anchor` value. + ''' + 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.Error(ex) + Return Nothing + End Try + End Function + + Public Function GetWindowRect(Handle As IntPtr) + Dim oWindowRect As New NativeMethods.RectangleAPI + + If NativeMethods.GetWindowRect(New HandleRef(Me, Handle), oWindowRect) = False Then + Return Nothing + End If + + Return oWindowRect + End Function + + Private Function GetRelativeRectangle(ControlRect As NativeMethods.RectangleAPI, WindowRect As NativeMethods.RectangleAPI, Anchor As Anchor) As NativeMethods.RectangleAPI + Dim oScreenRect As Rectangle = Screen.PrimaryScreen.Bounds + Dim oLeft, oBottom, oTop, oRight As Integer + + 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 + + Return New NativeMethods.RectangleAPI() With { + .Top = oTop, + .Bottom = oBottom, + .Left = oLeft, + .Right = oRight + } + End Function + + Private Function GetRect(Rect As NativeMethods.RectangleAPI, ParentRect As NativeMethods.RectangleAPI) As Rectangle + 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) + End Function + + Private Function GetRect(Rect As NativeMethods.RectangleAPI, ParentRect As Rectangle) As Rectangle + 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) + End Function End Class diff --git a/Windows/Windows.vbproj b/Windows/Windows.vbproj index 6a07b179..1a1dd32a 100644 --- a/Windows/Windows.vbproj +++ b/Windows/Windows.vbproj @@ -50,10 +50,12 @@ + + @@ -72,6 +74,7 @@ +