Windows 7: how to bring a window to the front no matter what other window has focus?
Solution 1
Late answer, but you can use:
import win32gui
hwnd = win32gui.FindWindowEx(0,0,0, "Window Title")
win32gui.SetForegroundWindow(hwnd)
Solution 2
I don't like these suggestions of using win32gui
because you can't easily install that via pip
. So here's my solution:
First, install pywinauto
via pip
. If you're on Python 2.7.9 or a newer version on the 2 branch, or Python 3.4.0 or a newer version from the 3 branch, pip
is already installed. For everyone else, update Python to get it (or you can manually download and install it by running this script, if you must run an older version of Python.)
Just run this from the command line (not from within Python):
pip install pywinauto
Next, import what you need from pywinauto
:
from pywinauto.findwindows import find_window
from pywinauto.win32functions import SetForegroundWindow
Finally, it's just one actual line:
SetForegroundWindow(find_window(title='taskeng.exe'))
Solution 3
According to nspire, I've tried his solution with python 2.7 and W8, and it works like a charm, even if the window is minimized *.
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)
- Originally it was if the window it's not minimized, but thanks to Whome's comment
win32gui.ShowWindow(HWND, win32con.SW_RESTORE)
, it now works in all situations .
Solution 4
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);
Solution 5
If you're implementing hotkeys, use RegisterHotKey
. As Raymond Chen puts it (companion blog article to the one already linked by Chris), "Pressing a registered hotkey gives you the foreground activation love".
Related videos on Youtube
jmite
I am Joey Eremondi, a PhD Student at the University of British Columbia. I do research in Programming Languages and Theory of Computation, particularly with dependent types. My Masters Thesis was on improving error messages for higher order unification. I've also co-authored a few papers on reversal-bounded counter automata. I have an M.Sc in Computing Science from Utrecht University, a B.Sc. Honours in Computer Science, and a B.Sc. 4-year in Mathematics, both from the University of Saskatchewan.
Updated on July 09, 2022Comments
-
jmite almost 2 years
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.
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
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.
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.
Thanks in advance!
EDIT: 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.
-
jmite almost 13 yearsOkay, but there are plenty of applications which are able to do it. It's clearly possible, and I've found tutorials telling me how. My question is, what am I doing which is causing the code from the tutorial not to work?
-
David Heffernan almost 13 yearswhy don't you take some code from one of these tutorials and run that
-
jmite almost 13 yearsThat's what I've done. The code I posted is almost the exact code from the tutorial, in a python wrapper (see for yourself at the two links I posted). I'm asking if anybody can tell why my code isn't doing what the pages say it will do, or if there's a better way to do it.
-
Sebastiaan almost 13 years
-
jmite almost 13 yearsI'm literally rewriting the taskbar in a way that makes that guideline completely insufficient. In any case, the solution was posted above, it's one line of code, so it's clearly not something the Windows API is going too far to prevent you from doing.
-
Ben Voigt almost 13 years@jmite: That's completely consistent with what Raymond wrote. The user controls focus on his own computer. You're the user, you change the setting, your computer acts the way you want. Just don't go deploying code that changes that setting on my computer.
-
Kevin Gale almost 12 yearsIf only it were as simple as don't do it or let the user decide. As a user I hate it when something pops up and steals focus. As a developer I get this as a requirement from customers all the time. They have some requirement that the user enter in a number every two hours and they want the screen to pop up no matter what the user is doing.
-
vikki over 11 years@David There are legitimate use cases for this. For example if you want to pass focus from your application to another when a user double clicks some link. If your opening the "other" application afresh then it will take focus, but if it's already running and you don't want to start a new process, you just bring the old one to the front. However I wouldn't go as far as changing a setting on the user's computer. nspire's answer works perfectly
-
Noitidart over 7 years@jmite thanks very much for sharing this solution. My use case is I created a screenshot app. If the user clicks the button "Take screenshot in 10 seconds", the countdown starts and then they go focus other windows and do stuff. Then after 10sec elapses, then I need to pop open the editor so the user can edit and quickly upload. I don't get why your solution works though as docs for
SPI_SETFOREGROUNDLOCKTIMEOUT
saysThe calling thread must be able to change the foreground window, otherwise the call fails.
which is same reason inSetForegroundWindow
docs for failing. -
Noitidart over 7 yearsDocs are here - msdn.microsoft.com/en-us/library/windows/desktop/… -- Also how would you revert this to the default? Like what is the default value to restore it? It's not
0
is it? Note: The old solution I was using was theAttachThreadInput
as you were, however it would fail if the user had right clicked the windows taskbar, as we can't attach to the system thread or something.
-
-
Whome over 10 yearsYou must restore window before calling SetWindowPos functions. Delphi apps can use "Application.Restore;" function to unminimize. Look for ShowWindow(handle, SW_RESTORE) python call. Just call it everytime it does not harm even if window was already shown.
-
Noitidart almost 8 yearsIt brings it to top, but keyboard focus is not in our top window.
-
Noitidart over 7 yearsThis is cool but it doesn't work prefectly. Like if user right clicks the windows taskbar in Win10. @jmite solution of
SystemParametersInfo
worked. -
Aubergine over 4 yearsWorks like a charm. (2019/08) and the keyboard is active
-
Pedro Lobito about 4 yearspython 3.6 on windows throws:
ImportError: cannot import name 'SetForegroundWindow
,fixed withfrom win32gui import SetForegroundWindow
-
jmite about 4 yearsNot that late, only 9 years :P
-
ArtOfWarfare about 4 years@PedroLobito - I explicitly said not to use
win32gui
- my solution says to usepywinauto
. You should have importedSetForegroundWindow
from pywinauto.win32functions
. -
Pedro Lobito about 4 yearsAs it is, your answer doesn't work on python 3.6.
pywinauto
is heavily based onwin32gui
and won''t load properly without it, so I don't see the point of not using it. -
GoekhanDev about 2 yearsNow 11 @jmite :P