25

How to get the monitor screen resolution from a hWnd?

I am using a hWnd because the window could be located on any one of multiple monitors.

i.e. the hWnd top/left coordinate is on a Monitor that has a Screen Resolution of 800 x 600.

I program in a language called PL/B and it allows calling Windows API.

What Window APIs can be used?

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
Gerhard Weiss
  • 9,343
  • 18
  • 65
  • 67

6 Answers6

27

Here's a C++ code example that works for me:

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;
sidewinderguy
  • 2,394
  • 4
  • 24
  • 24
25

The user32 function MonitorFromWindow allows you to pass in an hwnd, and returns a handle to the monitor it's on (or a default - see the linked MSDN article for details). With that you can call GetMonitorInfo to retrieve a MONITORINFO struct which contains a RECT detailing its resolution.

See the Multiple Screens Reference section of MSDN for more details.

I'd add example code but I don't know the language you referenced, and I don't know how useful C# example code would be to you. If you think it'll help, let me know and I'll code up something real quick.

Filip Skakun
  • 31,624
  • 6
  • 74
  • 100
Erik Forbes
  • 35,357
  • 27
  • 98
  • 122
5

There is GetSystemMetrics too, check it out on msdn

marscom
  • 615
  • 2
  • 11
  • 24
  • 3
    True, however using MonitorFromWindow will work better in a situation where the end user has multiple monitors. – sidewinderguy Jun 01 '12 at 07:03
  • @sidewinderguy What does RECT rcWork; signifies in the MONITORINFO struct ? Not getting what it meant by "work area rectangle of the display monitor" on MSDN – proton Apr 08 '14 at 14:58
4

Here's some C# code that gets the resolution (in DPI) via P/Invoke:

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);
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
0

For Monitors with hight resolution 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;
    }
}
BeatEngine
  • 123
  • 7
-2
RECT windowsize;    // get the height and width of the screen
GetClientRect(hwnd, &windowsize);

int srcheight = windowsize.bottom;
int srcwidth = windowsize.right;
john k
  • 6,268
  • 4
  • 55
  • 59