Windows 7:如何让窗口始终保持在最前面?

24 投票
10 回答
38202 浏览
提问于 2025-04-16 19:21

我正在做一个替代任务栏的程序,这个程序像一个应用切换器,使用了OpenGL和一些快捷键,所以它的设置方式是窗口不总是处于焦点状态。我想实现一个功能,可以把任意窗口调到最前面,就像任务栏或ALT-TAB程序那样。

不过,我的代码只会让应用的图标在任务栏里闪烁。Windows的API文档说这就是应该发生的情况,但我想找个方法绕过这个限制。

我参考了以下几个例子来调整我的代码,这些例子说如果连接到前台线程,就可以设置前台窗口。这里是相关网站:

http://www.voidnish.com/Articles/ShowArticle.aspx?code=dlgboxtricks

http://invers2008.blogspot.com/2008/10/mfc-how-to-steal-focus-on-2kxp.html

我的代码是这样的。注意,它使用的是Python的win32封装(self.hwnd是我想要调到最前面的窗口的句柄):

fgwin = win32gui.GetForegroundWindow()
fg = win32process.GetWindowThreadProcessId(fgwin)[0]
current = win32api.GetCurrentThreadId()
if current != fg:
    win32process.AttachThreadInput(fg, current, True)
    win32gui.SetForegroundWindow(self.hwnd)
    win32process.AttachThreadInput(fg, win32api.GetCurrentThreadId(), False)

但是,除非我的窗口是前台窗口(通常不是),否则这只会导致程序的图标闪烁。

我是不是在连接线程时做错了?有没有其他方法可以绕过这个问题?我觉得应该有,因为市面上有很多应用切换器似乎都能很好地做到这一点。

我用的是Python,但如果有其他语言的解决方案,我会使用封装或者做任何必要的事情来让它运行起来。

提前谢谢大家!

编辑: 我也愿意尝试一种方法,让它只在我自己的电脑上工作,也就是说,找一种方法让任何应用在我的机器上都能获得焦点。

10 个回答

10

根据nspire的说法,我用python 2.7和Windows 8试过这个方法,效果非常好,即使窗口被最小化也能正常工作 *。

win32gui.ShowWindow(HWND, win32con.SW_RESTORE)
win32gui.SetWindowPos(HWND,win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)  
win32gui.SetWindowPos(HWND,win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)  
win32gui.SetWindowPos(HWND,win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_SHOWWINDOW + win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)
  • 最开始的条件是如果窗口没有被最小化,但多亏了Whome的评论,使用了win32gui.ShowWindow(HWND, win32con.SW_RESTORE),现在在所有情况下都能正常工作。
14

我不太喜欢用 win32gui 的建议,因为通过 pip 安装它不太方便。所以我这里有个解决办法:

首先,通过 pip 安装 pywinauto。如果你使用的是 Python 2.7.9 或更高版本,或者 Python 3.4.0 或更高版本,pip 应该已经安装好了。对于其他版本的用户,建议更新 Python 来获取它(或者如果你必须使用旧版本的 Python,可以手动下载并运行 这个脚本 来安装)。

接下来,从命令行运行以下命令(不要在 Python 内部运行):

pip install pywinauto

然后,从 pywinauto 中导入你需要的内容:

from pywinauto.findwindows    import find_window
from pywinauto.win32functions import SetForegroundWindow

最后,只需要一行代码:

SetForegroundWindow(find_window(title='taskeng.exe'))
3

虽然回答得有点晚,但你可以使用:

import win32gui
hwnd = win32gui.FindWindowEx(0,0,0, "Window Title")
win32gui.SetForegroundWindow(hwnd)

撰写回答