[英]Is there a way to retrieve a device's DPI without using GDI+/WinForms “Graphics” class?
[英]What's the correct way to retrieve the DPI of secondary monitors?
问题
在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)
(结果120,无论hMonitor句柄如何)
(user32.dll)
IntPtr dC = CreateDC(...);
double logX = (double)GetDeviceCaps(dC, LOGPIXELSX);
double logY = (double)GetDeviceCaps(dC, LOGPIXELSY);
(结果120,与CreateDC的设备名称无关)
监视器布局
令我严重困惑的另一件事是,第一台显示器位于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的正确方法是shcore.dll
的GetDpiForMonitor
方法。 问题是没有尽早调用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
,这就是它的不同之处。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.