如何从 Winapi(C 或 C++ 语言)检测当前屏幕分辨率?
一些背景:
我想启动一个新的 OpenGL 全屏窗口,但希望它以桌面已设置的相同水平和垂直尺寸打开。 (现在当每个人都使用 LCD 屏幕时,我认为这是获得屏幕原始分辨率的最佳方法。)
我并不迫切需要知道桌面颜色深度,尽管这将是一个不错的奖励。
GetSystemMetrics
SM_CXSCREEN
/ SM_CYSCREEN
(也可以使用GetDeviceCaps
)GetSystemMetrics
SM_CX/YVIRTUALSCREENSystemParametersInfo
SPI_GETWORKAREA
GetMonitorInfo
编辑: 重要的是要记住,监视器并不总是从 0x0“开始”,因此仅知道大小不足以定位窗口。您可以使用
MonitorFromWindow
查找窗口所在的监视器,然后调用 GetMonitorInfo
如果你想走低级路线或改变分辨率,你需要使用
EnumDisplayDevices
,EnumDisplaySettings
和ChangeDisplaySettings
(这是获得刷新率AFAIK的唯一方法,但GetDeviceCaps
会告诉你颜色深度)
当系统使用DPI虚拟化(Vista及以上)时,使用GetSystemMetrics或GetWindowRect将无法获取真实屏幕分辨率(您将获得虚拟分辨率),除非您创建了DPI Aware应用程序。
因此,这里最好的选择(简单且向后兼容)是将 EnumDisplaySettings 与 ENUM_CURRENT_SETTINGS 一起使用。
它是 GetSystemMetrics,具有以下参数:
SM_CXSCREEN < width
SM_CYSCREEN < height
正如它所说(SM_CXSCREEN):
主屏幕宽度 显示监视器,以像素为单位。这是 通过调用获得相同的值 获取DeviceCaps如下: GetDeviceCaps( hdcPrimaryMonitor, 霍兹雷斯)。
我使用 GetSystemMetrics 函数
GetSystemMetrics(SM_CXSCREEN) 返回屏幕宽度(以像素为单位)
GetSystemMetrics(SM_CYSCREEN) - 高度(以像素为单位)
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724385%28v=vs.85%29.aspx
我认为SystemParametersInfo可能有用。
编辑:也请查看 GetMonitorInfo。
MFC 示例使用 GetSystemMetrics EnumDisplayMonitors 和 GetMonitorInfo 支持多显示器
点击此链接:使用源代码监控枚举
大约一周前删除,然后于 3-4-13 进行编辑。
对于用户决定这样做的情况,这是一个很好的选择 以较低的分辨率(坏主意)或角落运行桌面 某人决定购买一台显示器的情况 图形控制器无法充分利用:
// get actual size of desktop
RECT actualDesktop;
GetWindowRect(GetDesktopWindow(), &actualDesktop);
void GetMonitorRealResolution(HMONITOR monitor, int* pixelsWidth, int* pixelsHeight)
{
MONITORINFOEX info = { sizeof(MONITORINFOEX) };
winrt::check_bool(GetMonitorInfo(monitor, &info));
DEVMODE devmode = {};
devmode.dmSize = sizeof(DEVMODE);
winrt::check_bool(EnumDisplaySettings(info.szDevice, ENUM_CURRENT_SETTINGS, &devmode));
*pixelsWidth = devmode.dmPelsWidth;
*pixelsHeight = devmode.dmPelsHeight;
}
在任何情况下它都会返回原始分辨率,即使操作系统由于进程的 DPI 意识而试图对您撒谎。
float GetMonitorScalingRatio(HMONITOR monitor)
{
MONITORINFOEX info = { sizeof(MONITORINFOEX) };
winrt::check_bool(GetMonitorInfo(monitor, &info));
DEVMODE devmode = {};
devmode.dmSize = sizeof(DEVMODE);
winrt::check_bool(EnumDisplaySettings(info.szDevice, ENUM_CURRENT_SETTINGS, &devmode));
return (info.rcMonitor.right - info.rcMonitor.left) / static_cast<float>(devmode.dmPelsWidth);
}
这将为您提供给定显示器的实际分辨率相对于虚拟分辨率的比率。
如果主显示器的主 DPI 为 225%,第二个显示器的主 DPI 为 100%,并且您为第二个显示器运行此函数,您将得到 2.25。因为显示器的
2.25 * real resolution
= the virtual resolution
。
如果第二个显示器的缩放比例为 125%(而主显示器的缩放比例仍为 225%),那么此函数将返回您
1.79999995
,因为 125% 相对于 225% 就是这个值 (225/125 = 1.8),然后再次- 1.8*真实分辨率=
虚拟分辨率125%`
假设显示器 A 的 DPI 为 225%,显示器 B 的 DPI 为 125%,正如我上面所说,第二个显示器不会获得 1.25(如果您在第二个显示器上运行该函数。您将获得 1.8,因为我说)。
要克服这个问题,请使用此功能:
float GetRealDpiForMonitor(HMONITOR monitor)
{
return GetDpiForSystem() / 96.0 / GetMonitorScalingRatio(monitor);
}
这个函数依赖于我上面写的上一个函数(您需要复制的函数
GetMonitorScalingRatio
)
这将为您提供正确的值