问题
Microsoft can't figure out how to help me, so I have to ask here.
I have three monitors...
- Screen 1: 3840 x 2160, scaling 150%
- Screen 2: 1920 x 1200, scaling 100%
- Screen 3: 1920 x 1200, scaling 100%
I need in VB.net
or C#
to get the scaling of each monitors.
Microsoft advises me to use this code:
Private Declare Function GetDeviceCaps Lib "gdi32.dll" (hdc As IntPtr, nIndex As Integer) As Integer
Public Enum DeviceCap
VERTRES = 10
DESKTOPVERTRES = 117
End Enum
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
For Each screen As Forms.Screen In Forms.Screen.AllScreens
Dim pnt = New System.Drawing.Point(screen.Bounds.Left + 1, screen.Bounds.Top + 1)
Dim mon = MonitorFromPoint(pnt, 2)
Dim fac As Single = GetScalingFactor(mon)
Console.WriteLine($"Factor: {fac}")
Next
End Sub
Private Function GetScalingFactor(monitorHandle As IntPtr) As Single
Dim g As Graphics = Graphics.FromHwnd(IntPtr.Zero)
Dim desktop As IntPtr = g.GetHdc()
Dim LogicalScreenHeight As Integer = GetDeviceCaps(desktop, CInt(DeviceCap.VERTRES))
Dim PhysicalScreenHeight As Integer = GetDeviceCaps(desktop, CInt(DeviceCap.DESKTOPVERTRES))
Dim ScreenScalingFactor As Single = CSng(PhysicalScreenHeight) / CSng(LogicalScreenHeight)
Return ScreenScalingFactor
End Function
But it returns a scale of 1 for all my screens.
I need it to be independent of my app being dpiAware or not, so I have to read it from the screen control panel somehow.
The solution must work on both Windows 10 and Windows Server 2012 R2 Remote Desktop clients.
回答1:
I believe you can use the ResolutionScale property in the DisplayInformation class. This retrieves you an enum with the scale factor, but I do not know if it is dpiAware independent or not.
回答2:
This might help you.
Normally screen monitors have a rawDpi 102 dots x inch but if you have a Microsft Surface is logic you have another rawDpi. So in this case you can change 102 with real device rawDpi (you can get that by code under 100% screen resolution)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each screen In System.Windows.Forms.Screen.AllScreens
Dim mRawSreen As SCREENS = Display(screen, DpiType.MDT_RAW_DPI)
Console.WriteLine(" deviceName: " & screen.DeviceName &
" ScaleFactorX: " & (102 / mRawSreen.DPI_X * 100).ToString("N2") & "%" &
" ScaleFactorY: " & (102 / mRawSreen.DPI_Y * 100).ToString("N2") & "%")
Next
End Sub
Public Enum DpiType
MDT_EFFECTIVE_DPI = 0
MDT_ANGULAR_DPI = 1
MDT_RAW_DPI = 2
End Enum
Structure SCREENS
Dim DPI_X As Integer
Dim DPI_Y As Integer
End Structure
Private Function Display(screen As Screen, ByVal type As DpiType) As SCREENS
Dim x, y As UInteger
GetDpi(screen, type, x, y)
Dim current As SCREENS = New SCREENS With {
.DPI_X = x,
.DPI_Y = y
}
'Console.WriteLine(" deviceName: " & screen.DeviceName & " typeDpi: " & type.ToString & " : dpiX=" & x & ", dpiY=" & y)
Return current
End Function
Private Declare Function MonitorFromPoint Lib "User32.dll" (ByVal pt As System.Drawing.Point, ByVal dwFlags As UInteger) As IntPtr
Private Declare Function GetDpiForMonitor Lib "Shcore.dll" (ByVal hmonitor As IntPtr, ByVal dpiType As DpiType, ByRef dpiX As UInteger, ByRef dpiY As UInteger) As IntPtr
Sub GetDpi(ByVal screen As System.Windows.Forms.Screen, ByVal dpiType As DpiType, ByRef dpiX As UInteger, ByRef dpiY As UInteger)
Dim pnt = New System.Drawing.Point(screen.Bounds.Left + 5, screen.Bounds.Top + 5)
Dim mon = MonitorFromPoint(pnt, 2)
GetDpiForMonitor(mon, dpiType, dpiX, dpiY)
End Sub
来源:https://stackoverflow.com/questions/58971670/how-can-i-get-the-scale-factor-of-all-my-monitors