LoginSignup
1
1

More than 1 year has passed since last update.

Python Win32 APIでウインドウを前面に出す

Last updated at Posted at 2021-06-07

Win32 API自体、今では使う機会は少ないですが
- Win32 API(C言語)で作成されたソフトをPythonに移植したり
- exeしかないソフトに対してPythonでちょっとしたハックをしたり
するのに役立つかもしれません。

参考にした記事

Python: ctypesパターン集

前提

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);
1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1