タスクバーの置き換え、ドックのようなアプリケーションスイッチャースタイルのプログラムを実装しています。 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(self.hwndは前面に表示したいウィンドウのハンドル)にwin32ラッパーを使用していることに注意してください):
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で書いていますが、別の言語で解決策がある場合は、ラッパーを使用するか、これを起動して実行するために必要なことは何でもします。
前もって感謝します!
編集:特定のコンピューターでのみ機能するようにする方法、つまり、自分のマシンで方法を有効にする方法を受け入れます。あらゆるアプリケーションに焦点を当てます。
解決済み:あなたがしなければならないことは前景ロックを無効にすることです。これと同じくらい簡単だったことがわかりました:
win32gui.SystemParametersInfo(win32con.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, win32con.SPIF_SENDWININICHANGE | win32con.SPIF_UPDATEINIFILE)
Windows 95までさかのぼって、何年も実行されているコードがいくつかあります。アプリケーションのシステムトレイアイコンをダブルクリックすると、常にBringWindowToTopやSetForegroundWindowなどのWin32 API関数を使用して、アプリケーションウィンドウを前面に表示しました。これはすべてWindows7で意図したとおりに機能しなくなり、入力ウィンドウが他のウィンドウの後ろに表示され、ウィンドウアイコンがステータスバーで点滅しました。私が思いついた「回避策」はこれでした。そしてそれは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);
pip
を介して簡単にインストールできないため、win32gui
を使用するというこれらの提案は好きではありません。だからここに私の解決策があります:
まず、pywinauto
を介してpip
をインストールします。 Python 2.7.9または2ブランチの新しいバージョン、またはPython 3.4.0または3ブランチの新しいバージョンを使用している場合、 pip
はすでにインストールされています。他のすべての人は、Pythonを更新して取得します(または、 このスクリプト を実行して手動でダウンロードしてインストールできます)古いバージョンのPythonを実行する必要があります。)
これをコマンドラインから実行するだけです(Python内からではありません)。
pip install pywinauto
次に、必要なものをpywinauto
からインポートします。
from pywinauto.findwindows import find_window
from pywinauto.win32functions import SetForegroundWindow
最後に、これは実際の1行です。
SetForegroundWindow(find_window(title='taskeng.exe'))
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)
、これで、すべての状況で機能します。ホットキーを実装している場合は、 RegisterHotKey
を使用します。レイモンド・チェンが言っているように(クリスによってすでにリンクされているものへのコンパニオンブログ記事)、 「登録されたホットキーを押すとフォアグラウンドアクティベーションの愛が得られます」 。
SetForegroundWindow
関数のドキュメントでは、これは実際には意図された動作であると説明されています。プロセスはフォーカスを「盗む」ことができないはずです。ただし、とにかく機能するようにコードを調整することは可能です。
LockSetForegroundWindow
の備考セクションをご覧ください:説明しています
ユーザーがALTキーを押すと、システムはSetForegroundWindowへの呼び出しを自動的に有効にします[..]
SendInput
を呼び出す前に、 SetForegroundWindow
関数を使用してAltキーを押すことをプログラムにシミュレートさせることで、この動作を利用できます。
これは私が私の仕事をさせた方法です:
import win32gui
from win32con import (SW_SHOW, SW_RESTORE)
def get_windows_placement(window_id):
return win32gui.GetWindowPlacement(window_id)[1]
def set_active_window(window_id):
if get_windows_placement(window_id) == 2:
win32gui.ShowWindow(window_id, SW_RESTORE)
else:
win32gui.ShowWindow(window_id, SW_SHOW)
win32gui.SetForegroundWindow(window_id)
win32gui.SetActiveWindow(window_id)
上記でいくつかのすばらしい答えを見ましたが、ウィンドウ名がより柔軟なパラメーターになる追加の機能が必要でした。失敗するとfalseを返します。
from win32gui import IsWindowVisible, GetWindowText, EnumWindows,\
ShowWindow, SetForegroundWindow, SystemParametersInfo
#Sub-Functions
def window_enum_handler(hwnd, resultList):
if IsWindowVisible(hwnd) and GetWindowText(hwnd) != '':
resultList.append((hwnd, GetWindowText(hwnd)))
#Prime-Functions
def winFocus(partial_window_name):
SystemParametersInfo(8193, 0, 2 | 1)
handles=[]
EnumWindows(window_enum_handler, handles)
for i in handles:
if str(partial_window_name).upper() in str(i[1]).upper():
ShowWindow(i[0], 3)
SetForegroundWindow(i[0])
return True
print(partial_window_name + " was not found")
return False
winFocus("not existing window")
winFocus("ChroME")