什么情况下将窗口设置为最顶层会失效?

4
我有一个C++应用程序,需要创建置顶窗口。有时它可以工作,但很多时候会失败。在应用程序的某个部分,我创建了一个后台线程来显示置顶信息窗口。用户关闭窗口后,该线程消失。第一次应用程序创建线程并显示窗口时,窗口是置顶的。然而,所有后续的线程都无法将其窗口设置为置顶。我已经尝试了使用WS_EX_TOPMOST样式创建窗口,以及在窗口创建后调用SetWindowPos方法。这两种方法都没有起作用。我查找过,但未能找到任何有关窗口无法设置为置顶的问题的参考资料。
在我进行的一个测试中,我调用了SetWindowPos,在它返回后检查窗口的样式,发现虽然SetWindowPos返回成功,但其窗口的样式并未设置为置顶。我也使用Spy ++检查了窗口的样式,并确认样式并未被设置。

你的代码似乎有一些错误。你介意在这里发布它吗? - Daniel Mošmondor
5个回答

4

当进程在创建窗口或调用SetWindowPos时没有SetForegroundWindow权限时,SetWindowPos将悄无声息地无法设置WS_EX_TOPMOST。 这可能是你想要窗口置顶的时间之一(也可能是你不应该被允许的时间之一)。

有传言称自Vista以来,微软已经关闭了这个漏洞。

限制是可以理解的--你不希望来自随机进程的顶层窗口窃取焦点,因为它们没有业务需要。

一个合理使用情况的解决方法是,当一个进程间接启动一个辅助进程(例如,在父进程中启动安装然后从msiexec启动辅助进程),而辅助进程希望置顶甚至获取输入时,使用AllowSetForegroundWindow。

显然,你需要有获得焦点的权利才能放弃它。


0

我在使用Borland C++ Builder时遇到了类似的问题。在窗口创建并显示后,将FormStyle设置为fsStayOnTop可以解决这个问题。我认为关键是要在窗口完全显示后才执行此操作。

*visibleForm = new TForm3(Form3);
(*visibleForm)->FormStyle = fsStayOnTop;

0
不知道我遇到的问题是否与你的相同,但至少症状是一样的。通过将 this->TopMost = trueInitializeComponent 移动到 Form_Load 来解决它。

0

SetForegroundWindow() 会激活窗口。也许他不想要这个。 - Sanich

0
SetWindowPos(_hYourWindow, HWND_TOPMOST, 0, 0, 0, 0,
    SWP_ASYNCWINDOWPOS|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOMOVE);

应该可以工作!


1
为什么?您能否解释一下为什么它可以解决这个问题? - Sanich

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