Modules/Base/ScreenEx.vb
2025-10-01 15:17:45 +02:00

165 lines
5.3 KiB
VB.net

Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports Digitaldata.Modules.Base.NativeMethods
Imports System.Windows.Forms
Public Class ScreenEx
Public Const DEFAULT_WINDOW_HEIGHT = 480
Public Const DEFAULT_WINDOW_WIDTH = 640
Friend Const MONITORINFOF_PRIMARY As Integer = &H1
Friend Const MONITOR_DEFAULTTONEAREST As Integer = &H2
Friend Const MONITOR_DEFAULTTONULL As Integer = &H0
Friend Const MONITOR_DEFAULTTOPRIMARY As Integer = &H1
Friend Enum Monitor_DPI_Type As Integer
MDT_Effective_DPI = 0
MDT_Angular_DPI = 1
MDT_Raw_DPI = 2
MDT_Default = MDT_Effective_DPI
End Enum
Private Enum DeviceCap
VERTRES = 10
DESKTOPVERTRES = 117
End Enum
Public Shared Function GetLocationWithinScreen(pLocation As Point) As Point?
For Each screen As Screen In Screen.AllScreens
If screen.Bounds.Contains(pLocation) Then
Return New Point(pLocation.X - screen.Bounds.Left, pLocation.Y - screen.Bounds.Top)
End If
Next
Return Nothing
End Function
Public Shared Sub RestoreFormPosition(pForm As Form, pPosition As Point)
Dim oLocationWithinScreen As Point? = GetLocationWithinScreen(pPosition)
If oLocationWithinScreen Is Nothing Then
Dim oPrimaryScreen = Screen.PrimaryScreen
pForm.StartPosition = FormStartPosition.CenterScreen
Else
pForm.StartPosition = FormStartPosition.Manual
pForm.Location = pPosition
End If
End Sub
Public Shared Sub RestoreFormState(pForm As Form, pFormState As FormWindowState)
If pFormState = FormWindowState.Maximized Then
pForm.WindowState = FormWindowState.Normal
pForm.WindowState = FormWindowState.Maximized
ElseIf pFormState = FormWindowState.Minimized Then
pForm.WindowState = FormWindowState.Normal
pForm.WindowState = FormWindowState.Minimized
Else
pForm.WindowState = FormWindowState.Normal
End If
End Sub
Public Shared Sub RestoreFormState(pForm As Form, pFormState As String)
Dim oFormState As FormWindowState
If Not [Enum].TryParse(pFormState, oFormState) Then
oFormState = FormWindowState.Normal
End If
RestoreFormState(pForm, oFormState)
End Sub
Public Shared Sub RestoreFormSize(pForm As Form, pFormSize As Size)
Dim oFormSize As Size
If pFormSize.Height < 1 Or pFormSize.Width < 1 Or pFormSize.IsEmpty Then
oFormSize = New Size(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT)
Else
oFormSize = pFormSize
End If
pForm.Size = oFormSize
End Sub
''' <summary>
''' Checks if a point is Visible on any screen
''' </summary>
Public Shared Function IsVisibleOnAnyScreen(Location As Point) As Boolean
Try
Dim oRect As New Rectangle(Location, New Size(0, 0))
For Each oScreen In Screen.AllScreens
If oScreen.WorkingArea.IntersectsWith(oRect) Then
Return True
End If
Next
Return False
Catch ex As Exception
Return False
End Try
End Function
''' <summary>
''' Checks if Size is not negative
''' </summary>
Public Shared Function SizeIsVisible(Size As Size) As Boolean
If Size.Width >= 0 And Size.Height >= 0 Then
Return True
End If
Return False
End Function
''' <summary>
''' Checks if Location is not negative
''' </summary>
Public Shared Function LocationIsVisible(Location As Point) As Boolean
If Location.X >= 0 And Location.Y >= 0 Then
Return True
End If
Return False
End Function
Public Function GetScreenScaling(Form As Form) As Single
Dim oHandle As IntPtr = Form.Handle
Dim oFactor1, oFactor2 As Single
oFactor1 = GetFactorFromDeviceCaps(oHandle)
oFactor2 = GetDPIFromMonitor(oHandle)
If oFactor1 > 1 Then
Return oFactor1
Else
Return oFactor2
End If
End Function
Private Function GetFactorFromDeviceCaps(Handle As IntPtr) As Single
Dim g As Graphics = Graphics.FromHwnd(Handle)
Dim desktop As IntPtr = g.GetHdc()
Dim LogicalScreenHeight As Integer = GetDeviceCaps(desktop, DeviceCap.VERTRES)
Dim PhysicalScreenHeight As Integer = GetDeviceCaps(desktop, DeviceCap.DESKTOPVERTRES)
Dim oScreenScalingFactor As Single = CSng(PhysicalScreenHeight) / CSng(LogicalScreenHeight)
Return oScreenScalingFactor
End Function
Private Function GetDPIFromMonitor(Handle As IntPtr) As Single
'Get handle to monitor that contains this window.
Dim monitorHandle As IntPtr = MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST)
'Get DPI (If the OS is not Windows 8.1 or newer, calling GetDpiForMonitor will cause exception).
Dim dpiX As UInteger
Dim dpiY As UInteger
Dim result As Integer = GetDpiForMonitor(monitorHandle, Monitor_DPI_Type.MDT_Default, dpiX, dpiY)
If (result = 0) Then 'If S_OK (= 0)
Return dpiX / 96.0F
Else
Return -1
End If
End Function
End Class