Windows 7:如何让窗口始终保持在最前面?
我正在做一个替代任务栏的程序,这个程序像一个应用切换器,使用了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 个回答
根据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)
,现在在所有情况下都能正常工作。
我不太喜欢用 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'))
虽然回答得有点晚,但你可以使用:
import win32gui
hwnd = win32gui.FindWindowEx(0,0,0, "Window Title")
win32gui.SetForegroundWindow(hwnd)