簡體   English   中英

WPF:多監視器編程

[英]WPF: multi monitor programming

我在C#使用WPF

我想從多顯示器編程開始,這意味着應用程序將在具有不同視圖的許多顯示器上顯示。

我在互聯網上搜索過,我有使用Screen.AllScreens[] ,但我有以下問題

有許多方法可以將許多顯示器連接到PC

案例1:在筆記本電腦中:1個筆記本電腦的屏幕,1個屏幕連接到VGA端口,1個屏幕連接到HDMI端口...

案例2:桌面:許多屏幕連接到支持多輸出的VGA卡

案例3:許多屏幕連接到集線器HDMI或集線器VGA,集線器連接到PC

我的問題是, Screen.AllScreens[]支持哪種情況?

還有其他任何方式,支持所有案例?

非常感謝你!

Screens.AllScreens[]是一個WinForms方法,如果我沒有弄錯,但是這支持你所有的情況(據我所知)。 如果我沒記錯的話,那個WinForms方法在應用程序啟動時初始化了靜態屬性,如果在運行時更改了屏幕,它就不會更新。

在處理WPF時,我會完全避免使用WinForms。 而是編寫自己的Screens包裝器來調用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;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM