【问题标题】:Scaling non-client area for per-monitor high-DPI support on application supporting Windows 8.1在支持 Windows 8.1 的应用程序上缩放非客户区以支持每个显示器的高 DPI
【发布时间】:2019-06-04 05:43:55
【问题描述】:

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

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

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

【问题讨论】:

  • 值得支持8.1吗?大多数人肯定会利用免费升级到 10 的优势。
  • @JonathanPotter 你的意思是降级?在小型平板电脑上,8.1 优于 10。
  • Windows 10 Aniversary Update High-DPI Scaling Improvements 中引入的每个显示器缩放的非客户区。
  • 非客户区的缩放。在周年更新之前,无法使用 Windows 绘制的非客户区 DPI 比例(标题栏、系统菜单、顶级滚动条、菜单栏等)。这意味着,如果您创建了一个基于监视器的应用程序,那么在 DPI 更改之后,您将留下大小不正确(太大或太小)的非客户区,除了自己绘制所有这些东西之外,没有任何办法。在周年更新中,我们添加了一个 API,您可以调用它来打开非客户端缩放,EnableNonClientDpiScaling,但现在使用 PMv2,您可以自动获得此功能

标签: winapi windows-8.1 dpi highdpi


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    感谢 Anders,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.");
    }
    

    【讨论】:

    • 这段代码不需要,可以用manifest设置。 Vista 元素为“True/PM”,Windows 10 元素为 Per Monitor v2。
    猜你喜欢
    • 2016-08-20
    • 2015-11-25
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    • 1970-01-01
    • 2015-01-07
    • 2016-10-19
    • 1970-01-01
    相关资源
    最近更新 更多