Почему вызов Hide в обработчике событий FormClosing дочерней формы скрывает родительскую форму? - PullRequest
0 голосов
/ 18 февраля 2012

Когда форма Form2 закрыта, с помощью кнопки X иногда скрывается и основная форма, но не всегда.Часто основная форма скрывается после первого нажатия кнопки «newForm», а в других случаях требуется много операций открытия-закрытия, прежде чем основная форма будет скрыта при закрытии формы 2.Почему это происходит?Почему это нерегулярно?

Это небольшой тестовый код для более крупного приложения, над которым я работаю.В этом приложении поток непрерывно читает сетевой поток, и, когда встречается конкретное сообщение, отображается модальная форма.Пользователь может закрыть эту модальную форму или ему может быть приказано закрыть себя другим сетевым сообщением.В этом случае, чтобы дать пользователю некоторое время для просмотра данных, отображаемых в форме, я реализовал отложенное закрытие формы для этой формы.Когда форма запускает свой код закрытия задержки, по сети может появиться другое сообщение, которое откроет новый экземпляр этой формы, и в этом случае, как я заметил, когда таймер исходной формы заканчивается, исходная формаотображается слева, пока новый экземпляр не будет закрыт.Вызов Hide в обработчике события FormClosing закрывает исходную форму, если запущено более одного ее экземпляра, но имеет побочный эффект - скрывает все приложение (основную форму), когда закрывается последний экземпляр этой формы, либопользователь или по коду отложенного закрытия.И снова, все приложение не всегда скрыто, но это происходит.

//Main form's 'newForm' button
private void btn_newForm_Click(object sender, EventArgs e)
{
        Form2 f = new Form2();
        f.ShowDialog();
}   

public partial class Form2 : Form
{
    private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        Hide();
    }
}

Обновление (из приложения, над которым я работаю):

Проблема визуально показана ниже.Верхняя часть рисунка, помеченная буквой «А», представляет ситуацию, когда был создан первый модальный диалог (выделен серым цветом), и он находится в процессе автоматического закрытия по истечении 4 секунд.Второй экземпляр (заголовок синего окна) активен и ожидает ввода.В нижней части рисунка, помеченного буквой «B», счетчик закрытия первого экземпляра завершен, но первый экземпляр остается видимым.Добавление Hide не меняет картинку «A», но картинка «B» будет отображать только активный модальный диалог, что я и хочу.Если Hide не используется, и у нас есть случай, показанный в «B», после закрытия активного модального диалога неактивный диалог исчезнет вместе с активным, но не раньше.В это время моя основная форма также будет скрыта, иногда.

the problem

Ответы [ 3 ]

2 голосов
/ 19 февраля 2012

Ваша основная форма не скрывается, она скрывается за другим окном. Недостаток в вашем коде состоит в том, что на короткий момент ни одно ваших окон не может получить фокус. Ваше главное окно не может получить фокус, оно отключено вашим диалогом и не будет повторно включено, пока диалоговое окно не будет полностью закрыто. Ваш диалог не может получить фокус, вы скрываете его. Поэтому Windows ищет другое окно для фокусировки и может выбрать только окно, принадлежащее другому приложению. Как и Visual Studio, красивый и большой, поэтому ваше главное окно хорошо закрыто.

Не уверен, что вы пытаетесь сделать, нет смысла вызывать Hide (), так как диалог закроется через пару микросекунд. Просто удалите выписку.

0 голосов
/ 14 июня 2013

Я знаю, что тема довольно старая, но мне недавно пришлось искать ответы на этот точный вопрос.

Почему скрывает (дочернюю модальную) форму вместо закрытия это?

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

Например, я использую класс, представляющий собой пользовательское дерево сеток. Представьте себе что-то вроде документа Excel с несколькими таблицами (листами), и каждая таблица может иметь дочерние таблицы. Очень мощный способ хранения данных, которые могут использоваться несколькими объектами и несколькими формами одновременно.

Теперь этот объект «TreeTable_Class» имеет встроенную пользовательскую форму, которая фактически отображает содержимое одной из своих таблиц за раз в GridView, и вы можете выбрать, какую таблицу отображать, выбрав ее в TreeView. Здесь вы можете видеть, что «Редактор базы данных» на самом деле является формой MDI, которая может загружать форму из любого класса TreeTable_Class.

enter image description here

И это форма, которую я использую для редактирования содержимого ячейки для данной (выбранной) таблицы (я выбрал другую ячейку с длинным текстовым содержимым из другой таблицы в этой базе данных)

enter image description here

