【问题标题】:How to detect the current screen resolution?如何检测当前的屏幕分辨率?
【发布时间】:2011-06-05 14:26:37
【问题描述】:

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

一些背景:

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

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

【问题讨论】:

  • 请确保您的代码能够以某种合理的方式处理多个监视器。
  • @In silico,什么是明智的做法?只在主显示器上开始游戏(这是一个小游戏)?
  • @Amigable Clark Kant:默认为主显示器,但允许用户在游戏内设置屏幕中设置特定显示器。也许还支持 mygame.exe /Monitor1 等如果您还支持窗口模式,请使用 MonitorFromWindow 知道如果他们切换回全屏,要恢复到哪里。
  • @Amigable Clark Kant:安德斯在什么对你的小游戏“明智”上一针见血。当我说“明智”时,我真正的意思是“适合您的应用程序的行为”。在电脑游戏的情况下,即使在多显示器环境中,我也应该能够正确配置显示器设置。
  • @计算机。但是你到底想要什么?这将是一款小型 2D 街机风格的游戏。如果您告诉我您对此类应用程序的期望,我可以在完成后向您发送第一个版本。 :)

标签: c++ c winapi api resolution


【解决方案1】:

我认为SystemParametersInfo 可能有用。

编辑:也看看GetMonitorInfo

【讨论】:

  • SystemParametersInfo 在您只想要“工作区”= portion of the screen not obscured by the system taskbar or by application desktop toolbars 时很有用 :)
【解决方案2】:

它是GetSystemMetrics,带有这些参数:
SM_CXSCREEN SM_CYSCREEN

正如它所说的(SM_CXSCREEN):

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

【讨论】:

  • 请注意,GetSystemMetrics 仅用于向后兼容 Windows 98 之前的版本(和多显示器)支持。您应该使用SM_CXVIRTUALSCREEN/SM_CYVIRTUALSCREEN 来获取用户整个屏幕。
【解决方案3】:
  • 主监视器的大小:GetSystemMetrics SM_CXSCREEN / SM_CYSCREEN(也可以使用 GetDeviceCaps)
  • 所有监视器的大小(组合):GetSystemMetrics SM_CX/YVIRTUALSCREEN
  • 主监视器上的工作区大小(屏幕不包括任务栏和其他停靠栏):SystemParametersInfo SPI_GETWORKAREA
  • 特定显示器的尺寸(工作区和“屏幕”):GetMonitorInfo

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

如果你想走低级路线或改变你需要使用 EnumDisplayDevices、EnumDisplaySettings 和 ChangeDisplaySettings 的分辨率(这是获得刷新率 AFAIK 的唯一方法,但 GetDeviceCaps 会告诉你颜色深度)

【讨论】:

  • 我刚刚测试过,GetDeviceCaps 确实可以在多监视器设置中工作,VERT/HORZRES 和 VREFRESH 似乎都可以工作,但我只能让 CreateDC 接受 "\\.\DISPLAY2" 样式字符串和不是 "\\.\DISPLAY2\Monitor0" 所以我不确定如果一个适配器有多个监视器会做什么,所以如果你从 EnumDisplayDevices 获得监视器列表,请坚持使用 EnumDisplaySettings...
  • 我不确定在全屏模式下使用 OpenGL 时这一切如何应用?诸如“开始”在 0x0 之类的东西,这仍然适用吗?
  • 可能不是,我说的是 windows,希望 OpenGL 将其抽象出来,您只需告诉它使用哪个监视器,其余的就交给它了
  • @user396483 ...虚拟屏幕
  • @CoryTrese:要定位窗口,您应该使用 GetMonitorInfo。如果您正在寻找低级信息,您也可以尝试 EnumDisplaySettings 和 ENUM_CURRENT_SETTINGS...
【解决方案4】:

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

点击此链接:Monitor enumeration with source code

【讨论】:

    【解决方案5】:

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

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

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

    【讨论】:

    • GetWindowRect(GetDesktopWindow) 完全错误。它将有意仅返回主监视器的矩形。 "GetWindowRect 或 GetClientRect 返回的桌面窗口的矩形总是等于主监视器的矩形,以与现有应用程序兼容。"
    【解决方案6】:

    我使用 GetSystemMetrics 函数

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

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

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

    【讨论】:

    【解决方案7】:

    当系统使用DPI virtualization(Vista 及以上)时,使用 GetSystemMetrics 或 GetWindowRect 将失败获取真实屏幕分辨率(您将获得虚拟分辨率),除非您创建了 DPI Aware Application

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 2012-02-15
      • 2017-12-13
      • 1970-01-01
      相关资源
      最近更新 更多