Base: Add WindowsEx, ScreenEx

This commit is contained in:
Jonathan Jenne 2023-07-27 15:47:02 +02:00
parent 28538bcf41
commit 7b2b37a870
5 changed files with 335 additions and 45 deletions

View File

@ -81,8 +81,10 @@
<Compile Include="BaseUtils.vb" />
<Compile Include="DatabaseEx.vb" />
<Compile Include="ECM\ECM.vb" />
<Compile Include="WindowsEx.vb" />
<Compile Include="ModuleExtensions.vb" />
<Compile Include="FileEx.vb" />
<Compile Include="NativeMethods.vb" />
<Compile Include="ObjectEx.vb" />
<Compile Include="GraphicsEx.vb" />
<Compile Include="IDB\Attributes.vb" />
@ -105,7 +107,6 @@
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="PerformanceEx.vb" />
<Compile Include="ScreenEx.vb" />
<Compile Include="StringEx.vb" />
</ItemGroup>

237
Base/NativeMethods.vb Normal file
View File

@ -0,0 +1,237 @@
Imports System.Runtime.InteropServices
Imports System.Text
Imports DigitalData.Modules.Base.ScreenEx
Public Class NativeMethods
Public Declare Function GetWindowTextLength Lib "user32.dll" Alias "GetWindowTextLengthA" (ByVal hwnd As Int32) As Integer
Public Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hWnd As IntPtr, ByVal WinTitle As String, ByVal MaxLength As Integer) As Integer
<DllImport("Shell32", CharSet:=CharSet.Auto, SetLastError:=True)>
Public Shared Function ShellExecuteEx(ByRef lpExecInfo As ShellExecuteInfo) As Boolean
End Function
<DllImport("user32", EntryPoint:="SetClipboardViewer")>
Public Shared Function SetClipboardViewer(ByVal hWnd As IntPtr) As IntPtr
End Function
<DllImport("user32.dll")>
Public Shared Function GetDC(ByVal hwnd As IntPtr) As IntPtr
End Function
<DllImport("user32.dll")>
Public Shared Function ReleaseDC(ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As IntPtr
End Function
<DllImport("User32.dll")>
Public Shared Function ReleaseCapture() As Boolean
End Function
<DllImport("user32.dll")>
Public Shared Function GetWindowRect(ByVal hWnd As HandleRef, ByRef lpRect As RectangleAPI) As Boolean
End Function
<DllImport("user32.dll")>
Public Shared Function AttachThreadInput(ByVal idAttach As IntPtr, ByVal idAttachTo As IntPtr, fAttach As Boolean) As Boolean
End Function
<DllImport("user32.dll")>
Public Shared Function GetFocus() As IntPtr
End Function
<DllImport("user32.dll")>
Public Shared Function WindowFromPoint(ByVal p As PointAPI) As IntPtr
End Function
<DllImport("user32.dll")>
Public Shared Function GetForegroundWindow() As IntPtr
End Function
<DllImport("user32.dll")>
Public Shared Function GetWindowThreadProcessId(ByVal hwnd As IntPtr, ByRef lpdwProcessID As Integer) As Integer
End Function
<DllImport("user32.dll")>
Public Shared Function GetClassName(ByVal hwnd As Integer, ByVal lpClassName As StringBuilder, ByVal nMaxCount As Integer) As Integer
End Function
<DllImport("kernel32.dll")>
Public Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, ByVal bInheritHandle As Boolean, ByVal dwProcessId As UInteger) As IntPtr
End Function
<DllImport("kernel32.dll")>
Public Shared Function VirtualAllocEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UIntPtr, ByVal flAllocationType As UInteger, ByVal flProtect As PageProtection) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True)>
Public Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, <Out> ByRef lpdwProcessId As UInteger) As UInteger
End Function
<DllImport("kernel32.dll")>
Public Shared Function VirtualFreeEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UIntPtr, ByVal dwFreeType As UInteger) As Boolean
End Function
<DllImport("kernel32.dll")>
Public Shared Function CloseHandle(ByVal hObject As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll")>
Public Shared Function MapViewOfFile(ByVal hFileMappingObject As IntPtr, ByVal dwDesiredAccess As UInteger, ByVal dwFileOffsetHigh As UInteger, ByVal dwFileOffsetLow As UInteger, ByVal dwNumberOfBytesToMap As UIntPtr) As IntPtr
End Function
<DllImport("kernel32.dll")>
Public Shared Function UnmapViewOfFile(ByVal lpBaseAddress As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True)>
Public Shared Function CreateFileMapping(ByVal hFile As IntPtr, ByVal lpFileMappingAttributes As IntPtr, ByVal flProtect As PageProtection, ByVal dwMaximumSizeHigh As Integer, ByVal dwMaximumSizeLow As Integer, ByVal lpName As String) As IntPtr
End Function
<DllImport("user32.dll")>
Public Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function
<DllImport("kernel32.dll")>
Public Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr,
<Out> ByVal lpBuffer As Byte(), ByVal nSize As UIntPtr, ByVal lpNumberOfBytesRead As IntPtr) As Boolean
End Function
<DllImport("Kernel32.dll", EntryPoint:="RtlMoveMemory", SetLastError:=False)>
Public Shared Sub MoveMemoryFromByte(ByVal dest As IntPtr, ByRef src As Byte, ByVal size As Integer)
End Sub
<DllImport("Kernel32.dll", EntryPoint:="RtlMoveMemory", SetLastError:=False)>
Public Shared Sub MoveMemoryToByte(ByRef dest As Byte, ByVal src As IntPtr, ByVal size As Integer)
End Sub
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function RegisterWindowMessage(ByVal lpString As String) As Integer
End Function
<DllImport("user32.dll", ExactSpelling:=True, SetLastError:=True)>
Public Shared Function GetCursorPos(ByRef lpPoint As PointAPI) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("User32.dll", SetLastError:=True)>
Friend Shared Function MonitorFromWindow(ByVal hwnd As IntPtr,
ByVal dwFlags As Integer) As IntPtr
End Function
<DllImport("Shcore.dll", SetLastError:=True)>
Friend Shared Function GetDpiForMonitor(ByVal hmonitor As IntPtr,
ByVal dpiType As Monitor_DPI_Type,
ByRef dpiX As UInteger,
ByRef dpiY As UInteger) As Integer
End Function
<DllImport("gdi32.dll")>
Friend Shared Function GetDeviceCaps(ByVal hdc As IntPtr, ByVal nIndex As Integer) As Integer
End Function
Public Declare Function RegisterHotKey Lib "user32" (
ByVal Hwnd As IntPtr,
ByVal ID As Integer,
ByVal Modifiers As Integer,
ByVal Key As Integer
) As Integer
Public Declare Function UnregisterHotKey Lib "user32" (
ByVal Hwnd As IntPtr,
ByVal ID As Integer
) As Integer
Public Declare Auto Function GetWindowText Lib "user32" (
ByVal hWnd As IntPtr,
ByVal lpString As StringBuilder,
ByVal cch As Integer
) As Integer
Public Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal IDString As String) As Short
Public Declare Function GlobalDeleteAtom Lib "kernel32" (ByVal Atom As Short) As Short
Public Const STANDARD_RIGHTS_REQUIRED As Integer = &HF0000
Public Const SECTION_QUERY As Short = &H1
Public Const SECTION_MAP_WRITE As Short = &H2
Public Const SECTION_MAP_READ As Short = &H4
Public Const SECTION_MAP_EXECUTE As Short = &H8
Public Const SECTION_EXTEND_SIZE As Short = &H10
Public Const SECTION_ALL_ACCESS As Integer = STANDARD_RIGHTS_REQUIRED Or SECTION_QUERY Or SECTION_MAP_WRITE Or SECTION_MAP_READ Or SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE
Public Const FILE_MAP_ALL_ACCESS As Integer = SECTION_ALL_ACCESS
Public Const PROCESS_VM_OPERATION As Short = &H8
Public Const PROCESS_VM_READ As Short = &H10
Public Const PROCESS_VM_WRITE As Short = &H20
Public Const PROCESS_ALL_ACCESS As Long = &H1F0FFF
Public Const MEM_COMMIT As Short = &H1000
Public Const MEM_RESERVE As Short = &H2000
Public Const MEM_DECOMMIT As Short = &H4000
Public Const MEM_RELEASE As Integer = &H8000
Public Const MEM_FREE As Integer = &H10000
Public Const MEM_PRIVATE As Integer = &H20000
Public Const MEM_MAPPED As Integer = &H40000
Public Const MEM_TOP_DOWN As Integer = &H100000
Public Const INVALID_HANDLE_VALUE As Integer = -1
Public Const SW_SHOW As Short = 5
Public Const SEE_MASK_INVOKEIDLIST = &HC
Public Const SEE_MASK_NOCLOSEPROCESS = &H40
Public Const SEE_MASK_FLAG_NO_UI = &H400
Public Const ULW_COLORKEY As Integer = &H1
Public Const ULW_ALPHA As Integer = &H2
Public Const ULW_OPAQUE As Integer = &H4
Public Const AC_SRC_OVER As Byte = &H0
Public Const AC_SRC_ALPHA As Byte = &H1
Public Const HTCAPTION As Integer = &H2
Public Const WM_NCLBUTTONDOWN As Integer = &HA1
Public Const WM_HOTKEY As Integer = &H312
Public Const WM_DRAWCLIPBOARD As Integer = &H308
Public Enum PageProtection As UInteger
NoAccess = &H1
[Readonly] = &H2
ReadWrite = &H4
WriteCopy = &H8
Execute = &H10
ExecuteRead = &H20
ExecuteReadWrite = &H40
ExecuteWriteCopy = &H80
Guard = &H100
NoCache = &H200
WriteCombine = &H400
End Enum
Public Enum ChildWindowFromPointFlags As UInteger
CWP_ALL
CWP_SKIPINVISIBLE
CWP_SKIPDISABLED
CWP_SKIPTRANSPARENT
End Enum
<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 Structure RectangleAPI
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
Public Overrides Function ToString() As String
Return String.Format("Top: {0}, Bottom: {1}, Left: {2}, Right: {3}", Top, Bottom, Left, Right)
End Function
End Structure
Public Structure ShellExecuteInfo
Public cbSize As Integer
Public fMask As Integer
Public hwnd As IntPtr
<MarshalAs(UnmanagedType.LPTStr)> Public lpVerb As String
<MarshalAs(UnmanagedType.LPTStr)> Public lpFile As String
<MarshalAs(UnmanagedType.LPTStr)> Public lpParameters As String
<MarshalAs(UnmanagedType.LPTStr)> Public lpDirectory As String
Dim nShow As Integer
Dim hInstApp As IntPtr
Dim lpIDList As IntPtr
<MarshalAs(UnmanagedType.LPTStr)> Public lpClass As String
Public hkeyClass As IntPtr
Public dwHotKey As Integer
Public hIcon As IntPtr
Public hProcess As IntPtr
End Structure
<System.Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential)>
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

