Проблема мутли-монитора в WPF - WindowState - PullRequest
4 голосов
/ 23 декабря 2009

Я уже некоторое время пытаюсь, чтобы мое приложение 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 ]

11 голосов
/ 24 декабря 2009

Во-первых, обратите внимание, что концепция «Maximized» привязана к одному монитору, поэтому вы не можете по-настоящему развернуть окно на нескольких мониторах. Конечно, в WPF вы можете создать свою собственную оконную раму и нарисовать в ней все, что вам нравится, поэтому, если вы хотите, вы, безусловно, можете заставить пользователя думать, что окно развернуто и охватывает несколько экранов.

Также обратите внимание, что два монитора можно объединить в одно прямоугольное окно только в двух случаях:

  1. Два монитора имеют одинаковую высоту и имеют конфигурацию, расположенную рядом, или
  2. Оба монитора имеют одинаковую ширину и могут быть расположены сверху и снизу.

В противном случае вам потребуется использовать два отдельных окна, чтобы покрыть все поверхности обоих мониторов, или использовать большое окно, включающее области, которые не покрыты каким-либо монитором.

Хорошо, вот как получить информацию, необходимую для позиционирования ваших окон:

Сам WPF не предоставляет способ узнать количество мониторов, разрешение или относительное положение. К счастью, мы можем вызвать Win32 напрямую, используя [DllImport]. Чтобы получить разрешение и раскладку монитора, просто:

  1. Объявите структуру MONITORINFO как структуру в C #
  2. Объявление DllImports для EnumDisplayMonitors и GetMonitorInfo, оба из которых находятся в 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, чтобы не перезаписывать меню "Пуск" и т. Д.

Также обратите внимание, что во многих случаях некоторые из возвращаемых координат будут отрицательными, например, если дополнительный монитор находится слева от основного монитора. Это не проблема: просто используйте координаты, как указано, и ваши окна появятся в правильных местах.

0 голосов
/ 24 декабря 2009

Если вы всегда можете предположить, что ваш дополнительный монитор имеет то же разрешение, что и основной, вы можете реализовать что-то вроде этого:

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