代码之家  ›  专栏  ›  技术社区  ›  Hux

wpf mutli监视器问题-windowstate

  •  4
  • Hux  · 技术社区  · 15 年前

    我已经尝试让我的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;
        }
    }
    

    这个例子是可行的,但是窗口没有最大化,应用程序边框仍然可见。

    包括应用程序中的最大减速使监视器最大化到主监视器。

    为什么会这样?

    2 回复  |  直到 13 年前
        1
  •  11
  •   Ray Burns    15 年前

    首先要注意的是,“最大化”的概念是与一个监视器联系在一起的,因此您不能在多个监视器上真正拥有一个最大化的窗口。当然,在WPF中,您可以创建自己的窗口框架并在其中绘制您喜欢的任何内容,因此,如果您愿意,您当然可以让用户认为窗口是最大化的,跨越多个屏幕。

    还请注意,只有两种情况下,可以跨两个监视器,使用一个矩形窗口:

    1. 两个监视器具有相同的高度,并且配置为并排,或者
    2. 两个监视器的宽度相同,配置为高于和低于。

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

    好的,下面介绍如何获取定位窗口所需的信息:

    WPF本身不提供询问监视器计数、分辨率或相对位置的方法。幸运的是,我们可以使用[dllimport]直接调用win32。要获得监视器分辨率和布局,只需:

    1. 在C中将monitorinfo结构声明为结构#
    2. 声明EnumDisplayMonitors和GetMonitorinfo的dllimports,两者都在user32.dll中找到
    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,这样就不会覆盖开始菜单等。

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

        2
  •  -1
  •   Brent    15 年前

    如果可以始终假定辅助监视器与主监视器的分辨率相同,则可以实现如下内容:

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