【问题标题】:SetProcessDPIAware seems not to work under windows 10SetProcessDPIAware 似乎在 Windows 10 下不起作用
【发布时间】:2016-03-21 14:42:16
【问题描述】:

我正在尝试在 Windows C++ 应用程序中获取真实的屏幕分辨率(以像素为单位)。当 windows dpi 设置更改时,我得到的是虚拟(调整后的)分辨率而不是真实分辨率。我尝试过在清单中使用 SetProcessDPIAware、SetProcessDpiAwareness(所有三个枚举值作为参数)和真实设置。在所有这三种情况下,代码在我的 Windows 7 PC 中都可以正常工作(即显示真实分辨率),但在 Win 10 中却不行(这里它忽略了 DPI Aware 设置并返回调整后的分辨率)。

#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used stuff from Windows headers

// Windows Header Files:
#include <windows.h>
#include <winuser.h>
#include <VersionHelpers.h>
#include <ShellScalingAPI.h>
#include <stdlib.h>
#include <stdio.h>

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
char *cBuffer2 ;

  cBuffer2 = (char *)malloc(3000) ;
  if (IsWindowsVistaOrGreater())
  {
//    SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE);
      int result = SetProcessDPIAware();

      sprintf(cBuffer2,"SetProcessDPIAware() result: [%i]\n",result) ;

      int height = GetSystemMetrics(SM_CYSCREEN);
      int width = GetSystemMetrics(SM_CXSCREEN);
      sprintf(cBuffer2,"%s#1:\nHeight: [%i]\nwidth: [%i]\n",cBuffer2,height,width) ;


      HWND hwnd = (HWND)atoi(lpCmdLine) ;
      HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
      MONITORINFO info;
      info.cbSize = sizeof(MONITORINFO);
      GetMonitorInfo(monitor, &info);
      int monitor_width = info.rcMonitor.right - info.rcMonitor.left;
      int monitor_height = info.rcMonitor.bottom - info.rcMonitor.top;
      sprintf(cBuffer2,"%s#2:\nHeight: [%i]\nwidth: [%i]\n",cBuffer2,monitor_height,monitor_width) ;

  }

  MessageBox(0,cBuffer2,"SHOWRES.EXE",MB_OK) ;
  return 0 ;
}

我尝试使用的清单如下:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

有什么想法吗?

【问题讨论】:

  • 很难说你在这里做了什么。你似乎同时拥有很多东西。你为什么不选择一个并坚持下去。我建议您使用清单方法。你没有告诉我们输出是什么。
  • 问题是我们不知道您想要哪种方法,以及您尝试过的方法。我希望您选择一种方法,并提交minimal reproducible example
  • 所以您使用了清单并调用了SetProcessDPIAware。你为什么这么做?你应该选一个。您还应该显示程序的输出。您应该告诉我们您在所有机器上的 DPI 设置。无论如何,我会在这一点上放弃。提取更多信息太难了。祝你好运。
  • 我尝试了您的示例代码,仅使用 SetProcessDPIAware 它似乎在 Windows 10 中运行良好(获得显示器的真实分辨率)。
  • 我也试过了,它似乎有效。您在写信之前没有将cBuffer2 归零。

标签: c++ winapi screen-resolution dpi


【解决方案1】:

在 Jonathan Potter 和 Barmak Shemirani 的帮助下,我终于发现了发生了什么:Windows 10 与以前的 Windows 版本不同,它允许用户“即时”更改 dpi 设置,而无需注销并再次登录。我在通常具有标准(100%)设置的 win 10 机器上运行测试。所以我将设置更改为 150%,运行应用程序并得到错误的结果。

Jonathan 和 Barmak 的回答表明,在特定 PC 的设置中,而不是在程序或 win 10 中,导致了我的问题。所以我尝试了以下方法:

- changed DPI settings to 150%
- logged out
- logged in again
- ran the program

我得到了正确的结果(真实的屏幕分辨率,与调整后的分辨率)。

因此看来,为了使 SetProcessDPIAware(以及相关方法:SetProcessDpiAwareness() 和 manifest 为 true)正常工作,必须在更改 DPI 设置后和运行程序之前注销并再次登录。

再次感谢乔纳森和巴马克!

【讨论】:

  • 这可能没有帮助,但 SetProcessDpiAware() 的文档明确表示不要在更高版本的 Windows 中使用它(根据 MSDN 中针对该功能的要求部分),并且 SetProcessDpiAwareness() 应该是使用 而不是 (并且它最多应该被调用一次 - 无论是通过清单还是通过代码)。
猜你喜欢
  • 2011-10-08
  • 2015-01-29
  • 1970-01-01
  • 2019-01-28
  • 2010-12-22
  • 2023-03-15
  • 2016-11-29
  • 2016-02-01
  • 2020-09-23
相关资源
最近更新 更多