Переход на полноэкранный режим на дополнительном мониторе
Как вы можете запрограммировать приложение dotNet для Windows (или WPF), чтобы оно работало на дополнительном мониторе в полноэкранном режиме?
8 ответов
Метод расширения для максимизации окна до вторичного монитора (если он есть). Не предполагает, что вторичным монитором является System.Windows.Forms.Screen.AllScreens[2];
using System.Linq;
using System.Windows;
namespace ExtendedControls
{
static public class WindowExt
{
// NB : Best to call this function from the windows Loaded event or after showing the window
// (otherwise window is just positioned to fill the secondary monitor rather than being maximised).
public static void MaximizeToSecondaryMonitor(this Window window)
{
var secondaryScreen = System.Windows.Forms.Screen.AllScreens.Where(s => !s.Primary).FirstOrDefault();
if (secondaryScreen != null)
{
if (!window.IsLoaded)
window.WindowStartupLocation = WindowStartupLocation.Manual;
var workingArea = secondaryScreen.WorkingArea;
window.Left = workingArea.Left;
window.Top = workingArea.Top;
window.Width = workingArea.Width;
window.Height = workingArea.Height;
// If window isn't loaded then maxmizing will result in the window displaying on the primary monitor
if ( window.IsLoaded )
window.WindowState = WindowState.Maximized;
}
}
}
}
Для приложений WPF посмотрите этот пост. В конечном итоге это зависит от того, когда для WindowState установлено значение Maximized. Если вы установите его в XAML или в конструкторе окна (то есть до загрузки окна), оно всегда будет развернуто на основном экране. Если, с другой стороны, вы установите WindowState в значение Maximized при загрузке окна - оно развернется на экране, на котором оно было развернуто ранее.
Я замечаю ответ, который рекомендует установить позицию в событии Loaded, но это вызывает мерцание, когда окно сначала отображается нормально, а затем развернуто. Если вы подпишитесь на событие SourceInitialized в своем конструкторе и установите в нем положение, оно будет обрабатывать максимизацию на вторичных мониторах без мерцания - я предполагаю, что WPF здесь
public MyWindow()
{
SourceInitialized += MyWindow_SourceInitialized;
}
void MyWindow_SourceInitialized(object sender, EventArgs e)
{
Left = 100;
Top = 50;
Width = 800;
Height = 600;
WindowState = WindowState.Maximized;
}
Замените координаты на любой на вашем дополнительном мониторе
Смотрите эту статью codeproject.
Код там будет работать, но по умолчанию ваш основной монитор. Чтобы изменить это, вам нужно заменить вызовы GetSystemMetrics на вызовы GetMonitorInfo. Используя GetMonitorInfo, вы можете получить соответствующий RECT для передачи в SetWindowPos.
GetMonitorInfo позволяет получить RECT для любого монитора.
Есть статья MSDN о приложениях определения местоположения в настройках нескольких мониторов, которые могут помочь объяснить вещи немного лучше.
private void Form1_Load(object sender, EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.None;
this.Bounds = GetSecondaryScreen().Bounds;
}
private Screen GetSecondaryScreen()
{
foreach (Screen screen in Screen.AllScreens)
{
if (screen != Screen.PrimaryScreen)
return screen;
}
return Screen.PrimaryScreen;
}
Ответ @jay-evans помог мне. Однако мне также нужно было добавить пакет WpfscreenHelper Nuget, чтобы получить информацию об экране, не завися от старого пространства имен System.Windows.Forms, как в ответе @grantnz.
Также обратите внимание, что установка только размеров (слева, сверху, ширина + высота) оставила меня с небольшой рамкой с каждой стороны. Только после установки WindowState.Maximized достигается настоящий полноэкранный эффект.
Так как у меня есть мониторы с разной конфигурацией DPI, мне также пришлось использовать WpfWorkingArea вместо WorkingArea, так как координаты возвращались неправильно.
Публикация здесь для полноты, это использует WPF с .NET 7.0 и подтверждено, что он работает с различными конфигурациями DPI:
public MainWindow()
{
InitializeComponent();
SourceInitialized += MainWindow_SourceInitialized;
}
private void MainWindow_SourceInitialized(object? sender, EventArgs e)
{
var screen = WpfScreenHelper.Screen.AllScreens.FirstOrDefault(s => !s.Primary);
if (screen != null)
{
this.WindowState = WindowState.Normal;
this.Left = screen.WpfWorkingArea.Left;
this.Top = screen.WpfWorkingArea.Top;
this.Width = screen.WpfWorkingArea.Width;
this.Height = screen.WpfWorkingArea.Height;
this.WindowState = WindowState.Maximized;
}
}
Из вашего вопроса не ясно, ищите ли вы способ переместить окно на дополнительный монитор и затем перейти на полноэкранный режим, или вы просто хотите поддерживать полноэкранный режим на любом мониторе, на котором установлено окно (который может быть основным или дополнительным).).
Если позднее, для окна WPF, хотя и не совсем так же, как в полноэкранном режиме, вы можете удалить границы, когда оно развернуто, и восстановить границы, когда оно не развернуто. Не нужно проверять, для какого монитора и т. Д. Отображение заголовка / строки заголовка контролируется состоянием границы.
protected override void OnStateChanged(EventArgs e)
{
if (WindowState == WindowState.Maximized)
{
if (WindowStyle.None != WindowStyle)
WindowStyle = WindowStyle.None;
}
else if (WindowStyle != WindowStyle.SingleBorderWindow)
WindowStyle = WindowStyle.SingleBorderWindow;
base.OnStateChanged(e);
}
Благодарим Павла за ответ на основе форм в текущем вопросе и Нира за ответ в этом вопросе.
В WPF: установите свойство WindowState в Normal (не Maximixed) и создайте событие Loaded. В случае написать этот код:
this.Left = SystemParameters.PrimaryScreenWidth + 100;
this.WindowState = System.Windows.WindowState.Maximized;