Winapi VERTRES和HORZRES取决于系统启动时的缩放设置
我最近一直在玩WINAPI来检索缩放设置和屏幕分辨率,我遇到了这种奇怪的行为Winapi VERTRES和HORZRES取决于系统启动时的缩放设置,winapi,windows-10,dpi-aware,Winapi,Windows 10,Dpi Aware,我最近一直在玩WINAPI来检索缩放设置和屏幕分辨率,我遇到了这种奇怪的行为 我有小C++程序(下面列出),检索VelTres、HORZRES、DeTabVIETROS和DeTrtOfRoZRes的值。我的程序还将DPI感知模式设置为1(系统级感知)。我注意到VERTRES、HORZRES报告的值取决于系统启动时使用的系统比例因子 因此,在我的笔记本电脑上,我将系统比例因子配置为150%,分辨率配置为1920x1080。这是启动时的配置。检索HORZRES和DESKTOPHORZRES时,两个值
我有小C++程序(下面列出),检索VelTres、HORZRES、DeTabVIETROS和DeTrtOfRoZRes的值。我的程序还将DPI感知模式设置为1(系统级感知)。我注意到VERTRES、HORZRES报告的值取决于系统启动时使用的系统比例因子
因此,在我的笔记本电脑上,我将系统比例因子配置为150%,分辨率配置为1920x1080。这是启动时的配置。检索HORZRES和DESKTOPHORZRES时,两个值都报告为1920 如果我将缩放设置更改为100%,并且不重新启动计算机,下次检索这些值时,它们将报告为2880(对于HORZRES)和1920(对于DESKTOPHORZRES) 当我在缩放设置设置为100%的情况下重新启动计算机后,这两个值都会再次报告为1920 如果我再次将缩放比例更改为150%,则报告的值为1280(HORZRES)和1920(DESKTOPHORZRES) 仅当我将DPI感知设置为1时,如果将其设置为0(“不感知”)或2(“每屏幕感知”),则所述行为始终报告为1280(HORZRES)和1920(DESKTOPHORZRES),无论启动时如何配置缩放 我想知道为什么HORZRES(或VERTRES)报告的值取决于系统启动时使用的比例因子?这是预期的行为吗 如果上面已经有描述的话,我希望能有任何参考资料#include "stdafx.h"
#include <iostream>
#include <vector>
#include <cerrno>
#include <string>
#include <sstream>
#include <math.h>
#include <Windows.h>
#include <shellscalingapi.h>
#include <winuser.h>
class Rectangular
{
public:
Rectangular(int height, int width) : height(height), width(width) {};
const int height;
const int width;
};
class MonitorInfo
{
public:
MonitorInfo(std::string device_name, Rectangular logical_resolution, Rectangular physical_resolution, Rectangular physical_size_mm) :
device_name(device_name), logical_resolution(logical_resolution), physical_resolution(physical_resolution),
physical_size_mm(physical_size_mm), scaling(static_cast<int>(std::round(100.0*(float)physical_resolution.height / (float)logical_resolution.height))) {};
void print_to_stdout() const;
const std::string device_name;
const Rectangular logical_resolution;
const Rectangular physical_resolution;
const Rectangular physical_size_mm;
const int scaling;
};
class MonitorsInformation
{
public:
MonitorsInformation();
const std::vector<MonitorInfo>& get_monitors_info() const { return monitors; }
std::string get_last_error_string() const { return last_error; }
Rectangular get_monitors_rectangular() const;
private:
RECT rectangular_combined;
std::vector<MonitorInfo> monitors;
std::string last_error;
static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData);
};
void MonitorInfo::print_to_stdout() const
{
std::cout << "\nDevice: " << device_name << "\nLogical Screen resolution: " << logical_resolution.width << "x" << logical_resolution.height;
std::cout << "\nPhysical Screen resolution: " << physical_resolution.width << "x" << physical_resolution.height;
std::cout << "\nDPI ratio: " << scaling;
std::cout << "\nPhysical Size(mm): " << physical_size_mm.width << "x" << physical_size_mm.height << "\n";
}
MonitorsInformation::MonitorsInformation() : rectangular_combined(RECT()), last_error(std::string()), monitors(std::vector<MonitorInfo>())
{
EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this);
}
BOOL CALLBACK MonitorsInformation::MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
{
MonitorsInformation* pThis = reinterpret_cast<MonitorsInformation*>(pData);
MONITORINFOEXA monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEXA);
if (!GetMonitorInfoA(hMon, &monitor_info))
{
pThis->last_error = "GetMonitorInfoA failed with error: " + errno;
return FALSE;
}
UnionRect(&pThis->rectangular_combined, &pThis->rectangular_combined, lprcMonitor);
HDC device_context = CreateDCA(NULL, monitor_info.szDevice, NULL, NULL);
int LogicalScreenHeight = GetDeviceCaps(device_context, VERTRES);
int LogicalScreenWidth = GetDeviceCaps(device_context, HORZRES);
int PhysicalScreenHeight = GetDeviceCaps(device_context, DESKTOPVERTRES);
int PhysicalScreenWidth = GetDeviceCaps(device_context, DESKTOPHORZRES);
pThis->monitors.push_back(
MonitorInfo(
std::string(monitor_info.szDevice),
Rectangular(
LogicalScreenHeight,
LogicalScreenWidth),
Rectangular(
PhysicalScreenHeight,
PhysicalScreenWidth),
Rectangular(
GetDeviceCaps(device_context, VERTSIZE),
GetDeviceCaps(device_context, HORZSIZE))));
return TRUE;
}
Rectangular MonitorsInformation::get_monitors_rectangular() const
{
return Rectangular(
std::abs(rectangular_combined.top) + std::abs(rectangular_combined.bottom),
std::abs(rectangular_combined.left) + std::abs(rectangular_combined.right));
}
int main()
{
SetProcessDPIAware();
for (;;)
{
MonitorsInformation MonitorsInfo;
char exit_char = 'N';
std::cout << "You have " << MonitorsInfo.get_monitors_info().size() << " monitors connected.\n";
printf("Screen rectangular. %d x %d\n",
MonitorsInfo.get_monitors_rectangular().width, MonitorsInfo.get_monitors_rectangular().height);
for (auto &monitor : MonitorsInfo.get_monitors_info())
{
monitor.print_to_stdout();
}
std::cout << "Would you like to repeat? [Y]/[N]\n";
std::cin >> exit_char;
if (exit_char == 'N' || exit_char == 'n')
{
break;
}
}
return 0;
}
#包括“stdafx.h”
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类矩形
{
公众:
矩形(整数高度,整数宽度):高度(高度),宽度(宽度){};
常数int高度;
常数整数宽度;
};
类监视器信息
{
公众:
MonitorInfo(标准::字符串设备名称、矩形逻辑分辨率、矩形物理分辨率、矩形物理大小\u mm):
设备名称(设备名称)、逻辑分辨率(逻辑分辨率)、物理分辨率(物理分辨率),
物理大小mm(物理大小mm),缩放(静态转换(标准:圆形(100.0*(浮点)物理分辨率高度/(浮点)逻辑分辨率高度)){};
无效打印到stdout()常量;
const std::字符串设备名称;
常数矩形逻辑分辨率;
常数矩形物理分辨率;
常数矩形物理尺寸mm;
常数整型;
};
类监视器信息
{
公众:
监视器信息();
const std::vector&get_monitors_info()const{return monitors;}
std::string get_last_error_string()常量{return last_error;}
矩形get_监视器_矩形()常数;
私人:
矩形组合;
std::向量监视器;
std::字符串最后一个错误;
静态BOOL回调MonitorEnum(HMONITOR hMon、HDC HDC、LPRECT lprcMonitor、LPARAM pData);
};
void MonitorInfo::打印到常量
{
std::cout@AlexanderZinovyev感谢您的进一步解释,我可以复制您的问题,将比例因子保持在150%并关闭我的计算机
检查API文档后,我发现以下注释:
注意:GetDeviceCaps报告显示驱动程序提供的信息。
显示驱动程序拒绝报告任何信息,GetDeviceCaps
根据固定计算计算信息。如果显示驱动程序
报告无效信息,GetDeviceCaps返回无效信息。如果
显示驱动程序拒绝报告信息,GetDeviceCaps可能会
计算不正确的信息,因为它假设固定DPI(96 DPI)
或固定大小(取决于显示器驱动程序提供的信息和
没有提供。)不幸的是,实现了一个显示驱动程序
到Windows显示驱动程序型号(WDDM)(在Windows中引入
Vista)导致GDI无法获取信息,因此GetDeviceCaps必须始终
计算信息。
因此,GetDeviceCaps API的返回值似乎不能反映设备的真实价值。除非在更改DPI后重新启动(或至少注销),否则很多事情都会变得很奇怪。事实就是这样。我使用setProcessDPIaarEnesContext(DPI\u感知\u上下文\u不知道);
和setProcessDPIaarEnesContext设置DPI感知(DPI_AWARE_CONTEXT_SYSTEM_AWARE);
两者都无法再现您的问题。当比例因子增加时,HORZRES值始终会减小。(100%-1920;125%-1536;150%-1280;175%-1097)我没有重新启动。我在Windows 10 Enterprise Desktop上进行测试。@RitaHan MSFT,感谢您的输入。是的,如果我将比例因子从默认值100%增加到例如150%,我可以看到相同的行为。在这种情况下,我看到HORZRES变小了(正如我预期的那样)。当我将比例因子保持在150%并关闭计算机时,我的问题就发生了。