【问题标题】:What's the correct way to retrieve the DPI of secondary monitors?检索辅助显示器 DPI 的正确方法是什么?
【发布时间】:2015-10-31 01:07:38
【问题描述】:

问题
在 Windows 8.1(和更高版本)上,DPI 设置是针对每个显示器的。我可以在系统设置中清楚地看到我的主显示器(笔记本电脑)设置为 125% dpi,而我的备用显示器设置为 100% dpi。我的应用程序完全用 C# 编写,我尝试的每个 API 调用都会导致辅助监视器的 DPI 不正确。请记住,我在我的进程初始化中调用此方法,并在我的清单中指定了 DPI 感知:

(shcore.dll)
SetProcessDpiAwareness(PROCESS_DPI_AWARENESS::PROCESS_PER_MONITOR_DPI_AWARE);

尝试

(shcore.dll) 
GetDpiForMonitor(hMonitor, MONITOR_DPI_TYPE::MDT_EFFECTIVE_DPI, &dpiX, &dpiY)

(无论 hMonitor 句柄如何,结果为 120)

(user32.dll)
IntPtr dC = CreateDC(...);
double logX = (double)GetDeviceCaps(dC, LOGPIXELSX);
double logY = (double)GetDeviceCaps(dC, LOGPIXELSY);

(无论 CreateDC 的设备名称如何,结果为 120)

显示器布局
另一件让我非常困惑的事情是,第一台显示器位于 rect {0,0,1920,1080},而第二台显示器位于 {2400,0,2400,1350},这实际上使实际桌面大小为 {4800x1350},虚拟桌面大小为 {3840x1080},但是显示器之间缺少我无法解释且无法理解的像素。

                 Screen 1    Screen 2
Actual Pixels:   1920x1080   2400x1350
Virtual Pixels:  1536x864    1920x1080
Top-Left Coord:  0x0         2400x0
Actual DPI:      120 (125%)   96 (100%)
Returned DPI:    120 (125%)  120 (125%)

我可以确认显示器具有不同 DPI 的另一种方法是将任何 DPI 感知应用程序的中心点拖动到显示器之间的边界将导致窗口更改其大小以在显示器之间保持一致(WPF 通过默认)。

【问题讨论】:

    标签: c# c++ wpf winapi


    【解决方案1】:

    我已经为此奋斗了一天,在我发布问题后不到一个小时,我就找到了答案。如果以后有人遇到这个问题,我会在这里留下这个问题。

    获取备用显示器 DPI 的正确方法是 shcore.dllGetDpiForMonitor 方法,正如我在上面尝试的那样。问题是SetProcessDpiAwareness 没有足够早地被调用以在windows/wpf 应用程序中产生影响。我通过创建一个新的控制台应用程序和一个新的 wpf 应用程序并用最少的代码重现它来测试这一点。控制台应用程序返回了正确的值,而 wpf 应用程序返回了错误的值。

    解决方案是将以下内容添加到清单文件中:

    <application xmlns="urn:schemas-microsoft-com:asm.v3">
      <windowsSettings>
        <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
      </windowsSettings>
    </application>
    

    这里的关键是 dpiAware 标记的值,它是 True/PM 而不仅仅是 True,这就是区别所在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-10
      • 1970-01-01
      • 2017-09-14
      • 2021-02-02
      • 1970-01-01
      • 2011-08-21
      • 1970-01-01
      • 2022-10-13
      相关资源
      最近更新 更多