使Windows通用对话框“按监视器DPI感知”

时间:2016-02-17 10:57:10

标签: windows mfc dpi dpi-aware

我有一个在VS2008中使用MFC创建的程序。 现在我已经修改它以使其成为“Per Monitor DPI-Aware”,它几乎已经完成了。我修改了清单并处理了WM_DPICHANGE消息。但仍有一个问题:

我使用 CFileDialog 类来显示“打开/保存”对话框,并使用 SHBrowseForFolder 功能显示文件夹选择对话框。但是所有这些对话框都是“Per Monitor DPI-Aware”,当您在具有不同DPI设置的监视器之间移动它们时,它们将不会调整其UI。

我使用spy ++来监视这些对话框的消息,我发现它们可以接收WM_DPICHANGED消息,但它们只是不处理它。

我已经在Windows 10上的notepad.exe中测试了打开的文件对话框,它运行得很好。

有谁知道如何制作这些对话框“Per Monitor DPI-Aware”?

--------的修改 --------

还有两个问题:

  1. 当我将窗口移动到具有不同DPI的显示器时,窗口会自行调整大小,但标题栏和标题字体大小的高度不会更改。
  2. 复选框控件的框大小也不会更改。
  3. 我觉得这些问题可能有某种联系,但我无法弄明白。

    -------- SAD NEWS --------

    我使用VS2013编译了microsoft的“DPI Tutorial Sample”,它有同样的问题。

    https://code.msdn.microsoft.com/DPI-Tutorial-sample-64134744

2 个答案:

答案 0 :(得分:1)

标题栏(标题栏)可以通过调用Windows版本> = Windows 10周年更新(1607)上提供的EnableNonClientDpiScaling来扩展。

如果要DPI扩展不支持每个监视器DPI扩展的旧对话框,可以使用SetThreadDpiAwarenessContext(使用DPI_AWARENESS_CONTEXT_SYSTEM_AWARE或DPI_AWARENESS_CONTEXT_UNAWARE)使Windows对话框的顶级窗口缩放。该对话框可能会模糊,但至少会正确调整大小(也仅适用于Windows 10的> = 1607版本)。使用模式是在打开对话框之前调用此API,然后在调用API后立即恢复以前的DPI上下文。

答案 1 :(得分:0)

根据MSDN,处理WM_DPICHANGED消息的窗口应返回0.但是,您发送的任何MFC窗口或控件WM_DPICHANGED将返回0,因为它会调用默认窗口过程未知的消息。

因此,判断某个窗口是否通过测试其WM_DPICHANGED返回值对零来处理LRESULT消息是不准确的。

每个监视器DPI感知应用程序的窗口标题栏在MSDN上记录的不同DPI监视器上移动时不会缩放。不幸的是,窗口的非客户区域从不调整DPI。

计算器和其他每个监视器支持DPI的Windows本机应用程序具有自定义标题栏图,如here所述。