关闭所有打开的 WinForms 但保留一个?

3
我正在使用一个与Windows窗体应用.NET 3.5相关的计时器。我设置了一个定时器,如果在一定时间内没有任何操作,当前的窗体将会被关闭,并且用户会返回到默认的“未登录”窗体。该窗体显示某些信息,但不允许访问其他窗体。
Application.OpenForms给了我一个列表,可以关闭大多数可能还开着的窗体,但是Application.OpenForms似乎只知道MDI窗体。其中一些MDI窗体可能有MessageBox或其他模态窗体。甚至有可能模态窗体本身也有弹出对话框。
我知道Application.OpenForms中存在缺陷(bug),但我不认为在创建Messagebox或其他类似窗体之后仍会修改属性。无论如何,这些问题只会影响那些窗体,其他所有窗体都应该列在ApplicationOpenForms中。
是否有一种简洁的方法来迭代并关闭应用程序中的每个类型的窗体,除了我关心的那一个? (或者严格来说,关闭除了MDI父窗体之外的所有窗体,然后打开我关心的那一个)。

我认为这里使用 foreach 循环会很好。 - Brian
这会变得非常混乱,特别是当有一个打开的 MessageBox 窗口(即 MessageBox.Show)时。模态窗体通常很棘手,因为你不能简单地关闭它们。你必须模拟按下“取消”按钮,并以正确的顺序处理模态窗体。准备花费大量时间解决这个问题。 - Jim Mischel
你正在尝试实现Windows已经知道如何执行的事情。而且它做得非常好,非常安全。在一段时间的不活动后自动锁定工作站非常容易设置。事实上,大多数关心安全的公司已经这样做了。添加自己的锁屏方案不仅难以实现,而且永远不会像Windows所做的那样安全。特别是你处理密码的代码部分。 - Hans Passant
@HansPassant - 我并不是在尝试锁定工作站。我只是想限制用户在一个特定应用程序中可以使用的表单。相信我,如果能避免的话,我绝不会重新发明轮子! - MickeyfAgain_BeforeExitOfSO
2个回答

1

对我来说,这是一个98%的答案,对其他人可能是100%。

几乎在每种情况下,导致问题的表单都只是通知或确认,例如“记录已保存”或“您真的要取消吗?”并且使用MessageBox实现。所需要的就是创建一个功能等效于MessageBox的自定义表单,在需要它的MDI子窗体中创建一个实例,并使用它。当MDI子窗体关闭时(通过迭代Application.OpenForms找到),模态确认表单也会关闭。我想MessageBox没有关闭的原因是因为它实际上不是由MDI子窗体拥有的。(MSDN:“您无法创建MessageBox类的新实例。”)

当然,我不需要复制整个MessageBox功能,在大多数情况下,我真正需要的只是一个文本框和几个按钮。

其他内置的Windows表单,如PrintDialog和FileOpenDialog也存在类似于MessageBox的问题。我没有费心重新创建自己的版本。如果意外留下一个未关闭的表单,也不会造成太大的伤害。只有在某人在打开PrintDialog并在PrintDialog表单上点击打印按钮之间走开并在不活动计时器过期之前没有回来时才会发生这种情况。

可能有一种相对简单的方法可以向这些类型的表单发送消息,告诉它们关闭 - 最坏的情况是查找它们并使用低级别的Windows消息。


0

你能否考虑在表单创建时将其句柄/引用注册到数据结构中(比如定义为单例的数组)。

采用这种方法,你将拥有所有已创建的表单,并且甚至可以在同一结构上存储其他感兴趣的信息。一旦你拥有了列表,就可以在第二个线程中运行工作进程,根据数据结构中存储的信息进行清理。


不知何时何地,Windows已经有了应用程序拥有的所有窗体(包括MessageBox等)的列表。这正是我不想重新发明的轮子。 - MickeyfAgain_BeforeExitOfSO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接