如何获取所有显示器的缩放比例?

4

微软帮不了我,所以我只能在这里询问。

我有三个显示器...

  • 屏幕1:3840 x 2160,缩放比例为150%
  • 屏幕2:1920 x 1200,缩放比例为100%
  • 屏幕3:1920 x 1200,缩放比例为100%

我需要使用VB.netC#来获取每个显示器的缩放比例。

Microsoft建议我使用以下代码:

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

但它对我所有的屏幕都返回1的比例。

我需要它独立于我的应用程序是否dpiAware,所以我不得不以某种方式从屏幕控制面板中读取它。

解决方案必须适用于Windows 10和Windows Server 2012 R2远程桌面客户端。


@JoãoSilva - 我的注册表中没有LogPixels条目。不过还是谢谢你。 - MojoDK
这个链接似乎可以解决问题 - 以各种方式(虽然是用C#编写的,但应该很容易转换)。选择你喜欢的方法。 - Christian.K
1
你的代码使用了WPF风格的事件处理程序,这是一个WPF应用程序吗?WPF应用程序天生就是DpiAware的,除非你强制禁用它。为什么不使用 PresentationSource.FromVisual(Application.Current.MainWindow).CompositionTarget.TransformToDevice 返回的矩阵呢?在WPF中使用 Graphics.FromHwnd() 没有任何意义。 - Jimi
@Jimi...它必须在Winforms、Wpf、dpiAware和非dpiAware中工作...因此我需要从系统中读取它。 - MojoDK
如果你想走这条路...请参考QueryDisplayConfigGetScaleFactorForMonitor(注意支持的不同平台)。使用QueryDisplayConfig,你需要关注SOURCE - Jimi
显示剩余5条评论
2个回答

0

我相信你可以在DisplayInformation类中使用ResolutionScale属性。这将检索一个枚举,其中包含比例因子,但我不知道它是否与dpi无关。


0

这可能会对你有所帮助

通常屏幕显示器的原始DPI为102点每英寸,但如果你使用微软Surface设备,则逻辑上你会有另一个原始DPI。 因此,在这种情况下,你可以将102更改为实际设备的原始DPI(你可以通过在100%屏幕分辨率下编写代码来获取该值)。

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

谢谢你在这里帮助我......但我不完全确定,上面的DPI代码如何帮助我获得用户定义的自定义缩放? - MojoDK
原始DPI与有效DPI不同。有效DPI在屏幕自定义分辨率上不会改变,而是原始DPI会在自定义分辨率中进行更改。因此,在这一点上,您可以通过百分比(如上面的代码所示,普通原始DPI/自定义原始DPI)进行计算。要获取初始的普通原始DPI,您也可以使用此代码,并将其保存在注册表或其他位置。这是为了删除我的静态102. :) - G3nt_M3caj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接