如何使用 ctypes.windll.user32.SetWindowsHookExW 挂钩 ctypes.windll.user32.MessageBoxW?
How do I hook a ctypes.windll.user32.MessageBoxW by using ctypes.windll.user32.SetWindowsHookExW?
我想做一个笑话程序,首先它打开一个消息框,关闭后在随机位置出现另一个消息框。它会一直这样重复,直到有任何事情终止了它的任务。使用 tkinter 消息框然后那些不能挂钩,我必须制作另一个 tkinter 表单(这真的很难看并且与 Windows 消息框不同)。所以我切换到 ctypes,问题开始了。然后我为钩子创建了一个回调函数,当我将函数传递给 ctypes.windll.user32.SetWindowsHookExA 函数的第二个参数时,它显示 TypeError: wrong type。我该如何解决这个问题?
我试图将函数转换为 c_void_p,但这样做只会得到更多错误,例如 'Illegal instruction'。
这是我的代码:
import ctypes, random
def msgBoxHook(nCode, wParam, lParam):
if nCode == 3:
hwnd = ctypes.wintypes.HWND
hwnd = wParam
msgRekt = ctypes.wintypes.RECT # >:)
ctypes.windll.user32.GetWindowRect(hwnd, ctypes.byref(msgRekt))
ctypes.windll.user32.MoveWindow(hwnd, randint(0, ctypes.windll.user32.GetSystemMetrics(0)), randint(0, ctypes.windll.user32.GetSystemMetrics(1)), msgRekt.right - msgRekt.left, msgRekt.bottom - msgRekt.top, True)
return ctypes.windll.user32.CallNextHookEx(0, nCode, wParam, lParam)
# When I try to call
ctypes.windll.user32.SetWindowsHookExA(5, msgBoxHook, 0, ctypes.windll.kernel32.GetCurrentThreadId())
# It shows:
"""
Traceback (most recent call last):
File "test.py", line 1, in <module>
ctypes.ArgumentError: argument 2: <class 'TypeError'>: wrong type
"""
预期:当使用 ctypes.windll.user32.MessageBoxW(None, 'Hello', 'World', 0x00000010 | 0x00000000) 它随机打开一个消息框带有标题 'World'、文本 'Hello' 和带确定按钮的停止图标的位置。
现实:如上图
清单[Python 3.Docs]: ctypes - A foreign function library for Python.
你不能将 Python 对象传递给普通的 C 函数(我的意思是你可以,但是结果不会是预期的)。
[MS.Docs]: SetWindowsHookExA function expects an [MS.Docs]: CBTProc callback function 当它的第 1st 参数是 WH_CBT (5)。
所以,你必须包装你的函数:
WH_CBT = 5
HOOKProc = ctypes.WINFUNCTYPE(wintypes.LPVOID, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM)
CBTProc = HOOKProc
hook = ctypes.windll.user32.SetWindowsHookExA(WH_CBT, CBTProc(msgBoxHook), 0, ctypes.windll.kernel32.GetCurrentThreadId())
这应该可以帮助您解决当前的问题。但是你肯定会 运行 进入其他人(当然这可能是其他问题的主题)。
我已经发现的一个是,不要为您使用的任何函数定义 argtypes 和 restype,所以这(几乎)肯定会给你带来麻烦(崩溃)。一些例子:
我想做一个笑话程序,首先它打开一个消息框,关闭后在随机位置出现另一个消息框。它会一直这样重复,直到有任何事情终止了它的任务。使用 tkinter 消息框然后那些不能挂钩,我必须制作另一个 tkinter 表单(这真的很难看并且与 Windows 消息框不同)。所以我切换到 ctypes,问题开始了。然后我为钩子创建了一个回调函数,当我将函数传递给 ctypes.windll.user32.SetWindowsHookExA 函数的第二个参数时,它显示 TypeError: wrong type。我该如何解决这个问题?
我试图将函数转换为 c_void_p,但这样做只会得到更多错误,例如 'Illegal instruction'。
这是我的代码:
import ctypes, random
def msgBoxHook(nCode, wParam, lParam):
if nCode == 3:
hwnd = ctypes.wintypes.HWND
hwnd = wParam
msgRekt = ctypes.wintypes.RECT # >:)
ctypes.windll.user32.GetWindowRect(hwnd, ctypes.byref(msgRekt))
ctypes.windll.user32.MoveWindow(hwnd, randint(0, ctypes.windll.user32.GetSystemMetrics(0)), randint(0, ctypes.windll.user32.GetSystemMetrics(1)), msgRekt.right - msgRekt.left, msgRekt.bottom - msgRekt.top, True)
return ctypes.windll.user32.CallNextHookEx(0, nCode, wParam, lParam)
# When I try to call
ctypes.windll.user32.SetWindowsHookExA(5, msgBoxHook, 0, ctypes.windll.kernel32.GetCurrentThreadId())
# It shows:
"""
Traceback (most recent call last):
File "test.py", line 1, in <module>
ctypes.ArgumentError: argument 2: <class 'TypeError'>: wrong type
"""
预期:当使用 ctypes.windll.user32.MessageBoxW(None, 'Hello', 'World', 0x00000010 | 0x00000000) 它随机打开一个消息框带有标题 'World'、文本 'Hello' 和带确定按钮的停止图标的位置。
现实:如上图
清单[Python 3.Docs]: ctypes - A foreign function library for Python.
你不能将 Python 对象传递给普通的 C 函数(我的意思是你可以,但是结果不会是预期的)。
[MS.Docs]: SetWindowsHookExA function expects an [MS.Docs]: CBTProc callback function 当它的第 1st 参数是 WH_CBT (5)。
所以,你必须包装你的函数:
WH_CBT = 5
HOOKProc = ctypes.WINFUNCTYPE(wintypes.LPVOID, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM)
CBTProc = HOOKProc
hook = ctypes.windll.user32.SetWindowsHookExA(WH_CBT, CBTProc(msgBoxHook), 0, ctypes.windll.kernel32.GetCurrentThreadId())
这应该可以帮助您解决当前的问题。但是你肯定会 运行 进入其他人(当然这可能是其他问题的主题)。
我已经发现的一个是,不要为您使用的任何函数定义 argtypes 和 restype,所以这(几乎)肯定会给你带来麻烦(崩溃)。一些例子: