Windows消息机制在python中的使用


写在前面

此问题是在不同线程之间通信时出现的,在开始下一次任务之前,要确保某个子线程已退出(后来才想到在适当地方join前述子线程就可以了),不过当时已经使用PostMessage实现了不同线程通信,在此记录一下,或许他日有用。

实现代码

import ctypes
WM_USER = 0x400
WM_PLAYER_STOP = WM_USER + 0x1
# 用于接收消息,在接收到消息之前将阻塞进程
GetMessageW = ctypes.windll.user32.GetMessageW
GetMessageW.argtypes = [ctypes.POINTER(ctypes.wintypes.MSG), ctypes.wintypes.HWND, ctypes.c_uint, ctypes.c_uint]
# 此方法只能将消息发送到同一线程
PostMessageW = ctypes.windll.user32.PostMessageW
PostMessageW.argtypes = [ctypes.wintypes.HWND,ctypes.c_uint,ctypes.wintypes.HINSTANCE, ctypes.c_uint]
# 此方法大致等同于GetMessage,具体见MSDN
PeekMessageW = ctypes.windll.user32.PeekMessageW
PeekMessageW.argtypes = [ctypes.POINTER(ctypes.wintypes.MSG), ctypes.wintypes.HWND, ctypes.c_uint, ctypes.c_uint,ctypes.c_int]
# 此方法可以将消息发送到指定的线程
PostThreadMessageW = ctypes.windll.user32.PostThreadMessageW
PostThreadMessageW.argtypes = [ctypes.wintypes.DWORD,ctypes.c_uint,ctypes.wintypes.HINSTANCE, ctypes.c_uint]
# 用于接收到消息之后的后续处理
DispatchMessageW = ctypes.windll.user32.DispatchMessageW
TranslateMessage = ctypes.windll.user32.TranslateMessage
TranslateMessage.argtypes = [ctypes.POINTER(ctypes.wintypes.MSG)]
DispatchMessageW.argtypes = [ctypes.POINTER(ctypes.wintypes.MSG)]

def postmessage():
    # threading.main_thread().ident为主线程的ID
    PostThreadMessageW(ctypes.wintypes.DWORD(threading.main_thread().ident),ctypes.c_uint(WM_PLAYER_STOP),ctypes.wintypes.HINSTANCE(WM_PLAYER_STOP),ctypes.c_uint(0))

def testgetmsg():
    # 创建子线程,子线程向主线程发送一条消息
    t = threading.Thread(target = postmessage)
    t.start()
    t.join()
    # 主线程发送消息
    PostMessageW(ctypes.wintypes.HWND(0),ctypes.c_uint(WM_PLAYER_STOP),ctypes.wintypes.HINSTANCE(WM_PLAYER_STOP),ctypes.c_uint(0))
    ctypes.windll.user32.PostQuitMessage(0)
    # Windows消息结构体
    message = ctypes.wintypes.MSG()
    while True:
        # 第一个参数是message对象的指针,第二个参数是目标窗口句柄,后面两个参数为消息类型的搜索范围
        msg = GetMessageW(ctypes.byref(message), 0, WM_USER, WM_USER + 100)
        if message.message == WM_PLAYER_STOP:
            print(message.message)
        if msg in [0,-1]:
            break
        else:
            TranslateMessage(ctypes.byref(message))
            DispatchMessageW(ctypes.byref(message))