View File

@ -1,44 +0,0 @@
Imports System.IO
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Security.Cryptography
Imports DigitalData.Modules.Logging
Public Class PerformanceEx
Public Sub New(pLogConfig As LogConfig, pAppDataPath As String)
Dim savedHash = String.Empty
Dim assemblyLocation = Assembly.GetEntryAssembly().Location
Dim hashPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "hash.txt")
If Not File.Exists(hashPath) Then
File.Create(hashPath)
Else
savedHash = File.ReadAllText(hashPath)
End If
Dim hash = String.Concat(SHA1.Create().ComputeHash(File.ReadAllBytes(assemblyLocation)).Select(Function(x) x.ToString("x2")))
If hash.Equals(savedHash) Then
Return
End If
Dim dotNetRuntimePath = RuntimeEnvironment.GetRuntimeDirectory()
Dim ngenPath = Path.Combine(dotNetRuntimePath, "ngen.exe")
Dim process = New Process With {
.StartInfo = New ProcessStartInfo With {
.FileName = ngenPath,
.Arguments = $"install ""{assemblyLocation}"" /nologo",
.CreateNoWindow = True,
.UseShellExecute = True,
.Verb = "runas"
}
}
Try
process.Start()
process.WaitForExit()
File.WriteAllText(hashPath, hash)
Catch
' ...
End Try
End Sub
End Class

