当Form2关闭时,通过它的X按钮,主窗体有时也会隐藏,但并非总是如此。通常在初始“newForm”按钮单击后隐藏Main表单,而在主表单在Form2结束时隐藏之前需要进行许多打开关闭操作。为什么会这样?为什么不规律?
这是我正在处理的更大应用程序的小测试代码。在该应用程序中,线程连续读取网络流,并且当遇到特定消息时,显示模态形式。用户可以关闭该模态表单,或者可以告诉用户通过不同的网络消息关闭自己。在这种情况下,为了给用户一些时间来查看表单显示的数据,我实现了该表单的延迟表单关闭。当表单运行其延迟关闭代码时,另一条消息可以通过网络进入,这将打开这个表单的新实例,在这种情况下,我观察到,一旦原始表单的计时器用完,原始表单是左显示,直到新实例关闭。在FormClosing事件处理程序中调用Hide会在原始表单的多个实例正在运行时关闭原始表单,但是当此表单的最后一个实例关闭时,它具有隐藏整个应用程序(主表单)的副作用,用户或延迟关闭代码。而且,整个应用程序并不总是被隐藏,但确实会发生。
//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”只会显示活动模式对话框,这就是我想要的。如果未使用Hide并且我们在“B”中显示了这种情况,则一旦关闭活动模式对话框,非活动对话框将与活动对话框一起消失,但不久就会消失。此时我的主表单也会被隐藏,有时候。
答案 0 :(得分:2)
您的主要表单不会被隐藏,它会在另一个窗口后面消失。代码中的缺陷是,短暂的 none 窗口可以获得焦点。您的主窗口无法获得焦点,它会被您的对话框禁用,并且在对话框完全关闭之前不会重新启用。您的对话框无法获得焦点,您可以隐藏它。因此,Windows寻找另一个窗口来关注,并且只能选择另一个应用程序拥有的窗口。就像Visual Studio一样,漂亮又大,所以你的主窗口很好地覆盖了它。
不确定你要做什么,调用Hide()是没有意义的,因为对话框将在几微秒后关闭。只需删除该声明即可。
答案 1 :(得分:0)
我不确定我是否正确,但您可能忘记在结束活动中添加e.Cancel = true;
。
其次,我认为使用模态形式只有在您期望用户使用OK或CANCEL等操作时才有用,这就是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();
}
答案 2 :(得分:0)
我知道这个话题很老,但我最近不得不为这个确切的问题寻找答案。
我可能错了,但我认为在某些情况下,隐藏模态子表单而不是关闭它有时很有用。
例如,我正在使用一个自定义网格树的类。可以想象具有多个表(表)的Excel文档,每个表都可以有子表。一种非常强大的方式来存储可以由多个对象和多个表单一次使用的数据。
现在,这个“TreeTable_Class”对象有一个内置的自定义表单,实际上在GridView中一次显示其中一个表的内容,您可以通过在Treeview中选择它来选择要显示的表。你可以在这里看到“数据库编辑器”实际上是MDI表单,可以从任何TreeTable_Class加载表单。
这是我用来编辑给定(选定)表格的单元格内容的表单(我从该数据库中的另一个表中选择了另一个具有长文本内容的单元格)
现在,当您选择关闭自定义表单而不是隐藏它时,该表单将无法访问,您无法再显示它,并且您会收到异常(没有对象的实例) )有点,它还没有被处理掉(所以检查如果MyForm没什么,那么...... 是没用的)我知道我必须实现GarbageCollector并手动处理子表单,但是它不在本主题的范围。
无论如何,我的类可以使用大量内存,数据,如果每次我想要显示该表单的 new 实例时我必须重建所有内容,那将是我的应用程序中有大量工作量。这就是为什么我选择隐藏表单而不是关闭直到主应用程序退出或者通过程序显式调用特定的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
您的班级中的这个微小的受保护的void RecallFormAfterCellEditorHidden()方法(如果您使用的是包含表单的类)或在您的Main From 中,假设您的主表单包含子表单(对话框)将尝试强制关注您的应用程序或MainForm ......
顺便说一下,TreeTable_ 表单实际上是TreeTable_ Class 的一个组件。后者是一个可以在任何地方使用的对象。在主窗体应用程序中,在另一个类中,在对话框中,在任何地方......并且可以通过引用传递以在几个项目之间共享其内容。此TreeTable_Class包含一个 RecallFocusAfterTreeViewerHidden()方法,用于处理该表单的关闭。这意味着,每次关闭其子窗体时,实际使用该类的窗体或应用程序将获得焦点。我已经这样做了一个可以在任何地方使用的对象
但是,每次关闭子对话框时,此方法都会使您的应用程序闪烁一点,并且不会100%成功!有时,我的父表单仍然会从屏幕上消失并在另一个窗口后面被击中。 Alt + TAB也不会帮助。但是,如果没有这种方法技巧,这种情我现在还没有更好的答案,还在寻找...如果我知道如何,我会回到这里。我正在我的工作中使用这个定制的应用程序在会议期间写备忘录,然后在PDF或DOCx中即时生成PV(procès语言 - 法语抱歉)......
我很抱歉,我在VB,而不是C#。希望这有点帮助,直到我们找到一个更好的解决方法......