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) он теперь работает во всех ситуациях.

Ответ 5

Документация для функции SetForegroundWindow объясняет, что это на самом деле предполагаемое поведение; процессы не должны "красть" фокус. Тем не менее, вы можете настроить свой код так, чтобы он работал в любом случае.

Взгляните на раздел примечаний LockSetForegroundWindow: он объясняет

Система автоматически разрешает вызовы SetForegroundWindow, если пользователь нажимает клавишу ALT [..]

Вы можете использовать это поведение, создавая вашу имитацию модели нажатием клавиши Alt с помощью функции SendInput до вызова SetForegroundWindow.