我正在开发一个在Windows 10和8.1上运行的应用程序,该应用程序遇到了在具有不同DPI的显示器之间移动时缩放非客户区域(菜单栏,标题栏)的问题。客户区已处理,但非客户区超出比例。 DPI意识设置为PerMonitorAware(由于Windows 8.1上不支持v2,因此为v1)。
EnableNonClientDpiScaling函数完全满足我的需要(这是所有类似问题的公认答案)-it,它只是Windows 10上API的一部分。
是否有一种方法可以手动处理此问题而无需前面提到的功能-为了保持对Windows 8.1的支持?还是支持Windows 8.1意味着在具有不同DPI的屏幕之间移动时无法调整非工作区的大小?
答案 0 :(得分:3)
DPI支持是一个不断发展的目标,您只需确定最低支持的平台是什么,并接受多显示器缩放在这些旧平台上并不是完美的选择。
在可用的版本(EnableNonClientDpiScaling
或使用您使用的任何语言的等效语言)上致电GetProcAddress
。
新的感知清单元素在Windows 10中的工作方式意味着您可以是受支持的Per-Monitor v2(1703和更高版本),以及在较早版本上支持PMv1,System或Unaware。 PMv2使您可以自动缩放基于DialogBox
的对话框。
答案 1 :(得分:1)
多亏了安德斯(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.");
}