Перемещение приложений между мониторами — C#

#c#

#c#

Вопрос:

У меня есть форма, на которую ссылаются как:

 MainForm= Form1;
 

но в другом методе того же класса; после обнаружения, что система имеет более 1 монитора:

 int screens = Screen.AllScreens.Length;
if (screens > 1)
{
    model.AddItem((CefMenuCommand)26504, "Switch Screen (Monitor)");
    model.AddSeparator();
}
 

Мне нужно переключаться между этими:

 Screen[] lsScreen = Screen.AllScreens;
Screen myScreen = Screen.FromControl(MainForm);

if(myScreen == lsScreen[1])
{
    MainForm.Location = lsScreen[0].WorkingArea.Location; // Primary Screen
    MainForm.Top = MainForm.Left = 0;
    MainForm.Width = lsScreen[0].WorkingArea.Width;
    MainForm.Height = lsScreen[0].WorkingArea.Height;
}
else
{
    MainForm.Location = lsScreen[1].WorkingArea.Location; // Secondary Screen
    MainForm.Width = lsScreen[1].WorkingArea.Width;
    MainForm.Height = lsScreen[1].WorkingArea.Height;
}
 

Обновить

это то, что показывает Visual Studio 2019:

введите описание изображения здесь

  1. работает частично правильно; поскольку я могу переместить приложение с основного экрана на дополнительный; проблема в том, что я не могу перейти с дополнительного экрана на основной (возврат); Мне кажется, что ошибка в последнем фрагменте кода, что я не могу определить, что этоесть.
  2. другим ограничением является то, что он работает только между двумя экранами; первичный и вторичный; Как я могу адаптировать свой код, чтобы улучшить его, чтобы он поддерживал неопределенное количество экранов…

Комментарии:

1. Требуется экстрасенсорная отладка. Возможно, этот метод вызывается более одного раза, обычная ошибка при подписке на событие. Установите точку останова.

2. метод вызывается только один раз. итак, добавьте эту строку кода (CefMenuCommand) 26504 «Переключить экран (монитор), который фактически запускает функцию.

3. @HansPassant Я думаю, что сравнение в IF неадекватно… if(myScreen == lsScreen[1])

Ответ №1:

Вот некоторый код из приложения, которое я написал, который динамически заполняет ContextMenuStrip всеми другими мониторами, на которые что-то может быть отправлено. Это может дать вам несколько идей о том, как подойти к этому:

 Private Sub ContextMenuStrip1_Opening(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles ContextMenuStrip1.Opening
    If Screen.AllScreens.Count > 1 Then
        SendToToolStripMenuItem.DropDownItems.Clear()
        SendToToolStripMenuItem.Visible = True
        Dim containingScreen As Screen = Screen.FromHandle(Me.Handle)
        For i As Integer = 0 To Screen.AllScreens.Count - 1
            Dim curScreen As Screen = Screen.AllScreens.ElementAt(i)
            If curScreen.DeviceName <> containingScreen.DeviceName Then
                Dim screenMenu As New ToolStripMenuItem(curScreen.DeviceName)
                screenMenu.Tag = i
                AddHandler screenMenu.Click, AddressOf ScreenMenu_Click
                SendToToolStripMenuItem.DropDownItems.Add(screenMenu)
            End If
        Next
    End If
End Sub

Private Sub ScreenMenu_Click(sender As Object, e As EventArgs)
    Dim screenMenu As ToolStripMenuItem = DirectCast(sender, ToolStripMenuItem)
    Dim index As Integer = screenMenu.Tag
    Me.SendToScreen(index)
End Sub

Public Sub SendToScreen(ByVal index As Integer)
    If index < 0 OrElse index > (Screen.AllScreens.Count - 1) Then
        index = 0
    End If

    Dim curScreen As Screen = Screen.FromHandle(Me.Handle)
    Dim destScreen As Screen = Screen.AllScreens.ElementAt(index)

    Dim ptF As New PointF((CDbl(Me.Location.X) - curScreen.Bounds.Left) / curScreen.Bounds.Width,
                          (CDbl(Me.Location.Y) - curScreen.Bounds.Top) / curScreen.Bounds.Height)
    Dim szF As New PointF(CDbl(Me.Width) / curScreen.Bounds.Width,
                          CDbl(Me.Height) / curScreen.Bounds.Height)

    Dim destPt As New Point(destScreen.Bounds.Left   ptF.X * destScreen.Bounds.Width,
                            destScreen.Bounds.Top   ptF.Y * destScreen.Bounds.Height)
    Dim destSz As New Size(destScreen.Bounds.Width * szF.X, destScreen.Bounds.Height * szF.Y)

    Me.Location = destPt
    Me.Size = destSz
End Sub
 

Вот как это выглядит, когда меню отображается в моей системе с тремя мониторами (иногда у меня подключено всего четыре, и тогда это тоже отлично работает):

введите описание изображения здесь

Комментарии:

1. Большое вам спасибо за ваш вклад, было бы неплохо воспользоваться преимуществами нескольких мониторов. Я вижу, что это не на C #, я сделаю реализацию, как только у меня будет время, так как мне нужно будет преобразовать код и убедиться, что все идет хорошо.

2. @idle-mind другая проблема, которую я вижу, заключается в том, что, как вы указываете, это делается через ContextMenuStrip; Мне также нужно адаптировать его для работы с CefMenu cefsharp …

3. Да, извините. Мой любимый язык VB.Net . Я тоже много работаю на C #, но этот конкретный проект является личным, поэтому я написал его на VB.

4. Я никогда не работал с «CefMenu cefsharp». Ключевые моменты в моем коде … Opening событие срабатывает до отображения меню. Именно там я перечисляю мониторы и добавляю подменю для каждого монитора, который не содержит мою форму. Номер индекса экрана сохраняется в .Tag свойстве подменю, чтобы его можно было использовать в Click случае и в конечном итоге SendToScreen() .

Ответ №2:

Решение первого вопроса:

замените это:

 if(myScreen == lsScreen[1])
 

с помощью этого:

 if(myScreen.DeviceName == lsScreen[1].DeviceName)
 

Ожидающее улучшения / Второй вопрос.