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

发布于 2024-10-10 14:54:46 字数 186 浏览 2 评论 0原文

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

一些背景:

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

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

How do I from Winapi (in C or C++) detect the current screen resolution?

Some background:

I want to start a new OpenGL fullscreen window, but want it open with the same horizontal and vertical size which the desktop already is set to. (Now when everyone uses LCD screens, I figured this is the best way to get the native resolution of the screen.)

I don't desperately need to also know the desktop color depth, although that would be a nice bonus.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

千柳 2024-10-17 14:54:46
  • 主显示器的大小:GetSystemMetrics< /code>SM_CXSCREEN / SM_CYSCREEN(也可以使用GetDeviceCaps
  • 所有监视器的大小(组合):GetSystemMetrics SM_CX/YVIRTUALSCREEN
  • 主显示器上工作区域的大小(不包括任务栏和其他停靠栏的屏幕): SystemParametersInfo SPI_GETWORKAREA
  • 特定监视器的大小(工作区域和“屏幕”):GetMonitorInfo

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

如果您想走低级路线或更改需要使用的分辨率 EnumDisplayDevicesEnumDisplaySettingsChangeDisplaySettings (这是获取刷新率 AFAIK 的唯一方法,但是 GetDeviceCaps 会告诉您颜色深度)

  • Size of the primary monitor: GetSystemMetrics SM_CXSCREEN / SM_CYSCREEN (GetDeviceCaps can also be used)
  • Size of all monitors (combined): GetSystemMetrics SM_CX/YVIRTUALSCREEN
  • Size of work area (screen excluding taskbar and other docked bars) on primary monitor: SystemParametersInfo SPI_GETWORKAREA
  • Size of a specific monitor (work area and "screen"): GetMonitorInfo

Edit:
It is important to remember that a monitor does not always "begin" at 0x0 so just knowing the size is not enough to position your window. You can use MonitorFromWindow to find the monitor your window is on and then call GetMonitorInfo

If you want to go the low-level route or change the resolution you need to use EnumDisplayDevices, EnumDisplaySettings and ChangeDisplaySettings (This is the only way to get the refresh rate AFAIK, but GetDeviceCaps will tell you the color depth)

忘羡 2024-10-17 14:54:46

当系统使用DPI虚拟化(Vista 及更高版本)使用 GetSystemMetrics 或 GetWindowRect 将无法获取真实屏幕分辨率(您将获得虚拟分辨率),除非您创建了 DPI 感知应用程序

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

When system use DPI virtualization (Vista and above) using GetSystemMetrics or GetWindowRect will fail to get the real screen resolution (you will get the virtual resolution) unless you created DPI Aware Application.

So the best option here (simple and backward compatible) is to use EnumDisplaySettings with ENUM_CURRENT_SETTINGS.

情何以堪。 2024-10-17 14:54:46

它是带有以下参数的 GetSystemMetrics
SM_CXSCREEN <宽度
SM_CYSCREEN <高度

正如它所说(SM_CXSCREEN):

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

It's GetSystemMetrics with these parameters:
SM_CXSCREEN < width
SM_CYSCREEN < height

As it says (SM_CXSCREEN):

The width of the screen of the primary
display monitor, in pixels. This is
the same value obtained by calling
GetDeviceCaps as follows:
GetDeviceCaps( hdcPrimaryMonitor,
HORZRES).

若沐 2024-10-17 14:54:46

我认为 SystemParametersInfo 可能有用。

编辑:也请查看 GetMonitorInfo

I think SystemParametersInfo might be useful.

Edit: Look at GetMonitorInfo too.

抚你发端 2024-10-17 14:54:46

MFC 示例 GetSystemMetrics EnumDisplayMonitors 和 GetMonitorInfo 的多监视器支持

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

MFC Example Multiple monitor support with GetSystemMetrics EnumDisplayMonitors and GetMonitorInfo

Follow this link: Monitor enumeration with source code

摇划花蜜的午后 2024-10-17 14:54:46

我使用 GetSystemMetrics 函数

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

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

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

I use the GetSystemMetrics function

GetSystemMetrics(SM_CXSCREEN) returns screen width(in pixels)

GetSystemMetrics(SM_CYSCREEN) - height in pixels

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

罗罗贝儿 2024-10-17 14:54:46

获得真实的显示器分辨率

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 * 真实分辨率 = 显示器的虚拟分辨率

如果第二个显示器的缩放比例为 125%(而主显示器的缩放比例仍为 225%),则此函数将返回 1.79999995,因为该值是相对于 225% 的 125% (225/125 = 1.8 ),然后再次 - 1.8 * 真实分辨率=125% 的虚拟分辨率`

获取真实 DPI 值(与任何值无关)

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

要克服这个问题,请使用此函数:

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

此函数取决于我上面编写的前一个函数(您需要复制的函数 GetMonitorScalingRatio

这将为您提供正确的值

To get real monitor resolution

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;
}

It will return that native resolution in any case, even if the OS tries to lie to you due to the DPI awareness of the process.

To get the scaling ratio between the virtual resolution and real resolution

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);
}

This will give you a ratio of the real resolution relative to the virtual resolution of the given monitor.

If the main DPI of the main monitor is 225% and on the second monitor it is 100%, and you run this function for the second monitor, you will get 2.25. because 2.25 * real resolution = the virtual resolution of the monitor.

If the second monitor has 125% scaling (while the main monitor is still 225% scaling), then this function will return you 1.79999995 because 125% relative to 225% is this value (225/125 = 1.8), and again - 1.8 * real resolution=the virtual resolution of 125%`

To get the real DPI value (not relative to anything)

Given that monitor, A has 225% DPI, and monitor B has 125% DPI, as I said above, you will not get 1.25 for the second monitor (if you run the function on the second monitor. You will get 1.8 as I said).

To overcome this, use this function:

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

This function depends on the previous function that I wrote above (the function GetMonitorScalingRatio that you need to copy)

This will give you the correct value

清醇 2024-10-17 14:54:46

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

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

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

Deleted about a week ago, then edited 3-4-13.

Here's a good one for situations where the user has decided to
run their desktop in a lower resolution (bad idea) or corner
cases where a person decided to get a monitor that their
graphics controller couldn't take full advantage of:

// get actual size of desktop
RECT actualDesktop;
GetWindowRect(GetDesktopWindow(), &actualDesktop);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文