如何检测当前屏幕分辨率?

问题描述 投票:0回答:8

如何从 Winapi(C 或 C++ 语言)检测当前屏幕分辨率?

一些背景:

我想启动一个新的 OpenGL 全屏窗口,但希望它以桌面已设置的相同水平和垂直尺寸打开。 (现在当每个人都使用 LCD 屏幕时,我认为这是获得屏幕原始分辨率的最佳方法。)

我并不迫切需要知道桌面颜色深度,尽管这将是一个不错的奖励。

c++ c winapi api resolution
8个回答
88
投票
  • 主显示器尺寸:
    GetSystemMetrics
    SM_CXSCREEN
    /
    SM_CYSCREEN
    (也可以使用
    GetDeviceCaps
  • 所有显示器的大小(组合):
    GetSystemMetrics
    SM_CX/YVIRTUALSCREEN
  • 主显示器上工作区域的大小(不包括任务栏和其他停靠栏的屏幕):
    SystemParametersInfo
    SPI_GETWORKAREA
  • 特定显示器的尺寸(工作区域和“屏幕”):
    GetMonitorInfo

编辑: 重要的是要记住,监视器并不总是从 0x0“开始”,因此仅知道大小不足以定位窗口。您可以使用

MonitorFromWindow
查找窗口所在的监视器,然后调用
GetMonitorInfo

如果你想走低级路线或改变分辨率,你需要使用

EnumDisplayDevices
EnumDisplaySettings
ChangeDisplaySettings
(这是获得刷新率AFAIK的唯一方法,但
GetDeviceCaps
会告诉你颜色深度)


13
投票

当系统使用DPI虚拟化(Vista及以上)时,使用GetSystemMetrics或GetWindowRect将无法获取真实屏幕分辨率(您将获得虚拟分辨率),除非您创建了DPI Aware应用程序

因此,这里最好的选择(简单且向后兼容)是将 EnumDisplaySettings 与 ENUM_CURRENT_SETTINGS 一起使用。


8
投票

它是 GetSystemMetrics,具有以下参数:
SM_CXSCREEN < width
SM_CYSCREEN < height

正如它所说(SM_CXSCREEN):

主屏幕宽度 显示监视器,以像素为单位。这是 通过调用获得相同的值 获取DeviceCaps如下: GetDeviceCaps( hdcPrimaryMonitor, 霍兹雷斯)。


4
投票

我使用 GetSystemMetrics 函数

GetSystemMetrics(SM_CXSCREEN) 返回屏幕宽度(以像素为单位)

GetSystemMetrics(SM_CYSCREEN) - 高度(以像素为单位)

https://msdn.microsoft.com/en-us/library/windows/desktop/ms724385%28v=vs.85%29.aspx


3
投票

我认为SystemParametersInfo可能有用。

编辑:也请查看 GetMonitorInfo


3
投票

MFC 示例使用 GetSystemMetrics EnumDisplayMonitors 和 GetMonitorInfo 支持多显示器

点击此链接:使用源代码监控枚举


2
投票

大约一周前删除,然后于 3-4-13 进行编辑。

对于用户决定这样做的情况,这是一个很好的选择 以较低的分辨率(坏主意)或角落运行桌面 某人决定购买一台显示器的情况 图形控制器无法充分利用:

// get actual size of desktop
RECT actualDesktop;
GetWindowRect(GetDesktopWindow(), &actualDesktop);

2
投票

获得真实的显示器分辨率

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%`

获取真实的DPI值(不相对于任何东西)

假设显示器 A 的 DPI 为 225%,显示器 B 的 DPI 为 125%,正如我上面所说,第二个显示器不会获得 1.25(如果您在第二个显示器上运行该函数。您将获得 1.8,因为我说)。

要克服这个问题,请使用此功能:

float GetRealDpiForMonitor(HMONITOR monitor)
{
    return GetDpiForSystem() / 96.0 / GetMonitorScalingRatio(monitor);
}

这个函数依赖于我上面写的上一个函数(您需要复制的函数

GetMonitorScalingRatio

这将为您提供正确的值

© www.soinside.com 2019 - 2024. All rights reserved.