【问题标题】:WPF mutli-monitor problem - WindowStateWPF多显示器问题 - WindowState
【发布时间】:2009-12-23 15:15:58
【问题描述】:

一段时间以来,我一直试图让我的 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 中包含最大化的减速使监视器最大化到主监视器。

这是为什么?

【问题讨论】:

    标签: wpf multiple-monitors


    【解决方案1】:

    首先请注意,“最大化”的概念与单个监视器相关联,因此您不能真正在多个监视器上拥有最大化的窗口。当然,在 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,这样您就不会覆盖开始菜单等。

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

    【讨论】:

    • 好的,我将使用多个窗口来跨越多个监视器,因为我不能保证用户将拥有的监视器。另外,我认为您可以使用 System.Windows.Forms.Screens 命名空间来访问屏幕信息。干杯,米格
    • 是的,使用System.Windows.Forms.Screen类比直接调用native方法要好。
    【解决方案2】:

    如果您始终可以假设您的辅助显示器与主显示器具有相同的分辨率,您可以实现如下所示:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-04
      • 2016-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      相关资源
      最近更新 更多