Win32 API自体、今では使う機会は少ないですが
- Win32 API(C言語)で作成されたソフトをPythonに移植したり
- exeしかないソフトに対してPythonでちょっとしたハックをしたり
するのに役立つかもしれません。
参考にした記事
前提
Win32 APIの初歩的な知識
例:ウインドウを前面に出す
ウインドウタイトルが完全にわかっている場合
使用するAPI
- FindWindowExW
- SetForegroundWindow
例えば、エクスプローラで"テスト"という名前のフォルダを開いているとき
from ctypes import *
FindWindowEx = windll.user32.FindWindowExW
SetForegroundWindow = windll.user32.SetForegroundWindow
hwnd = FindWindowEx(None, None, None, "テスト")
if hwnd != 0:
SetForegroundWindow(hwnd)
でエクスプローラが前面に出ます。
C言語で言うと、
#include <windows.h>
int main(void)
{
HWND hwnd = FindWindowExW(NULL, NULL, NULL, L"テスト");
if (hwnd != NULL)
{
SetForegroundWindow(hwnd);
}
}
このように、文字列はそのまま、NULLはNoneに置き換えます。
Win32 APIには~A,~Wと二種類存在する場合がありますが(この場合はFindWindowExA,FindWindowExW)、ASCII文字列しか使わない場合は~Aでも構いません。
FindWindowExWの仕様は、
https://docs.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-findwindowexw
これを見るとエラー(ウインドウがみつからなかった)の場合はNULLを返すことがわかるので、
if hwnd != 0:
None:でエラーチェックしています。
2021/06/12追記
NULLを返す場合は、PythonではNoneではなく0になるようでした...
!= None
では、エラーでも素通りします。
部分文字列や正規表現で検索したい場合
使用するAPI
- EnumWindows
- GetWindowText
- GetWindowTextLength
- SetForegroundWindow
FindWindowExは文字列が完全に一致しないとエラーになるので、この場合はEnumWindowsを使います。
EnumWindowsで現在開いているウインドウの一覧を取得し、コールバックにてウインドウタイトルと比較(GetWindowText)、目的のウインドウがみつかったら所望の処理をする、という流れになります。
from ctypes import *
EnumWindows = windll.user32.EnumWindows
GetWindowText = windll.user32.GetWindowTextW
GetWindowTextLength = windll.user32.GetWindowTextLengthW
SetForegroundWindow = windll.user32.SetForegroundWindow
WNDENUMPROC = WINFUNCTYPE(c_bool, POINTER(c_int), POINTER(c_int))
ghwnd = None
def EnumWindowsProc(hwnd, lParam):
global ghwnd
length = GetWindowTextLength(hwnd)
buff = create_unicode_buffer(length + 1)
GetWindowText(hwnd, buff, length + 1)
# print(buff.value)
if buff.value.startswith("テス"):
ghwnd = hwnd
return False
return True
EnumWindows(WNDENUMPROC(EnumWindowsProc), 0)
if ghwnd != None:
SetForegroundWindow(ghwnd)
一気に複雑になるので萎えますが、ポイントはウインドウタイトルを受け取るためのバッファをcreate_unicode_buffer
で確保しているところです。文字列そのものは.value
に格納されています。
C言語では以下のようになるところですが、Pythonではかえって面倒くさくなってしまうのが難点です。
char buff[20];
GetWindowTextA(hwnd, buff, 20);
printf("%s\n", buff);