Windows DPI 相关问题

Posted

技术标签:

【中文标题】Windows DPI 相关问题【英文标题】:Windows DPI related issues 【发布时间】:2015-10-15 19:55:28 【问题描述】:

抱歉,我没有给出具体的问题标题。

我的开发环境是带有 Visual Studio 2010 的 Windows 7。产品面向 Windows 7、8 和 10。

问题 1: 我怎样才能获得当前的 DPI 设置?

下面的代码总是返回 96,即 100% DPI 比例。

_dpiX = GetDeviceCaps(hdc, LOGPIXELSX);

问题 2: 我怎样才能得到实际的分辨率?

我尝试使用带有不同选项的 GetSystemMetrics,它们都返回相同的值,即缩放分辨率。例如,实际分辨率为 1920*1080 和 175% DPI,它们都返回 1097*617。

GetSystemMetrics(SM_CXFULLSCREEN)
GetSystemMetrics(SM_CXSCREEN)
GetSystemMetrics(SM_CXVIRTUALSCREEN)

问题 3: 我可以将应用设置为不使用 DPI 可视化功能吗?

我们有一个解决方法,涉及在“属性”->“兼容性”中勾选“在高 DPI 设置下禁用显示缩放”选项,并使用“更改所有用户的设置”。我在 Visual Studio 中将项目 DPIAwareness 设置为 true,但它什么也没做。

编辑: 有人说如果产品设置为 DPI 感知,它将无法获得 DPI 可视化。在我的例子中,它是一个将一些命令参数传递给另一个可执行文件的 GUI 程序。我在我的项目中将可执行的 DPIAwareness 设置为 true。但是 GUI 什么也没做。因此,如果 GUI 不支持 DPI,并且它启动了其他进程,那么其他进程是否也不支持 DPI?

【问题讨论】:

只要你不回答问题3,你就不会在乎1和2。很多很多方法可以自己找出来,谷歌“windows enable dpiawareness”。跨度> 事实上,如果我能解决问题 3,我可能只是解决了问题。关于问题 3 的核心思想是如何在我的项目中禁用 DPI 可视化。有人说将 DPIAwareness 设置为 true 会禁用它。但它似乎不起作用。 【参考方案1】:

第一个问题,你试过了吗?

monitorhandle = MonitorFromWindow(winH, MONITOR_DEFAULTTONEAREST)

winH 是程序窗口的句柄

MONITOR_DEFAULTTONEAREST = 2

然后:

GetDpiForMonitor(monitorhandle, MDT_EFFECTIVE_DPI, PointerToX, PointerToY)

MDT_EFFECTIVE_DPI = 0

这将检索 PointerToX 和 PointerToY 中的 DPI 设置

如果您需要 Windows 缩放值,您可以除以 96(当然*100 表示百分比)

如果在开始时设置 SetProcessDpiAwareness(1) 并没有帮助,我感到很惊讶,因为这应该消除设置兼容性标志的需要,尽管我不希望它在你的程序中自动扩展 GUI - 因此回答问题 1!

【讨论】:

【参考方案2】:

问题是您的应用程序不知道 DPI 要让它知道你需要在应用程序的清单文件中使 <dpiaware> 标记为 TRUE

仍然在这种情况下,您可以获得实际分辨率

你可以这样做

actualWidth = GetDeviceCaps(hdc, DESKTOPHORZRES);
actualHeight = GetDeviceCaps(hdc, DESKTOPVERTRES);

DESKTOPHORZRES 和 DESKTOPVERTRES 索引在 MSDN 中未提及,但它们会为您提供实际的宽度和高度

有一个函数GetDpiForWindow()可以为您提供 DPI 的实际值 但它只能在 Windows 10 或更高版本中使用

【讨论】:

以上是关于Windows DPI 相关问题的主要内容,如果未能解决你的问题,请参考以下文章

windows DPi缩放

Windows 应用程序 - DPI 问题

检索 Windows 设备的 DPI

更改Window缺省DPI,程序界面发生错乱的解决办法

如何在 Windows/Linux 上设置 Java Swing 应用程序的 DPI?

Windows DPI Awareness for WPF