Теперь, когда вы решите закрыть пользовательскую форму, а не скрывать ее, эта форма будет недоступной , вы больше не сможете ее отобразить и получите исключение (нет экземпляра объекта) В некоторой степени, он еще не ликвидирован (поэтому проверка Если MyForm ничего не значит ... бесполезна) Я знаю, что мне нужно реализовать GarbageCollector и удалить дочернюю форму вручную, но это выходит за рамки эта тема.

В любом случае, мой класс мог бы использовать большой объем памяти, данных, и если бы мне приходилось перестраивать ВСЕ содержимое каждый раз, когда я хочу показать новый экземпляр этой формы, это было бы большое количество рабочей нагрузки в моем приложении. Вот почему я выбрал скрыть форму вместо закрытия до тех пор, пока не закроется основное приложение или когда явно не будет вызван определенный метод CloseFormAndDispose (), либо программой, либо если я сделайте эту опцию доступной для пользователя через пользовательский интерфейс.

Попытка обхода:

Это обходной путь, который я нашел, чтобы переопределить форму ", замененную другой, потому что ни один из родительских / дочерних не мог быть извлечен ":

Извините, я в VB .. но вы можете использовать инструмент для преобразования этого в C # или сделать это вручную, это довольно просто ..

// This is the child, a Cell Editor that can edit the content of a Cell.
Protected WithEvents _CellEditor As CellEditor_Form = Nothing

Эта форма редактора является членом TreeTable_Form, формы, которая может фактически отображать и редактировать содержимое всего файла базы данных (одного файла) И этот класс TreeTable_Form содержит подпрограмму, которая обрабатывает событие закрытия CellEditor

Public Partial Class TreeTable_Form
    // Sorry. The "WithEvents" in C# is a litte bit complex to me... So, in VB :
    Protected WithEvents _CellEditor As CellEditor_Form = Nothing
    // ...

    // CellEditor handling method (I used a Code converter...) :
    // The original VB declaration is :
    // Protected Sub RecallFormAfterCellEditorHidden() Handles _CellEditor.Closed
    // You'll have to write specific Event handler for _CellEditor object declared above...
    protected void RecallFocusAfterCellEditorHidden()
    {
        Application.DoEvents();
        this.Focus();
    }

End Class

Этот крошечный защищенный метод vall RecallFormAfterCellEditorHidden () в вашем классе (если вы используете класс, содержащий формы) или в вашем основном из , при условии, что ваша основная форма содержит дочерние формы (диалоги) будут пытаться сосредоточить внимание на вашем приложении или MainForm ...

Кстати, TreeTable_ Form на самом деле является компонентом TreeTable_ Class . Последнее - это объект, который можно использовать где угодно. В приложении главной формы, в другом классе, в диалоге, где угодно ... и может передаваться по ссылке, чтобы разделить его содержимое между несколькими элементами. И этот TreeTable_Class содержит RecallFocusAfterTreeViewerHidden () метод, который обрабатывает закрытие этой формы. Это означает, что форма или приложение, которое фактически использует класс, будет получать фокус каждый раз, когда вы закрываете его дочернюю форму. Я сделал это таким образом, чтобы получить объект, который можно использовать где угодно

У нас все еще проблемы!

Однако этот метод заставит ваше приложение немного мерцать при каждом закрытии дочернего диалогового окна, и не получится при 100% !Иногда моя родительская форма все еще исчезает с экрана и попадает в другое окно.Alt + TAB тоже не поможет.Но это случается реже, чем без этого трюка метода.У меня нет лучшего ответа в это время, я все еще ищу ... Я вернусь сюда, если узнаю как.Я использую это специальное приложение в своей работе, например, для написания заметок во время собраний и выпускаю PV (устное - французское извинение) в PDF или DOCx на лету ...

И я извиняюсьЯ в VB, а не в C #.Надеюсь, это немного поможет, пока мы не найдем лучший обходной путь для этого ...

0 голосов
/ 19 февраля 2012

Я не уверен, прав ли я, но, возможно, вы забыли добавить e.Cancel = true; к своему закрывающему событию.

Во-вторых, я думаю, что использование модальной формы полезно только тогда, когда вы ожидаете действия вроде OK илиОТМЕНА от пользователя, вот где DialogResults пригодится.Звучит странно, если это происходит время от времени, а не постоянно!может быть, вы можете попробовать так:

//Main form's 'newForm' button 

//Define form in your mainform 
private Form2 f;

private void btn_newForm_Click(object sender, EventArgs e) 
{ 
        if(f != null) { f.Show(); return; }

        f = new Form2()
        f.FormClosing += delegate { f.Hide(); };         
        f.Show(); 
}  
...