什么';这是检索辅助监视器DPI的正确方法

本文关键字:DPI 监视器 方法 检索 什么 | 更新日期: 2023-09-27 18:20:10

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

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

尝试次数

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

(结果120与hMonitor句柄无关)

(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会这样做)。

什么';这是检索辅助监视器DPI的正确方法

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

获得备用监视器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,这就是区别所在。