我在 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/