Обнаружение doubleClick на mdiContainer без дочернего элемента (c # winforms) - PullRequest
1 голос
/ 01 марта 2010

У меня есть Form, что mdiContainer. Когда у формы нет дочернего элемента, я хочу перехватить событие doubleClick, когда пользователь дважды щелкает clientArea (такое же поведение, как в Photoshop).

Но когда я устанавливаю событие doubleClick, ничего не происходит. Как мне этого добиться?

Ответы [ 2 ]

1 голос
/ 02 марта 2010

Вот ответ, который включает в себя «обход» с помощью Panel и стратегию скрытия и отображения объекта MdiClient главной формы приложения MDI.

Когда все дочерние окна MDI закрыты, Panel будетзаполните область клиента MDI и обработайте события мыши.Если вы установите свойство BackColor панели в соответствии с цветом фона клиентской области MDI по умолчанию (как это описано ниже), вы сможете добиться «бесшовного» визуального перехода ... хотя: возможно, вы захотите изменить цвет какдоступна продуманная стратегия, позволяющая пользователю узнать двойной щелчок или любое другое событие мыши, которое вы хотите обработать.

Хотя вы можете заставить это работать, как показано в этом примере, я призываю вас подуматьо том, действительно ли эта функция «действительно стоит».

Я не оценил разумное предложение Gareth S., приведенное выше, чтобы решить эту проблему с помощью переключения свойства IsMdiContainer в главной форме MDI по простой причине, по которой ябоюсь, что это может потребовать повторного создания сложных оконных конфигураций, и побочный эффект установки 'IsMdiContainer в значение false в форме, где для свойства' IsMdiContainer установлено значение true '- это удаление элемента управления MdiClient из коллекции элементов управления формы.будет какой-то хитрый побочный эффектЭто может сказаться на этом, но я могу быть совершенно неправ.

Мне удобнее работать со стратегией, которая скрывает и показывает объект MdiClient, а не тот, который удаляет его как побочный эффект установки свойства, и которыйзатем потребуйте, чтобы вы снова добавили его в коллекцию элементов управления основной формы MDI, чтобы использовать его снова.Вы можете сделать другой выбор.

Я не буду вдаваться в подробности о том, как обрабатывается объект MdiClient, а расскажу, как обойти его отсутствие обработки определенных событий мыши.

Допущения:

  1. Вы определили «вторичную» форму с именем «Form2», которая будет использоваться для всех дочерних окон основной формы MDI.

Код:

  1. Добавьте панель в основную форму MDI: установите для ее DockStyle значение 'Fill;установите его BackColor для использования System 'AppWorkspace Color для фона, чтобы соответствовать настройкам цветовых предпочтений компьютера пользователя (это то, что использует BackColor по умолчанию MdiClient).Напишите обработчики событий на этой панели для 'DoubleClick или' MouseDoubleClick, в зависимости от ваших предпочтений.

  2. В вашей основной форме MDI: объявите переменную области видимости Form для хранения ссылки на объект MdiClient.

    private MdiClient theMdiClient;
    

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

    Form2 f2 = new Form2();
    Form2 f3 = new Form2();
    Form2 f4 = new Form2();
    Form2 f5 = new Form2();
    
  3. Основное событие загрузки формы MDI: Нам нужнополучить ссылку на объект MdiClient: если вы знаете, что у вас есть только один элемент управления в форме (панели), вы можете быть уверены, что MainMdiForm.Controls [1] будет содержать объект MdiClient во время события загрузки формы, но это действительнолучше выполнить итерацию, чтобы убедиться:

    Примечание: мы объясняем вызов, который устанавливает ссылку на основную форму MDI в каждом дочернем окне (theMdiParent) в разделе № 5 ниже

    private void Form1_Load(object sender, EventArgs e)
    {
        // find the MdiClient control and set a reference
        foreach (Control theControl in this.Controls)
        {
            MdiClient testMdiClient = theControl as MdiClient;
            if (testMdiClient != null)
            {
                theMdiClient = testMdiClient;
                break;
            }
        }
    
            // hide the panel
            panel1.Hide();
    
            // set child windows MdiParent to Main MDI Form
            // set the child windows reference to this Form
            // show the child windows
            f2.MdiParent = this;
            // explained in section #5 below
            f2.theMDIParent = this;
            f2.Show();
    
            f3.MdiParent = this;
            f3.theMDIParent = this;
            f3.Show();
    
            f4.MdiParent = this;
            f4.theMDIParent = this;
            f4.Show();
    
            f5.MdiParent = this;
            f5.theMDIParent = this;
            f5.Show();
    
            // set the initialization flag for future use
            isInitializing = false;
    }
    
  4. Теперь более интересный аспект этой проблемы: как повторно отобразить Panel, если в основной форме MDI нет дочерних окон.Сначала мы определим открытый метод в основной форме MDI: затем мы можем предположить, что если этот метод вызывается обработчиком события FormClosed в каждом дочернем окне, то: если свойство MdiChildren.Length основной формы MDI точно равно 1: последнее оставшееся видимое дочернее окно было только что закрыто. Обратите внимание, что затем мы удаляем объект MdiClient из коллекции элементов управления главной формы MDI:

    public void MDIChildClosed()
    {
        if (this.MdiChildren.Length == 1)
        {
            this.Controls.Remove(theMdiClient);
            panel1.Visible = true; 
        }
    }
    
  5. Мы создаем открытое свойствов Form2 (все дочерние окна являются экземплярами Form2) для хранения ссылки на основную форму MDI, которая является их MdiParent:

    public Form1 theMDIParent { get; set; }
    

    Затем мы обрабатываем событие FormClosed для дочернего окна (Form2), используя ссылку на Mdi Parent (Form 1), чтобы вызвать его открытый метод MdiChildClosed ():

    private void Form2_FormClosed(object sender, FormClosedEventArgs e)
    {
        theMDIParent.MDIChildClosed();
    }
    
  6. И в методе MdiChildClosed () основной формы MDI (Form1): как уже говорилось, мы удаляем объект MdiClient из коллекции элементов управления главной формы MDI и делаем Panel, которая обрабатывает события мыши, снова видимой :

    public void MDIChildClosed()
    {
        if (this.MdiChildren.Length == 1)
        {
            this.Controls.Remove(theMdiClient);
            panel1.Visible = true; 
        }
    }
    
  7. Теперь, надеюсь, вам интересно: как вы возвращаете объект MdiClient, когда конечный пользователь (с помощью кнопки, меню и т. Д.) Создает новые дочерние окна Mdi после того, как все дочерние окна MDI были закрыты и панель отображается снова. Как бы вы ни инициировали создание новых дочерних окон mdi, вы будете делать что-то вроде этого в основной форме MDI (Form1):

      // hide the panel
      panel1.Hide();
      // add the MdiClient back
      this.Controls.Add(theMdiClient);
    
      // example of creating a new child Form
      Form2 f6 = new Form2();
      f6.MdiParent = this;
      f6.theMDIParent = this;
      f6.Show();
    
  8. Резюме: много работы, имхо, за сравнительно небольшую отдачу. Очевидно, что вы могли бы реорганизовать этот код разными способами и сделать все более элегантно. Я лично чувствую, что приложения типа MDI давно "вышли из моды".

Единственная возможная "искра", которая вылетает из этого исследования, для меня, это идея, что вы можете разместить все виды элементов управления конфигурацией на своей панели (как здесь используется), возможно, иметь возможность скрыть все дочерние окна MDI и отображать Panel, а не ждать, пока все дочерние окна MDI будут закрыты.

1 голос
/ 01 марта 2010

Не идеальное решение, но вы можете установить для IsMDIContainer значение false, пока не будет создан дочерний элемент. (При значении false событие срабатывает нормально)

...