python user32.GetMessage从不存在

2024-09-29 23:19:48 发布

您现在位置:Python中文网/ 问答频道 /正文

对于我的一些python应用程序,我正在使用ctypes和windowsapi安装系统钩子,为了使它们工作,必须运行一个消息循环。因为我有其他事情发生在前台,所以这个消息循环被设置为作为后台线程运行。这个部分工作得很好,但是当我想停止这个后台线程时,我无法让它退出,当收到WM_QUIT消息时GetMessage函数应该返回0,而我的消息循环体应该返回0,但是由于某些原因它从来没有这样做过。 我尝试过SendMessage、PostMessage、PostThreadMessage和PostQuitMessage的各种组合,但都没有成功。在

#!python3

import tkinter as tk
import ctypes
import ctypes.wintypes
from threading import Thread

user32 = ctypes.windll.user32

def loop():
    msg = ctypes.wintypes.MSG()
    while user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0:
        print('msg')
        user32.TranslateMessageW(msg)
        user32.DispatchMessageW(msg)
    print('end of loop')

def SendMessage1():
    user32.SendMessageA(0xFFFF, 0x001C, 0, 0) # broadcast handle, app_activate message

def SendMessage2():
    user32.SendMessageA(0, 0x001C, 0, 0) # null handle

def PostMessage1():
    user32.PostMessageA(0xFFFF, 0x001C, 0, 0)

def PostMessage2():
    user32.PostMessageA(0, 0x001C, 0, 0)

def PostThreadMessage1():
    user32.PostThreadMessageA(0xFFFF, 0x001C, 0, 0)

def PostThreadMessage2():
    user32.PostThreadMessageA(0, 0x001C, 0, 0)

def PostQuitMessage1():
    user32.PostQuitMessage(0)

def PostQuitMessage2():
    user32.PostQuitMessage(0)

root = tk.Tk()

t = Thread(target=loop)
t.daemon=True
t.start()

tk.Button(root, text='SendMessage 1', command=SendMessage1).pack()
tk.Button(root, text='SendMessage 2', command=SendMessage2).pack()
tk.Button(root, text='PostMessage 1', command=PostMessage1).pack()
tk.Button(root, text='PostMessage 2', command=PostMessage2).pack()
tk.Button(root, text='PostThreadMessage 1', command=PostThreadMessage1).pack()
tk.Button(root, text='PostThreadMessage 2', command=PostThreadMessage2).pack()
tk.Button(root, text='PostQuitMessage 1', command=PostQuitMessage1).pack()
tk.Button(root, text='PostQuitMessage 2', command=PostQuitMessage2).pack()

root.mainloop()

我也尝试了这些函数的A和W变量。我认为问题可能是因为我无法获取实际监听消息的线程的句柄,也找不到任何与此相关的文档。在

我还研究了在线程上下文中引发一个异常,但是由于挂起是在dll中而不是在python代码中,GIL已经被释放了,这并不能导致它退出。在

我怎样才能让这个线程优雅地退出呢?在


Tags: textimport消息defbuttonmsgrootctypes
1条回答
网友
1楼 · 发布于 2024-09-29 23:19:48

确定我确实需要线程的句柄,并且可以使用kernel32.GetCurrentThreadId()函数访问它:

#!python3

import tkinter as tk
import ctypes
import ctypes.wintypes
from threading import Thread

user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32

WM_QUIT = 0x0012

tid = None

def loop():
    global tid
    tid = kernel32.GetCurrentThreadId()
    msg = ctypes.wintypes.MSG()
    while user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0:
        print('msg')
        user32.TranslateMessage(msg)
        user32.DispatchMessageW(msg)
    print('end of loop')

def PostThreadMessage():
    user32.PostThreadMessageW(tid, WM_QUIT, 0, 0)

root = tk.Tk()

t = Thread(target=loop)
t.daemon=True
t.start()

tk.Button(root, text='PostThreadMessage', command=PostThreadMessage).pack()

root.mainloop()

相关问题 更多 >

    热门问题