WPF 多显示器问题 - 窗口状态

5

我一直在努力让我的WPF应用程序跨越多个监视器运行,现在我已经接近成功。

问题似乎出现在我设置以下代码行时:

win1.WindowState = WindowState.Maximized

这会导致应用程序只覆盖主屏幕。

我的代码如下:

public partial class App : Application
{
    private void Application_Startup(object sender, StartupEventArgs e)
    {
        Window1 win1 = new Window1();
        win1.WindowStartupLocation = WindowStartupLocation.Manual;
        win1.Width = 2560;
        win1.Height = 1024;
        win1.Left = 0;
        win1.Top = 0;
        win1.Topmost = true;
        win1.Background = new SolidColorBrush(Colors.Black);
        win1.WindowStyle = WindowStyle.None;
        win1.Show();
        win1.Focus();
    }
}

在窗口1内部:

public partial class Window1 : Window
{
    public Window1()
    {

    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        WindowState = WindowState.Maximized;
    }
}

这个例子可以运行,但窗口没有最大化,并且应用程序边框仍然可见。
在Application_Startup中包含最大化减速使监视器最大化到主监视器。
为什么会这样?
2个回答

13

首先需要注意的是,"最大化"的概念是针对单个监视器的,因此您不能真正在多个监视器上拥有一个最大化的窗口。当然,在WPF中,您可以创建自己的窗口框架并在其中绘制任何喜欢的内容,因此如果您愿意,您肯定可以让用户认为该窗口已经最大化并覆盖了多个屏幕。

还要注意的是,有两种情况下可以使用单个矩形窗口跨越两个监视器:

  1. 这两个监视器具有相同的高度,并且配置为并排放置;或
  2. 这两个监视器具有相同的宽度,并且配置为上下放置。

否则,您将需要使用两个单独的窗口来覆盖两个监视器的整个表面,或者使用一个包含任何监视器都未覆盖的区域的大型窗口。

好的,接下来是如何获取您需要定位窗口所需的信息:

WPF本身不提供一种方法来查询您的监视器数量、分辨率或相对位置。幸运的是,我们可以直接使用[ DllImport ]调用Win32。为了获取显示器的分辨率和布局,只需要:

  1. 在C#中将MONITORINFO结构声明为一个结构体
  2. 声明DllImport以便使用User32.dll中的EnumDisplayMonitors和GetMonitorInfo
  3. 编写一个方法调用EnumDisplayMonitors并传递一个获取监视器信息并将其返回到列表中的委托。

这是基本思路:

List<MONITORINFO> GetAllMonitorInfo()
{
  var result = List<MONITORINFO>();
  EnumDisplayMonitors(null, null,
    (hMonitor, hdcMonitor, lprcMonitor, dwData) =>
    {
      var info = new MONITORINFO { cbSize = Marshall.Sizeof(typeof(MONITORINFO)) };
      GetMonitorInfo(hMonitor, ref info);
      result.Add(info);
    }, null);
  return result;
}

获取到监视器的坐标后,使用您选择的算法来确定要创建多少个窗口以及每个窗口的坐标。然后,使用显式的大小和位置创建窗口。

请注意,您可能希望使用rcWork而不是rcMonitor,这样就不会覆盖开始菜单等内容。

还要注意,在许多情况下,返回的某些坐标将为负数,例如如果辅助监视器位于主监视器的左侧。这不是问题:只需按照给定的坐标使用即可,您的窗口将出现在正确的位置。


好的,我将使用多个窗口来跨越多个监视器,因为我无法保证用户会有哪些监视器。此外,我认为您可以使用System.Windows.Forms.Screens命名空间来访问屏幕信息。祝好, MiG - Hux
2
是的,最好使用System.Windows.Forms.Screen类而不是直接调用本机方法。 - Ray Burns

-1
如果您总是可以假设您的辅助显示器与主显示器具有相同的分辨率,那么您可以实现类似于以下的内容:
// Use this is you are concerned about the taskbar height
Rect workArea = SystemParameters.WorkArea;
this.Width = SystemParameters.PrimaryScreenWidth * 2;
this.Height = workArea.Bottom;
this.Left = 0;
this.Top = 0;

或者:

// Use this is you don't care about the taskbar height
this.Width = SystemParameters.PrimaryScreenWidth * 2;
this.Height = SystemParameters.PrimaryScreenHeight;
this.Left = 0;
this.Top = 0;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接