Windows 窗体中 TopMost 属性确实令人讨厌的错误
我有一个 Windows 窗体应用程序,它位于通知区域中。单击该图标会将其显示在前面,再次单击该图标(或单击应用程序 X 图标)会将其返回。对于这种类型的应用程序,当通过单击图标显示窗口时,使窗口始终位于顶部非常重要(尽管它是可选的)。
右键单击该图标会弹出一个上下文菜单,可以在其中选择是否启用“始终位于顶部”选项。当应用程序首次启动时,将从 XML 文件中读取应用程序设置,我 99% 认为它正常工作,TopMost
属性已正确读取(和写入)。
一段时间后(几分钟、几小时、几天,等等;我通常会休眠并且很少关机),TopMost
停止工作。我不更改选项,我不认为任何内容会更改选项值,但我单击通知区域图标并且应用程序不会显示在前面。它显示出来,但它位于背景上(它显示在 Alt+Tab 上),它并不像应有的那样“始终位于顶部”。我打开上下文菜单,禁用该选项(因为它已启用)并重新启用它,然后它就开始工作。该应用程序现在“始终位于最前面”。然而,一段时间后它可能会失去这种能力。
我不明白为什么会发生这种情况以及这是如何发生的。有谁知道为什么吗?如果没有,知道我该如何尝试调试这种行为吗?
编辑:
我添加了一段代码来在 TopMost
属性更改时显示 MessageBox,以查看是否可以注意到任何奇怪的行为,但这并不好。它没有帮助,因为表单带有 TopMost = true
但它仍然在后台......
I have this Windows Forms application where it sits in the notification area. Clicking on the icon brings it up front, clicking it again (or clicking on the app X icon) sends it back. This is the type of app that having the window always on top is important when it's displayed by clicking the icon (it's optional though).
Right-clicking the icon brings up a context menu where one can select to enable the "always on top" option or not. When the application first starts up, the app settings are read from an XML file and I'm 99% that this is working as it should, the TopMost
property is properly read (and written).
After some time (minutes, hours, days, whatever; I normally hibernate and rarely shutdown) the TopMost
stops working. I don't change the option, I don't think anything is changing the option value but I click the notification area icon and app is not brought up front. It shows up but it's on the background (it displays on Alt+Tab), it's not "always on top" as it should. I bring up the context menu, disable the option (cause it's enabled) and enable it back and it starts to work after that. The app is now "always on top". However, it can lose this ability anytime after a while.
I can't understand why this happens and how this happens. Does anyone have any idea why? If not, any idea how could I try to debug such behavior?
EDIT:
I added a piece of code to show a MessageBox when the TopMost
property was changed to see if I could notice any strange behavior but it was no good. It didn't help because the form was with TopMost = true
but it still was in the background...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不只有一个“最顶层”窗口。最顶层只是说“在所有非最顶层窗口之前”。
我非常确定桌面的重新初始化(例如休眠时)需要另一个
SetWindowPos(hwnd, HWND_TOPMOST, ...)
(这是底层的 Win32 API 调用)。作为解决方法,您可以在显示窗口时重置并再次设置该属性。
另一种可能性是隐藏窗口也会改变 Z 顺序 - 要么隐式地改变 Win32 的实现方式,要么显式地改变 WinForms 调用隐藏/显示窗口的方式。
There is more than just one "Topmost" window. Topmost just says "Before all non-topmost windows".
I am pretty sure a reinitialization of the desktop (such as when hibernating) requires another
SetWindowPos(hwnd, HWND_TOPMOST, ...)
(which is the underlying Win32 API call).As a workaround, you could reset and set the property again when showing the window.
Another possibility is that hiding the window also changes the Z order - either implicitely how Win32 implements that, or explicitely in the way WinForms call the hide/show window.
像 peterchen 一样,我也不知道如何找到根本原因。但为什么不让它变得简单一点呢?
当您单击图标时,您将显示窗口并相信 TopMost 仍然处于活动状态。为什么不在显示窗口之前使用当前设置调用
SetWindowPos()
呢?这不应该产生任何性能问题(仅当用户单击图标时才会发生)或任何其他副作用。我知道,找出根本原因固然很好,但如果你能用这么小的解决方法来解决它,也许就不值得了。
Like peterchen i also don't have a clue how to get the root cause. But why not make it a little bit simpler?
When you click on your Icon you'll show up your window and rely that TopMost is still active. Why not call
SetWindowPos()
with the current setting right before you show the window. This shouldn't make any performance problems (only happens if the user clicks the icon) nor any other side effect.I know, it would be great to find out the root cause, but maybe it's not worth if you can solve it with such a little workaround.