gpt4 book ai didi

python user32.GetMessage 永远不会退出

转载 作者:太空宇宙 更新时间:2023-11-04 00:16:52 26 4
gpt4 key购买 nike

对于我的一些 python 应用程序,我正在使用 ctypes 和 Windows API 安装系统 Hook ,为了使它们工作,必须运行消息循环。因为我在前台发生了其他事情,所以这个消息循环被设置为作为后台线程运行。这部分工作正常,但是当我想停止这个后台线程时,我无法让它退出,GetMessage 函数应该在收到 WM_QUIT 消息时返回 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 已经被释放并且这不会导致它退出。

如何让这个线程正常退出?

最佳答案

确定我确实需要线程句柄,并且可以使用 threading.Threadnative_id 属性访问它:

#!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():
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()
tid = t.native_id

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

root.mainloop()

关于python user32.GetMessage 永远不会退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50603171/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com