覆盖任务栏命令"关闭所有Windows"的处理

Sim*_* D. 6 c# wpf

我有一个WPF应用程序与多个不相关的Windows,即总有一个MainWindow和任选许多其他没有所有者.如果这些窗口在任务栏中分组,则窗口将在任务栏上下文菜单中提供"关闭所有Windows"操作.如果单击它,我的应用程序的每个窗口都会按照我无法控制的顺序获得单独的关闭命令.

问题:如果可以取消挂起的更改,我的一些窗口可能会在关闭之前询问.如果有很多这样的话,这很烦人并且令人困惑.

我想要的是:如果要求关闭MainWindow,我想提示一次,如果没关系的话.如果是,所有窗口应该静默关闭,否则保持打开状态.但我的MainWindow不是第一个处理结束程序的人.

我已经发现,我可能需要使用wparam SC_CLOSE检查我的MainWindow的Windows消息循环中的某些WM_SYSCOMMAND.(请参阅如何在使用Windows 7的MFC中区分"关闭所有Windows"和"关闭"各个窗口?)

但是,在执行任何其他窗口的关闭例程之前,我该如何评估它呢? ComponentDispatcher.ThreadPreprocessMessage在我的主窗口来得太晚了,它在一些其他窗口开始关闭程序后触发.

这个问题在某种程度上与这个问题有关: 当使用任务栏的关闭所有Windows时,奇怪的表格关闭行为

Pet*_*iho 3

就我个人而言,我会保持现状。我可以看到多次提示保存/取消更改可能会很烦人,但这对我来说似乎并不令人困惑。虽然很烦人,但这似乎是一个小烦恼,坦率地说,当用户打开一堆这样的窗口时,可能会教用户不要使用“关闭所有窗口”选项。那是说……


正如您发现的问题所指出的,没有内置方法可以区分“关闭所有窗口”和常规“关闭窗口”命令。系统只是按顺序将消息发送到窗口。

在 MFC 中(即另一个问题的上下文),您可以调用AfxGetCurrentMessage()来检索有关实际引发SC_CLOSE消息的信息。如果是用户输入被转换为关闭命令,则将存在某种类型的用户输入(键盘、鼠标等)作为当前消息。否则,你只会看到它WM_SYSCOMMAND本身。

但是您不能在 WPF 中应用相同的方法,因为 WPF 不提供GetCurrentMessage()方法或其等效方法(据我所知)。对您获得的窗口消息的唯一访问是重写该Control.WndProc()方法,并且当您获得关闭命令时,最新的窗口消息将始终是SC_CLOSE.

在我看来,您能做的最好的事情就是使用WndProc()覆盖来跟踪传入消息,以便您可以在非关闭命令消息传入时重置标志。

然后,当您收到关闭命令并显示用户提示时,您可以检查该标志。如果设置为 true,那么您可以忽略提示并仅使用用户最近选择的任何内容。由于每当非关闭命令消息传入时您都会清除该标志,因此收到的第一个关闭命令将始终显示提示。


另一种选择是先发制人地关闭所有剩余的窗口。在这里,您仍然会提示用户有某种“应用于所有其他窗口”选项,但您实际上可以显式关闭所有其他窗口,而不是仅依赖该标志进行设置。


从用户界面的角度来看,这些都不是理想的。主要问题是当用户尝试仅关闭一个窗口时。在第一种方法中,即使没有任何其他窗口需要关闭,用户也会在提示中看到“应用于所有其他窗口”选项。第二种方法更加自洽,但添加了一项您可能想要也可能不想要的功能:用户可以在仅关闭一个窗口时随时关闭程序中的所有窗口。

这些行为都不完全是标准的 Windows 用户界面行为。即,在试图为用户节省一些烦恼(和困惑,尽管就像我说的,我不认为这部分是这样)时,您引入了本身可能会让用户感到困惑的内容。

鉴于它涉及额外的工作编码,并且可能只是将一个烦人/令人困惑的结果交换为另一个结果,最好的解决方案可能就是根本不尝试解决该问题。