Álvaro García
Álvaro García

Reputation: 19396

How to get the resolution of the screen in which a user control is opened?

I wanted to know the resolution of the screen and I have read this question:Get and Set Screen Resolution

However, it seems this give the resolution of the primary screen, but I would like to know if there is some way to get the resolution of the screen in which is shown the window.

For example, I have to screens, the laptop screen and a monitor. The laptop has a resolution of 1366x768 and the monitor has a resolution of 1920x1080. The main screen is the monitor, and the screen of the laptop is the secondary screen.

I would like to have a simple application that it has a button, and I would like than when I click the button, it gives the resolution of the monitor in which I am seeing the window. If I drag the window to the other monitor, then it should give me the resolution of the other monitor.

Thanks.

Upvotes: 0

Views: 585

Answers (1)

emoacht
emoacht

Reputation: 3601

You can accomplish it by various ways but I like straightforward way using MonitorFromRect and GetMonitorInfo functions. Assuming you set proper app.manifest for Per-Monitor DPI, the following extension method will work to get screen Rect from a FrameworkElement.

Regarding the point jwdonahue raised, this method will return the Rect of screen which has the largest intersection with the specified FrameworkElement.

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;

public static class ScreenHelper
{
    public static Rect ToScreenRect(this FrameworkElement element) => GetMonitorRect(GetElementRect(element));

    private static Rect GetElementRect(FrameworkElement element)
    {
        var point = element.PointToScreen(new Point(0, 0));
        var dpi = VisualTreeHelper.GetDpi(element);
        return new Rect(point, new Size(element.ActualWidth * dpi.DpiScaleX, element.ActualHeight * dpi.DpiScaleY));
    }

    private static Rect GetMonitorRect(Rect elementRect)
    {
        RECT rect = elementRect;
        var monitorHandle = MonitorFromRect(ref rect, MONITOR_DEFAULTTONULL);
        if (monitorHandle != IntPtr.Zero)
        {
            var monitorInfo = new MONITORINFO { cbSize = (uint)Marshal.SizeOf<MONITORINFO>() };
            if (GetMonitorInfo(monitorHandle, ref monitorInfo))
            {
                return monitorInfo.rcMonitor;
            }
        }
        return Rect.Empty;
    }

    [DllImport("User32.dll")]
    private static extern IntPtr MonitorFromRect(ref RECT lprc, uint dwFlags);

    private const uint MONITOR_DEFAULTTONULL = 0x00000000;

    [DllImport("User32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);

    [StructLayout(LayoutKind.Sequential)]
    private struct MONITORINFO
    {
        public uint cbSize;
        public RECT rcMonitor;
        public RECT rcWork;
        public uint dwFlags;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;

        public static implicit operator Rect(RECT rect)
        {
            return new Rect(
                rect.left,
                rect.top,
                rect.right - rect.left,
                rect.bottom - rect.top);
        }

        public static implicit operator RECT(Rect rect)
        {
            return new RECT
            {
                left = (int)rect.X,
                top = (int)rect.Y,
                right = (int)rect.Right,
                bottom = (int)rect.Bottom
            };
        }
    }
}

Upvotes: 1

Related Questions