首页 > 解决方案 > 如何获取打开用户控件的屏幕分辨率?

问题描述

我想知道屏幕的分辨率,我读过这个问题:获取和设置屏幕分辨率

但是,这似乎给出了主屏幕的分辨率,但我想知道是否有某种方法可以获得显示窗口的屏幕的分辨率。

例如,我要屏幕、笔记本电脑屏幕和显示器。笔记本电脑的分辨率为 1366x768,显示器的分辨率为 1920x1080。主屏幕是显示器,笔记本电脑的屏幕是副屏幕。

我想要一个简单的应用程序,它有一个按钮,我希望当我单击按钮时,它会给出我看到窗口的显示器的分辨率。如果我将窗口拖到另一台显示器,那么它应该给我另一台显示器的分辨率。

谢谢。

标签: c#wpf

解决方案


您可以通过多种方式完成它,但我喜欢使用 MonitorFromRect 和 GetMonitorInfo 函数的直接方式。假设您为 Per-Monitor DPI 设置了正确的 app.manifest,以下扩展方法将用于从 FrameworkElement 获取屏幕 Rect。

关于 jwdonahue 提出的点,此方法将返回与指定 FrameworkElement 有最大交集的屏幕的 Rect。

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

推荐阅读