🤹

PythonでWin32 API ①(ウィンドウの作成)

2024/01/18に公開

はじめに

PythonでWin32 APIを扱う.
基本的はウィンドウの作成を行う.

開発環境

  • Windows10 Home
  • PyCharm
  • Python3.11

定数の定義

win_const.py
WHITE_BRUSH = 0
BLACK_BRUSH = 2

CS_HREDRAW = 0x0002
CS_VREDRAW = 0x0001

CW_USEDEFAULT = 0x80000000

IDC_ARROW = 32512

WS_OVERLAPPEDWINDOW = 0x00CF0000

WM_DESTROY = 0x0002

SW_SHOWDEFAULT = 10

関数の定義

win_func.py
from ctypes import *
from ctypes.wintypes import *

WNDPROC = WINFUNCTYPE(LONG, HWND, UINT, WPARAM, LPARAM)

構造体の定義

win_struct.py
from ctypes import *
from ctypes.wintypes import *

from win_func import WNDPROC


class WNDCLASSEX(Structure):
    _fields_ = [
        ("cbSize", UINT),
        ("style", UINT),
        ("lpfnWndProc", WNDPROC),
        ("cbClsExtra", c_int),
        ("cbWndExtra", c_int),
        ("hInstance", HINSTANCE),
        ("hIcon", HICON),
        ("hCursor", HANDLE),
        ("hbrBackground", HBRUSH),
        ("lpszMenuName", LPCWSTR),
        ("lpszClassName", LPCWSTR),
        ("hIconSm", HICON),
    ]

ソースコード

main.py
from ctypes import *

from win_struct import *
from win_const import *


# dll
gdi32 = windll.gdi32
kernel32 = windll.kernel32
user32 = windll.user32


# ウィンドウプロシージャ
def WndProc(hwnd, msg, wp, lp):
    if msg == WM_DESTROY:
        user32.PostQuitMessage(0)
        return 0
    return user32.DefWindowProcW(hwnd, msg, WPARAM(wp), LPARAM(lp))


# メイン関数
def WinMain(hInstance, nCmdShow):
    # ウィンドウクラス
    wc = WNDCLASSEX()
    wc.cbSize = sizeof(WNDCLASSEX)
    wc.style = CS_HREDRAW | CS_VREDRAW
    wc.lpfnWndProc = WNDPROC(WndProc)
    wc.hInstance = hInstance
    wc.hCursor = user32.LoadCursorW(None, IDC_ARROW)
    wc.hbrBackground = HBRUSH(WHITE_BRUSH)
    wc.lpszClassName = "windowClass"

    user32.RegisterClassExW(wc)
    # ウィンドウの作成
    hwnd = user32.CreateWindowExW(
        0, "windowClass", "title",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        1080, 720,
        0, 0,
        hInstance, 0
    )
    if not hwnd:
        return 0

    user32.ShowWindow(hwnd, nCmdShow)
    user32.UpdateWindow(hwnd)

    msg = MSG()

    # ループ
    while user32.GetMessageW(byref(msg), None, 0, 0):
        user32.TranslateMessage(msg)
        user32.DispatchMessageW(msg)
    return msg.wParam


if __name__ == "__main__":
    hInstance = kernel32.GetModuleHandleW(None)
    nCmdShow = SW_SHOWDEFAULT
    WinMain(hInstance, nCmdShow)

実行結果

おわり

変数と関数の命名について,Pythonの命名規則に沿って命名するとわかりにくくなるため,C++ぽい名前にした.

参考文献

https://qiita.com/Stosstruppe/items/c94839d5e479a3447869

https://wisdom.sakura.ne.jp/system/winapi/

Discussion