Windows 7: как вывести окно на передний план независимо от того, какое другое окно имеет фокус?
Я реализую замену на панели задач, например, в стиле приложения. Он делает некоторые уникальные вещи с OpenGL и с быстрыми клавишами, поэтому так, как он настраивается, окно не всегда имеет фокус. Я хотел бы реализовать его таким образом, чтобы я мог принести произвольное окно на передний план, подобно панели задач или программе ALT-TAB.
Однако мой код просто заставляет значок приложения мигать на панели задач. В документации по API Windows говорится, что это то, что должно произойти, но я ищу способ обойти это.
Я адаптировал свой код из следующих примеров, которые говорят, что привязка к потоку переднего плана должна позволять вам устанавливать окно переднего плана. Вот сайты:
http://www.voidnish.com/Articles/ShowArticle.aspx?code=dlgboxtricks
http://invers2008.blogspot.com/2008/10/mfc-how-to-steal-focus-on-2kxp.html
Мой код выглядит так. Обратите внимание, что он использует обертки win32 для python (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, но если есть решение на другом языке, я буду использовать обертки или сделать все, что необходимо для его запуска и запуска.
Спасибо заранее!
EDIT:. Я был бы открыт для того, чтобы он работал только на моем конкретном компьютере, то есть на том, чтобы включить на моей машине способ для любого фокуса приложения.
РЕШЕНО:. Вам нужно отключить блокировку переднего плана. Оказывается, это было так просто:
win32gui.SystemParametersInfo(win32con.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, win32con.SPIF_SENDWININICHANGE | win32con.SPIF_UPDATEINIFILE)
Ответы
Ответ 1
У меня был код, который работал в течение многих лет, полностью переходя к Windows 95. При двойном щелчке по значку в системном трее приложений я всегда использовал функции Win32 API, такие как BringWindowToTop и SetForegroundWindow, чтобы принести окна приложений к на переднем плане. Все это перестало работать, как предполагалось, в Windows 7, где мое окно ввода окажется за другими окнами, и значок окна будет мигать в строке состояния. "Работа вокруг", с которой я столкнулся, - это; и, похоже, он работает со всеми версиями 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);
Ответ 2
Мне не нравятся эти рекомендации по использованию win32gui
, потому что вы не можете легко установить это через pip
. Итак, вот мое решение:
Сначала установите pywinauto
через pip
. Если вы находитесь на Python 2.7.9 или более новой версии на ветке 2 или Python 3.4.0 или более новой версии из 3-х ветвей, pip
уже установлен. Для всех остальных обновите Python, чтобы получить его (или вы можете вручную загрузить и установить его, запустив этот script, если вы должны запустить более старую версия Python.)
Просто запустите это из командной строки (не изнутри Python):
pip install pywinauto
Затем импортируйте то, что вам нужно, из pywinauto
:
from pywinauto.findwindows import find_window
from pywinauto.win32functions import SetForegroundWindow
Наконец, это только одна фактическая строка:
SetForegroundWindow(find_window(title='taskeng.exe'))
Ответ 3
Согласно nspire, я пробовал его решение с помощью python 2.7 и W8, и он работает как шарм, даже если окно сведено к минимуму *.
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)
- Первоначально это было, если окно не было сведено к минимуму, но благодаря Кому комментарий
win32gui.ShowWindow(HWND, win32con.SW_RESTORE)
он теперь работает во всех ситуациях.
Ответ 4
Если вы используете горячие клавиши, используйте RegisterHotKey
. Как поясняет Раймонд Чен (сопутствующая статья в блоге с тем, что уже связано с Крисом), Нажатие зарегистрированной горячей клавиши дает вам любовь к активации переднего плана.
Ответ 5
Документация для функции SetForegroundWindow
объясняет, что это на самом деле предполагаемое поведение; процессы не должны "красть" фокус. Тем не менее, вы можете настроить свой код так, чтобы он работал в любом случае.
Взгляните на раздел примечаний LockSetForegroundWindow
: он объясняет
Система автоматически разрешает вызовы SetForegroundWindow, если пользователь нажимает клавишу ALT [..]
Вы можете использовать это поведение, создавая вашу имитацию модели нажатием клавиши Alt с помощью функции SendInput
до вызова SetForegroundWindow
.