Windows 7:无论其他窗口有焦点,如何将窗口置于最前面?
我正在实现一个任务栏替换、类似停靠栏的应用程序切换器风格的程序.它使用 OpenGL 和键盘快捷键做了一些独特的事情,所以它的设置方式,窗口并不总是有焦点.我想实现它,以便我可以将任意窗口带到前台,就像任务栏或 ALT-TAB 程序一样.
I'm implementing a task-bar replacement, dock-like application-switcher style program. It's doing some unique stuff with OpenGL, and with keyboard shortcuts, so the way it's set up, the window doesn't always have focus. I'd like to implement it such that I can bring an arbitrary window to the foreground, much like a taskbar or an ALT-TAB program would.
但是,我的代码只是使应用程序图标在任务栏中闪烁.Windows API 文档说这是应该发生的事情,但我正在寻找一种方法来解决这个问题.
However, my code simply causes the application icon to flash in the taskbar. The Windows API documentation says that this is what is supposed to happen, but I'm looking for a way to work around this.
我从以下示例中改编了我的代码,其中说明附加到前台线程应该允许您设置前台窗口.以下是网站:
I've adapted my code from the following examples, which say that attaching to the foreground thread should allow you to set the foreground window. Here are the sites:
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 是我想放在前面的窗口的句柄):
My code looks like this. Note that it's using the win32 wrappers for python (self.hwnd is the handle of the window I want to bring to the front):
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)
然而,除非我的窗口是前台窗口(通常不是),否则这只会导致程序的图标闪烁.
However, unless my window is the foreground window (which it isn't usually), this just causes the program's icon to flash.
我是不是把线贴错了?有没有另一种方法可以解决这个问题?我想一定有,因为有很多应用程序切换器似乎能够很好地做到这一点.
Am I doing the thread attaching wrong? Is there another way to work around this? I figure there must be, as there are lots of application switchers out there that seem to be able to do this just fine.
我是用 python 写的,但如果有其他语言的解决方案,我将使用包装器或做任何必要的事情来启动和运行.
I'm writing this in python, but if there is a solution in another language I will use wrappers or do whatever is necessarry to get this up and running.
提前致谢!
我愿意接受一种使其仅在我的特定计算机上工作的方法,即一种在我的机器上启用任何应用程序获得焦点的方法.
I'd be open to a way to make it work only on my particular computer, i.e. a way to enable, on my machine, a way for any application to take focus.
推荐答案
我有一些已经运行多年的代码,一直回??到 Windows 95.双击应用程序系统托盘图标时,我总是使用 Win32诸如BringWindowToTop 和SetForegroundWindow 之类的API 函数将我的应用程序窗口带到前台.这一切在 Windows 7 上都停止了,我的输入窗口最终会落后于其他窗口,并且窗口图标会在状态栏上闪烁.我想出的解决方法"是这样的;它似乎适用于所有版本的 Windows.
I've had some code that's been running for years, going all the way back to Windows 95. When double clicking the applications system tray icon I always used Win32 API functions such as BringWindowToTop and SetForegroundWindow to bring my application windows to the foreground. This all stopped working as intended on Windows 7, where my input window would end up behind other windows and the window icon would flash on the status bar. The 'work around' that I came up with was this; and it seems to work on all versions of Windows.
//-- show the window as you normally would, and bring window to foreground.
// for example;
::ShowWindow(hWnd,SW_SHOW);
::BringWindowToTop(hWnd);
::SetForegroundWindow(hWnd);
//-- on Windows 7, this workaround brings window to top
::SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
::SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
::SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
相关文章