Windows/Window: Add SnapToBorder

This commit is contained in:
Jonathan Jenne 2021-09-23 11:04:31 +02:00
parent 7ffff9ab0e
commit 4dbc0aabc7

View File

@ -7,6 +7,8 @@ Imports DigitalData.Modules.Logging
Public Class Window
Private _Logger As Logger
Private Const WINDOW_SNAP_OFFSET = 35
Public Enum Anchor
TopLeft
BottomLeft
@ -387,4 +389,89 @@ Public Class Window
Throw ex
End Try
End Function
<StructLayout(LayoutKind.Sequential)>
Public Structure WINDOWPOS
Public hwnd As IntPtr
Public hwndInsertAfter As IntPtr
Public x As Integer
Public y As Integer
Public cx As Integer
Public cy As Integer
Public flags As Integer
End Structure
Public Shared Sub SnapToDesktopBorder(pForm As Form, pLParam As IntPtr, Optional pWidthAdjustment As Integer = 0)
If pForm Is Nothing Then
' Satisfies rule: Validate parameters
Throw New ArgumentNullException("pForm")
End If
' Snap client to the top, left, bottom or right desktop border
' as the form is moved near that border
Try
' Marshal the LPARAM value which is a WINDOWPOS struct
Dim oNewPosition As New WINDOWPOS
oNewPosition = CType(Marshal.PtrToStructure(pLParam, GetType(WINDOWPOS)), WINDOWPOS)
If oNewPosition.y = 0 OrElse oNewPosition.x = 0 Then
Return ' Nothing to do!
End If
' Adjust the client size for borders and caption bar
Dim oClientRect As Rectangle = pForm.RectangleToScreen(pForm.ClientRectangle)
oClientRect.Width += SystemInformation.FrameBorderSize.Width - pWidthAdjustment
oClientRect.Height += (SystemInformation.FrameBorderSize.Height + SystemInformation.CaptionHeight)
' Now get the screen working area (without taskbar)
Dim oWorkingRect As Rectangle = System.Windows.Forms.Screen.GetWorkingArea(pForm.ClientRectangle)
' Left border
If oNewPosition.x >= oWorkingRect.X - WINDOW_SNAP_OFFSET AndAlso
oNewPosition.x <= oWorkingRect.X + WINDOW_SNAP_OFFSET Then
oNewPosition.x = oWorkingRect.X
End If
' Get screen bounds and taskbar height
' (when taskbar is horizontal)
Dim oScreenRect As Rectangle = System.Windows.Forms.Screen.GetBounds(System.Windows.Forms.Screen.PrimaryScreen.Bounds)
Dim oTaskbarHeight As Integer = oScreenRect.Height - oWorkingRect.Height
' Top border (check if taskbar is on top
' or bottom via WorkingRect.Y)
If oNewPosition.y >= -WINDOW_SNAP_OFFSET AndAlso
(oWorkingRect.Y > 0 AndAlso oNewPosition.y <=
(oTaskbarHeight + WINDOW_SNAP_OFFSET)) OrElse
(oWorkingRect.Y <= 0 AndAlso oNewPosition.y <=
(WINDOW_SNAP_OFFSET)) Then
If oTaskbarHeight > 0 Then
oNewPosition.y = oWorkingRect.Y ' Horizontal Taskbar
Else
oNewPosition.y = 0 ' Vertical Taskbar
End If
End If
' Right border
If oNewPosition.x + oClientRect.Width <=
oWorkingRect.Right + WINDOW_SNAP_OFFSET AndAlso
oNewPosition.x + oClientRect.Width >=
oWorkingRect.Right - WINDOW_SNAP_OFFSET Then
oNewPosition.x = oWorkingRect.Right - (oClientRect.Width +
SystemInformation.FrameBorderSize.Width)
End If
' Bottom border
If oNewPosition.y + oClientRect.Height <=
oWorkingRect.Bottom + WINDOW_SNAP_OFFSET AndAlso
oNewPosition.y + oClientRect.Height >=
oWorkingRect.Bottom - WINDOW_SNAP_OFFSET Then
oNewPosition.y = oWorkingRect.Bottom - (oClientRect.Height +
SystemInformation.FrameBorderSize.Height)
End If
' Marshal it back
Marshal.StructureToPtr(oNewPosition, pLParam, True)
Catch ex As ArgumentException
End Try
End Sub
End Class