在支持 Windows 8.1 的设备上缩放非工作区以获得每显示器高 DPI 支持



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

EnableNonClientDpiScaling 函数完全符合我的需求(它是所有类似问题的公认答案) - 唉,它只是 Windows 10 开始的 API 的一部分。

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

DPI 支持是一个移动目标,您只需要确定支持的最低平台是什么,并接受多显示器扩展在这些旧平台上并不完美。

在可用的版本上调用EnableNonClientDpiScalingGetProcAddress或您使用的任何语言的等效版本)。

新的感知清单元素在 Windows 10 中的工作方式意味着,你可以在支持它的地方使用每监视器 v2(1703 及更高版本),在旧版本中可以是 PMv1、系统或无感知。PMv2 可让您自动缩放基于DialogBox的对话框。

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

// 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.");
}

最新更新