3

我正在开发一个在 Windows 10 和 8.1 上运行的应用程序,并且在具有不同 DPI 的显示器之间移动时遇到了缩放非客户区(菜单栏、标题栏)的问题。客户区得到处理,但非客户区不成比例。DPI Awareness 设置为 PerMonitorAware(v1,因为 v2 在 Windows 8.1 上不可用)。

EnableNonClientDpiScaling 函数完全符合我的需要(它是所有类似问题的公认答案) - 可惜它只是 Windows 10 上 API 的一部分。

有没有办法在没有前面提到的功能的情况下手动处理这个 - 为了保持对 Windows 8.1 的支持?或者支持 Windows 8.1 是否意味着在具有不同 DPI 的屏幕之间移动时无法调整非客户区的大小?

4

2 回答 2

3

DPI 支持是一个不断变化的目标,您只需确定您的最低支持平台是什么,并接受多显示器缩放在这些旧平台上并不完美。

调用EnableNonClientDpiScaling可用的版本(GetProcAddress或您使用的任何语言的等效版本)。

新的感知清单元素在 Windows 10 中的工作方式意味着您可以是受支持的 Per-Monitor v2(1703 及更高版本),以及旧版本上的 PMv1、System 或 Unaware。PMv2 为您提供DialogBox基于对话框的自动缩放。

于 2019-01-09T13:09:31.200 回答
1

感谢安德斯,GetProcAddress正是我正在寻找的东西。虽然它不能解决 Win 8.1 上的非客户区大小调整(似乎除了自己绘制所有东西之外真的没有办法),它使得DPI_AWARENESS_CONTEXT在 Win 10 上设置最新成为可能:

// the following sets PROCESS_PER_MONITOR_AWARE_V2 on Win10 and
// reverts to PROCESS_PER_MONITOR_AWARE on Win 8.1

typedef BOOL(__stdcall *SetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
SetProcessDpiAwarenessContext dpi_call = nullptr;
dpi_call = reinterpret_cast<SetProcessDpiAwarenessContext>(GetProcAddress(
    GetModuleHandle(TEXT("User32.dll")),
    "SetProcessDpiAwarenessContext"));
if (dpi_call != nullptr) {
    if (!(*dpi_call)((DPI_AWARENESS_CONTEXT) - 4))
        throw std::runtime_error("Unable to set DPI aware app.");
} else {
    if (SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE) != S_OK)
        throw std::runtime_error("Unable to set DPI aware app.");
}
于 2019-01-09T17:35:32.650 回答