#!python # -*- mode: python; Encoding: utf-8; coding: utf-8 -*- # Last updated: <2026/01/05 17:29:02 +0900> """ pywin32でウインドウを作成して、 ウインドウハンドル(HWND)を子スクリプトに渡す。 Windows11 x64 25H2 + Python 3.10.10 64bit """ import win32gui import win32con import win32api import subprocess import sys import os # 起動対象となる子プロセスのスクリプト名 CHILD_PY = "pywinsc0.py" # CHILD_PY = "pywinsc0.exe" WINDOW_CLASSNAME = "MyPythonWindowClassSample" def wnd_proc(hwnd, msg, wparam, lparam): if msg == win32con.WM_DESTROY: print("[Parent] WM_DESTROY 受信。Quit を送信。") win32gui.PostQuitMessage(0) return 0 return win32gui.DefWindowProc(hwnd, msg, wparam, lparam) def create_window_and_launch_child(): window_class_name = WINDOW_CLASSNAME wc = win32gui.WNDCLASS() wc.lpfnWndProc = wnd_proc wc.lpszClassName = window_class_name wc.hInstance = win32api.GetModuleHandle(None) # 背景色を黒に設定 bgcolor = win32gui.CreateSolidBrush(win32api.RGB(0, 128, 0)) wc.hbrBackground = bgcolor try: win32gui.RegisterClass(wc) except win32gui.error as e: # 同じクラス名が登録済み(Error code = 1410)は無視 if e.winerror != 1410: raise hwnd = win32gui.CreateWindowEx( 0, window_class_name, "Parent Window", win32con.WS_OVERLAPPEDWINDOW, # 一般的なウィンドウ形式(最小化・最大化・枠あり) win32con.CW_USEDEFAULT, # 表示位置 X(OSにお任せ) win32con.CW_USEDEFAULT, # 表示位置 Y(OSにお任せ) 640, # ウィンドウ幅 480, # ウィンドウ高さ 0, # 親ウィンドウのハンドル(今回は自身が親なので0) 0, # メニューハンドル wc.hInstance, # インスタンスハンドル None, # 追加の作成パラメータ ) if not hwnd: print("[Parent] Error: ウィンドウ作成に失敗。") return # 作成したウィンドウを表示状態にする win32gui.ShowWindow(hwnd, win32con.SW_SHOW) print(f"[Parent] ウインドウ生成。HWND: {hwnd}") # 子プロセス起動 try: # 引数として「/p HWND」を渡す print(f"[Parent] {CHILD_PY} を起動...") _, ext = os.path.splitext(CHILD_PY) if ext == ".py" or ext == ".pyw": # 起動中のPython実行環境 (sys.executable) を使って子スクリプトを実行 subprocess.Popen([sys.executable, CHILD_PY, "/p", str(hwnd)]) else: # .exe等を実行 subprocess.Popen([CHILD_PY, "/p", str(hwnd)]) except Exception as e: print(f"[Parent] 子プロセス起動に失敗: {e}") # 初回描画を強制的に促す(メッセージキューにWM_PAINTを入れる) win32gui.InvalidateRect(hwnd, None, True) # キューを待たずに、今すぐ描画を反映 win32gui.UpdateWindow(hwnd) # メッセージループ開始 # これを実行しないとウィンドウが「応答なし」になり、すぐにプログラムが終了してしまう。 # Windowsから送られてくる「再描画」「移動」等のメッセージを常に待ち受け wnd_procに振り分ける。 print("[Parent] メッセージループ開始。") win32gui.PumpMessages() print("[Parent] プロセス終了。") def main(): create_window_and_launch_child() if __name__ == "__main__": main()