View File

@ -1,11 +1,30 @@
Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports DigitalData.Modules.Base.NativeMethods
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
@ -100,4 +119,45 @@ Public Class ScreenEx
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

36
Base/WindowsEx.vb Normal file
View File

@ -0,0 +1,36 @@
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Base.NativeMethods
Public Class WindowsEx
Private ReadOnly _LogConfig As LogConfig
Private ReadOnly _Logger As Logger
Public Sub New(LogConfig As LogConfig)
_LogConfig = LogConfig
_Logger = LogConfig.GetLogger()
End Sub
Public Function OpenFileProperties(FilePath As String) As Boolean
Try
Dim oShellExecuteInfo As New ShellExecuteInfo()
oShellExecuteInfo.cbSize = Marshal.SizeOf(oShellExecuteInfo)
oShellExecuteInfo.lpVerb = "properties"
oShellExecuteInfo.lpFile = FilePath
oShellExecuteInfo.nShow = SW_SHOW
oShellExecuteInfo.fMask = SEE_MASK_INVOKEIDLIST
If Not ShellExecuteEx(oShellExecuteInfo) Then
Dim oWin32Error = Marshal.GetLastWin32Error()
Dim oException As New Win32Exception(oWin32Error)
Throw oException
End If
Return True
Catch ex As Exception
_Logger.Error(ex)
Return False
End Try
End Function
End Class