簡體   English   中英

為什么在子窗體的FormClosing事件處理程序中調用“隱藏”會隱藏父窗體?

[英]Why calling Hide in a child form's FormClosing event handler hides the parent form?

當關閉Form2時,通過X按鈕,有時也會隱藏Main窗體,但並非總是如此。 通常,在最初單擊“ newForm”按鈕后,隱藏主窗體,而有時,在將主窗體隱藏在Form2的關閉位置之前,需要進行許多打開-關閉操作。 為什么會這樣呢? 為什么不規則?

這是我正在處理的較大應用程序的少量測試代碼。 在該應用程序中,線程連續讀取網絡流,並且當遇到特定消息時,將顯示模式形式。 用戶可以關閉該模式形式,也可以通過其他網絡消息告知用戶關閉自身。 在這種情況下,為了給用戶一些時間查看表單顯示的數據,我為該表單實施了延遲的表單關閉。 當表單運行其延遲關閉代碼時,另一條消息可以通過網絡進入,這將打開該表單的新實例,在這種情況下,我觀​​察到,一旦原始表單的計時器用盡,原始表單就是直到新實例關閉為止。 如果有多個實例正在運行,則在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();
    }
}

更新(從我正在處理的應用程序中):

該問題顯示在下面。 圖片的頂部標記為“ A”,表示實例化了第一個模態對話框(顯示為灰色),並且在經過4秒鍾后處於自動關閉狀態。 第二個實例(藍色窗口標題)處於活動狀態,正在等待輸入。 在圖片的下部,標記為“ B”,關閉第一個實例的計數器已經完成,但是第一個實例仍然可見。 添加“隱藏”不會更改圖片“ A”,但是圖片“ B”將僅顯示活動的模態對話框,這就是我想要的。 如果未使用“隱藏”,並且情況顯示為“ B”,則關閉活動模式對話框后,不活動對話框將與活動對話框一起消失,但不會很快消失。 此時,有時也會隱藏我的主要表單。

問題

您的主窗體不會被隱藏,而是消失在另一個窗口后面。 在你的代碼的缺陷是,短暫的瞬間你的Windows可以獲得焦點。 您的主窗口無法獲得焦點,它已被對話框禁用,並且在對話框完全關閉之前不會重新啟用。 您的對話框無法獲取焦點,您將其隱藏。 因此,Windows會尋找另一個要關注的窗口,並且只能選擇另一個應用程序擁有的窗口。 與Visual Studio一樣,它又大又好,因此您的主窗口可以很好地覆蓋它。

不確定要執行的操作,調用Hide()沒有意義,因為對話框將在幾微秒后關閉。 只需刪除該語句。

我知道這個話題已經很老了,但是最近我不得不為這個精確的問題尋找答案。

為什么隱藏 (子模式)窗體而不是關閉它?

我可能是錯的,但我認為在某些情況下,隱藏模式子窗體而不是關閉它有時是有用的。

例如,我使用的是一個自定義網格樹的類。 想一想帶有多個表(表格)的Excel文檔,每個表可以有子表。 一種非常強大的方式來存儲可以一次由多個對象和多種形式使用的數據。

現在,此“ TreeTable_Class”對象具有一個內置的自定義窗體,該窗體實際上一次在GridView中顯示其表之一的內容,您可以通過在Treeview中選擇要顯示的表來選擇要顯示的表。 您可以在此處看到“數據庫編輯器”實際上是MDI表單,可以從任何TreeTable_Class加載該表單。

在此處輸入圖片說明

這是我用來編輯給定(選定)表的單元格內容的表格(我從該數據庫的另一個表中選擇了一個帶有長文本內容的單元格)

在此處輸入圖片說明

現在,當您選擇關閉自定義表單而不是將其隱藏時,該表單將無法訪問 ,無法再顯示,並且會收到異常(該對象無實例)。某種程度上,它還沒有被處置(所以檢查“ 如果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是一種可以實際顯示和編輯整個數據庫文件(單個文件)內容的表單,並且此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

假設您的主窗體包含子窗體(對話框), 該微小的受保護的void RecallFormAfterCellEditorHidden()方法將在您的Class(如果您使用的是包含Forms的類)中, 或者在您的Main From中 (假設您的主窗體包含子窗體(對話框)) MainForm ...

順便說一句,TreeTable_ Form實際上是TreeTable_ Class的組件。 后者是一個可以在任何地方使用的對象。 在主窗體應用程序中,在另一個類中,在對話框中,任何地方...都可以通過引用傳遞,以在多個項目之間共享其內容。 並且此TreeTable_Class包含一個RecallFocusAfterTreeViewerHidden()方法,用於處理該表單的關閉。 這意味着,每次關閉其子窗體時,實際使用該類的窗體或應用程序都會獲得焦點。 我以這種方式獲得了可以在任何地方使用的對象

我們仍然遇到問題!

但是,此方法將使您的應用程序在每次關閉子對話框時都會閃爍一下, 並且不會成功100% 有時,我的父窗體仍然從屏幕上消失並被另一個窗口擊中。 Alt + TAB也不會停止。 但這比沒有使用此方法的技巧少。 目前,我沒有更好的答案,仍在搜索...如果知道如何,我會回到這里。 我在工作中使用了這個定制的應用程序,例如在會議期間編寫備忘錄,並以PDF或DOCx的形式即時生成PV(語言對白-抱歉)。

對不起,我在VB中,不在C#中。 希望這會有所幫助,直到我們找到更好的解決方案...

我不確定我是否正確,但也許您忘記添加e.Cancel = true; 結束活動。

其次,我認為僅當您期望用戶執行OK或CANCEL之類的操作時,使用modal形式才有用,這是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(); 
}  

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM