【问题标题】:How to get the Monitor Screen Resolution from a hWnd?如何从 hWnd 获取显示器屏幕分辨率?
【发布时间】:2010-01-28 16:46:00
【问题描述】:

如何从 hWnd 获取显示器屏幕分辨率?

我正在使用 hWnd,因为窗口可以位于多个监视器中的任何一个上。

即hWnd 上/左坐标位于屏幕分辨率为 800 x 600 的监视器上。

我用一种叫做 PL/B 的语言编程,它允许调用 Windows API。

可以使用哪些 Window API?

【问题讨论】:

    标签: winapi screen-resolution


    【解决方案1】:

    这是一个适合我的 C++ 代码示例:

    HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
    MONITORINFO info;
    info.cbSize = sizeof(MONITORINFO);
    GetMonitorInfo(monitor, &info);
    int monitor_width = info.rcMonitor.right - info.rcMonitor.left;
    int monitor_height = info.rcMonitor.bottom - info.rcMonitor.top;
    

    【讨论】:

      【解决方案2】:

      user32 函数MonitorFromWindow 允许您传入一个 hwnd,并返回一个句柄到它所在的监视器(或默认值 - 有关详细信息,请参阅链接的 MSDN 文章)。这样您就可以调用GetMonitorInfo 来检索MONITORINFO struct,其中包含详细说明其分辨率的RECT。

      有关详细信息,请参阅 MSDN 的 Multiple Screens Reference 部分。

      我会添加示例代码,但我不知道您引用的语言,也不知道 C# 示例代码对您有多大用处。如果您认为这会有所帮助,请告诉我,我会快速编写代码。

      【讨论】:

      • 非常感谢埃里克。我能够使用您提供的参考将其转换为 PL/B。
      • 太好了,我很高兴听到它。 =)
      【解决方案3】:

      还有GetSystemMetrics,在msdn上查看

      【讨论】:

      • 是的,但是在最终用户有多个监视器的情况下,使用 MonitorFromWindow 会更好。
      • @sidewinderguy 什么是 RECT rcWork;在 MONITORINFO 结构中表示?没有得到 MSDN 上“显示监视器的工作区域矩形”的含义
      【解决方案4】:

      这是一些通过 P/Invoke 获取分辨率(以 DPI 表示)的 C# 代码:

      public static void GetWindowDpi(IntPtr hwnd, out int dpiX, out int dpiY)
      {
          var handle = MonitorFromWindow(hwnd, MonitorFlag.MONITOR_DEFAULTTOPRIMARY);
      
          GetDpiForMonitor(handle, MonitorDpiType.MDT_EFFECTIVE_DPI, out dpiX, out dpiY);
      }
      
      /// <summary>
      /// Determines the function's return value if the window does not intersect any display monitor.
      /// </summary>
      [SuppressMessage("ReSharper", "IdentifierTypo")]
      [SuppressMessage("ReSharper", "UnusedMember.Local")]
      private enum MonitorFlag : uint
      {
          /// <summary>Returns NULL.</summary>
          MONITOR_DEFAULTTONULL = 0,
          /// <summary>Returns a handle to the primary display monitor.</summary>
          MONITOR_DEFAULTTOPRIMARY = 1,
          /// <summary>Returns a handle to the display monitor that is nearest to the window.</summary>
          MONITOR_DEFAULTTONEAREST = 2
      }
      
      [DllImport("user32.dll")]
      private static extern IntPtr MonitorFromWindow(IntPtr hwnd, MonitorFlag flag);
      
      [SuppressMessage("ReSharper", "IdentifierTypo")]
      [SuppressMessage("ReSharper", "UnusedMember.Local")]
      private enum MonitorDpiType
      {
          /// <summary>
          /// The effective DPI.
          /// This value should be used when determining the correct scale factor for scaling UI elements.
          /// This incorporates the scale factor set by the user for this specific display.
          /// </summary>
          MDT_EFFECTIVE_DPI = 0,
          /// <summary>
          /// The angular DPI.
          /// This DPI ensures rendering at a compliant angular resolution on the screen.
          /// This does not include the scale factor set by the user for this specific display.
          /// </summary>
          MDT_ANGULAR_DPI = 1,
          /// <summary>
          /// The raw DPI.
          /// This value is the linear DPI of the screen as measured on the screen itself.
          /// Use this value when you want to read the pixel density and not the recommended scaling setting.
          /// This does not include the scale factor set by the user for this specific display and is not guaranteed to be a supported DPI value.
          /// </summary>
          MDT_RAW_DPI = 2
      }
      
      [DllImport("user32.dll")]
      private static extern bool GetDpiForMonitor(IntPtr hwnd, MonitorDpiType dpiType, out int dpiX, out int dpiY);
      

      【讨论】:

      • 这不再适用于较新的系统,因为在 Windows 8.1 之前都支持 GetDpiForMonitor 方法
      • @Filipsi 你确定吗?编写此代码时,我使用的是 Windows 10。
      【解决方案5】:

      适用于高分辨率 2K 4K > 1920px 的显示器

      void GetDesktopResolution(int* horizontal, int* vertical)
      {
      
          HDC hScreenDC = GetDC(GetDesktopWindow());
          int width = GetDeviceCaps(hScreenDC, HORZRES);
          int height = GetDeviceCaps(hScreenDC, VERTRES);
          ReleaseDC(GetDesktopWindow(), hScreenDC);
      
          RECT desktop;
          const HWND hDesktop = GetDesktopWindow();
          GetWindowRect(hDesktop, &desktop);
          
          if (width > 2000)
          {
              const POINT ptZero = { 0, 0 };
              HMONITOR mon = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
      
              DEVICE_SCALE_FACTOR f;// vers < win 8 = GetScaleFactorForDevice(DEVICE_PRIMARY);
              GetScaleFactorForMonitor(mon,&f);
              if (f > 110)
              {
                  *horizontal = width * ((f+10) / 100.0);
                  *vertical = height * ((f+10) / 100.0);
              }
              else
              {
                  *horizontal = width;
                  *vertical = height;
              }
          }
          else
          {
              *horizontal = desktop.right;
              *vertical = desktop.bottom;
          }
      }
      

      【讨论】:

        【解决方案6】:
        RECT windowsize;    // get the height and width of the screen
        GetClientRect(hwnd, &windowsize);
        
        int srcheight = windowsize.bottom;
        int srcwidth = windowsize.right;
        

        【讨论】:

        • 这是窗口大小,不是屏幕大小。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多