0
from ctypes import *
from ctypes.wintypes import *

WNDPROCTYPE = WINFUNCTYPE(c_int, HWND, c_uint, WPARAM, LPARAM)

WS_EX_APPWINDOW = 0x40000
WS_OVERLAPPED = 0x00000000
WS_MAXWINDOW = 0x01000000
WS_SYSMENU = 0x00080000
WS_THICKFRAME = 0x00040000
WS_MINIMIZEBOX = 0x00020000
WS_MAXIMIZEBOX = 0x00010000
WS_CAPTION = 0xC00000

SW_SHOWNORMAL = 1
SW_SHOW = 5

CS_HREDRAW = 2
CS_VREDRAW = 1

CW_USEDEFAULT = 0x80000000

WM_DESTROY = 2

WHITE_BRUSH = 0


class WNDCLASSEX(Structure):
    _fields_ = [
        ("cbSize", c_uint),
        ("style", c_uint),
        ("lpfnWndProc", WNDPROCTYPE),
        ("cbClsExtra", c_int),
        ("cbWndExtra", c_int),
        ("hInstance", HANDLE),
        ("hIcon", HANDLE),
        ("hCursor", HANDLE),
        ("hBrush", HANDLE),
        ("lpszMenuName", LPCWSTR),
        ("lpszClassName", LPCWSTR),
        ("hIconSm", HANDLE),
    ]


user32 = ctypes.WinDLL("user32", use_last_error=True)
user32.DefWindowProcW.argtypes = [HWND, c_uint, WPARAM, LPARAM]


def PyWndProcedure(hWnd, Msg, wParam, lParam):
    if Msg == WM_DESTROY:
        user32.PostQuitMessage(0)
        return 0
    return user32.DefWindowProcW(hWnd, Msg, wParam, lParam)


def main():
    WndProc = WNDPROCTYPE(PyWndProcedure)
    hInst = windll.kernel32.GetModuleHandleW(0)
    wclassName = u"My Python Win32 Class"
    wname = u"My test window"

    wndClass = WNDCLASSEX()
    wndClass.cbSize = sizeof(WNDCLASSEX)
    wndClass.style = CS_HREDRAW | CS_VREDRAW
    wndClass.lpfnWndProc = WndProc
    wndClass.cbClsExtra = 0
    wndClass.cbWndExtra = 0
    wndClass.hInstance = hInst
    wndClass.hIcon = 0
    wndClass.hCursor = 0
    wndClass.hBrush = windll.gdi32.GetStockObject(WHITE_BRUSH)
    wndClass.lpszMenuName = 0
    wndClass.lpszClassName = wclassName
    wndClass.hIconSm = 0
    egRes = windll.user32.RegisterClassExW(byref(wndClass))
    hWnd = windll.user32.CreateWindowExW(
        0,
        wclassName,
        wname,
        WS_OVERLAPPED
        | WS_CAPTION
        | WS_SYSMENU
        | WS_THICKFRAME
        | WS_MINIMIZEBOX
        | WS_MAXIMIZEBOX
        | WS_CAPTION,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        300,
        300,
        0,
        0,
        hInst,
        0,
    )

    if not hWnd:
        print("Failed to create window")
        exit(0)
    print("ShowWindow", windll.user32.ShowWindow(hWnd, SW_SHOW))
    print("UpdateWindow", windll.user32.UpdateWindow(hWnd))

    msg = MSG()
    lpmsg = pointer(msg)

    print("Entering message loop")
    # I think the problem is here
    
    while windll.user32.GetMessageA(lpmsg, 0, 0, 0) != 0:
        windll.user32.TranslateMessage(lpmsg)
        windll.user32.DispatchMessageA(lpmsg)

    print("done.")


if __name__ == "__main__":
    print("Win32 Application in python")
    main()

I have this code in Python and I am using the Windows API. This makes a simple window, and it closes the window when I press the close button, but for some reason, it does not go past the while loop. The program just stops there. How do I make it go past the while loop? Thank you. (I am new to this Windows API and it is really confusing.)

  • 1
    Why are you mixing A and W function suffix? – Anders Apr 30 '22 at 19:58
  • Agree, why not *GetMessage**W***? https://stackoverflow.com/questions/58610333/c-function-called-from-python-via-ctypes-returns-incorrect-value/58611011#58611011, https://stackoverflow.com/questions/71994439/having-trouble-using-winapi-to-read-input-from-a-device/72063735#72063735. For your case, using https://github.com/mhammond/pywin32, would drastically reduce code amount. – CristiFati Apr 30 '22 at 22:04
  • I actually fixed the issue by using PostQuitMessage. I will look into pywin32 though. – Aryan Arora May 01 '22 at 02:53

0 Answers0