c# - WPF:多显示器编程

标签 c# wpf multiple-monitors

我在 C# 中使用 WPF

我想从多显示器编程开始,这意味着该应用程序将以不同的 View 显示在多个显示器上。

我在网上搜索过,找到了使用Screen.AllScreens[]的方法,但是我有以下问题

有很多方法可以将多个显示器连接到 PC

案例 1:在笔记本电脑中:1 台笔记本电脑的屏幕,1 台屏幕连接到 VGA 端口,1 台屏幕连接到 HDMI 端口...

案例2:在桌面上:许多屏幕连接到支持多路输出的VGA卡

案例三:多屏连接Hub HDMI或Hub VGA,Hub连接PC

我的问题是,Screen.AllScreens[] 支持哪种情况?

还有其他方法,支持所有大小写吗?

非常感谢!

最佳答案

Screens.AllScreens[] 是一个 WinForms 方法,如果我没记错的话,但是是的,它支持您的所有情况(据我所知)。如果我没记错的话,WinForms 方法会在应用程序启动时初始化静态属性,如果屏幕在运行时发生更改,它不会更新。

当您处理 WPF 时,我会完全避免使用 WinForms。而是编写您自己的 Screens 包装器来 p/调用 Win32 API。此外,连接一个事件处理程序以在显示设置更改时通知您,例如:

Microsoft.Win32.SystemEvents.DisplaySettingsChanged += new EventHandler(this.SystemEvents_DisplaySettingsChanged);

这是我使用的包装器:

/// <summary>
/// This class deals with monitors.
/// </summary>
internal static class Monitors
{
    private static List<Monitors.Screen> Screens = null;

    internal static List<Monitors.Screen> GetScreens()
    {
        Monitors.Screens = new List<Monitors.Screen>();

        var handler = new NativeMethods.DisplayDevicesMethods.EnumMonitorsDelegate(Monitors.MonitorEnumProc);
        NativeMethods.DisplayDevicesMethods.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, handler, IntPtr.Zero); // should be sequential

        return Monitors.Screens;
    }

    private static bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, NativeMethods.DisplayDevicesMethods.RECT rect, IntPtr dwData)
    {
        NativeMethods.DisplayDevicesMethods.MONITORINFO mi = new NativeMethods.DisplayDevicesMethods.MONITORINFO();

        if (NativeMethods.DisplayDevicesMethods.GetMonitorInfo(hMonitor, mi))
        {
            Monitors.Screens.Add(new Monitors.Screen(
                (mi.dwFlags & 1) == 1, // 1 = primary monitor
                mi.rcMonitor.Left, 
                mi.rcMonitor.Top, 
                Math.Abs(mi.rcMonitor.Right - mi.rcMonitor.Left), 
                Math.Abs(mi.rcMonitor.Bottom - mi.rcMonitor.Top)));
        }

        return true;
    }

    /// <summary>
    /// Represents a display device on a single system.
    /// </summary>
    internal sealed class Screen
    {
        /// <summary>
        /// Initializes a new instance of the Screen class.
        /// </summary>
        /// <param name="primary">A value indicating whether the display is the primary screen.</param>
        /// <param name="x">The display's top corner X value.</param>
        /// <param name="y">The display's top corner Y value.</param>
        /// <param name="w">The width of the display.</param>
        /// <param name="h">The height of the display.</param>
        internal Screen(bool primary, int x, int y, int w, int h)
        {
            this.IsPrimary = primary;
            this.TopX = x;
            this.TopY = y;
            this.Width = w;
            this.Height = h;
        }

        /// <summary>
        /// Gets a value indicating whether the display device is the primary monitor.
        /// </summary>
        internal bool IsPrimary { get; private set; }

        /// <summary>
        /// Gets the display's top corner X value.
        /// </summary>
        internal int TopX { get; private set; }

        /// <summary>
        /// Gets the display's top corner Y value.
        /// </summary>
        internal int TopY { get; private set; }

        /// <summary>
        /// Gets the width of the display.
        /// </summary>
        internal int Width { get; private set; }

        /// <summary>
        /// Gets the height of the display.
        /// </summary>
        internal int Height { get; private set; }
    }
}

internal static class NativeMethods
{
    /// <summary>
    /// Methods for retrieving display devices.
    /// </summary>
    internal static class DisplayDevicesMethods
    {
        internal delegate bool EnumMonitorsDelegate(IntPtr hMonitor, IntPtr hdcMonitor, NativeMethods.DisplayDevicesMethods.RECT rect, IntPtr dwData);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, EnumMonitorsDelegate lpfnEnum, IntPtr dwData);

        /// <summary>
        /// Retrieves information about a display monitor.
        /// </summary>
        /// <param name="hmonitor">A handle to the display monitor of interest.</param>
        /// <param name="info">A pointer to a MONITORINFO or MONITORINFOEX structure that receives information about the specified display monitor.</param>
        /// <returns>If the function succeeds, the return value is nonzero.</returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetMonitorInfo(IntPtr hmonitor, [In, Out] NativeMethods.DisplayDevicesMethods.MONITORINFO info);

        /// <summary>
        /// The RECT structure defines the coordinates of the upper-left and lower-right corners of a rectangle.
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        internal struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        /// <summary>
        /// The MONITORINFO structure contains information about a display monitor.
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
        internal class MONITORINFO
        {
            internal int cbSize = Marshal.SizeOf(typeof(NativeMethods.DisplayDevicesMethods.MONITORINFO));
            internal NativeMethods.DisplayDevicesMethods.RECT rcMonitor = new NativeMethods.DisplayDevicesMethods.RECT();
            internal NativeMethods.DisplayDevicesMethods.RECT rcWork = new NativeMethods.DisplayDevicesMethods.RECT();
            internal int dwFlags;
        }
    }
}

关于c# - WPF:多显示器编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34090565/

相关文章:

c# - 任务 IsCanceled 是假的,而我取消了

c# - 基于对象集合的动态ContextMenu的模式/方法

c# - 从程序集中加载 ResourceDictionary

C# 字节流通过 TCP

c# - 无法通过 HTTP 响应从文件下载创建 DotNetZip ZipFile

c# - 如何检查窗口在用户屏幕上是否完全可见?

c# - PointToScreen 多个显示器

c# - .NET 中显示数量发生变化时的事件?

C# + 信息权限管理

wpf - wpf 应用程序中的多个 Storyboard