【发布时间】:2021-04-07 06:02:33
【问题描述】:
如果这是一个 XY 问题,这就是我想要做的:
我有一个 wxPython 应用程序,它必须使用 WM_COPYDATA windows 消息与另一个进程通信。虽然使用ctypes 模块发送消息非常简单,但接收答案需要我覆盖 wx 循环,因为 wx 没有为这种情况提供特定事件。
在 python2 上,我使用了 ctypes.windll.user32.SetWindowLongPtrW 和 ctypes.windll.user32.CallWindowProcW 函数来获得所需的行为。但是,在python3中,同样的代码会导致OSError: exception: access violation writing。
据我所知,python2 ctypes 模块和 python3 ctypes 模块之间的唯一区别是它们处理字符串的方式。
我还读到,两个版本的内存布局方式有所不同,但由于我不是 C 专家,我无法在我的代码中找到问题。
我已经用 python3.7 (64Bit) 和 python2.7(64Bit) 和 wx 4.0.7 测试了代码(尽管它也适用于 wx2.8 和 python2)
这是最小的可重现示例:
import ctypes, ctypes.wintypes, win32con, wx, sys
_LPARAM = ctypes.wintypes.LPARAM
_WPARAM = ctypes.wintypes.WPARAM
_HWND = ctypes.wintypes.HWND
_UINT = ctypes.wintypes.UINT
_LPCWSTR = ctypes.wintypes.LPCWSTR
_LONG_PTR = ctypes.c_long
_LRESULT = _LONG_PTR
_LPCWSTR = ctypes.wintypes.LPCWSTR
_WNDPROC = ctypes.WINFUNCTYPE(_LPARAM, # return Value
_HWND, # First Param, the handle
_UINT, # second Param, message id
_WPARAM, # third param, additional message info (depends on message id)
_LPARAM, # fourth param, additional message info (depends on message id)
)
_SetWindowLongPtrW = ctypes.windll.user32.SetWindowLongPtrW
_SetWindowLongPtrW.argtypes = (_HWND, ctypes.c_int, _WNDPROC)
_SetWindowLongPtrW.restypes = _WNDPROC
_CallWindowProc = ctypes.windll.user32.CallWindowProcW
_CallWindowProc.argtypes = (_WNDPROC, _HWND, _UINT, _WPARAM, _LPARAM)
_CallWindowProc.restypes = _LRESULT
def _WndCallback(hwnd, msg, wparam, lparam):
print(hwnd, msg, wparam, lparam)
return _CallWindowProc(_old_wndproc, hwnd, msg, _WPARAM(wparam), _LPARAM(lparam))
_mywndproc = _WNDPROC(_WndCallback)
app = wx.App(redirect=False)
frame = wx.Frame(None, title='Simple application')
frame.Show()
_old_wndproc = _WNDPROC( _SetWindowLongPtrW(frame.GetHandle(), win32con.GWL_WNDPROC, _mywndproc ) )
if _old_wndproc == 0:
print( "Error" )
sys.exit(1)
app.MainLoop()
编辑:我知道有一个 pywin32 模块,它可能会对我有所帮助。但是,由于代码适用于 python2,我很好奇这里发生了什么。
【问题讨论】:
标签: python python-3.x python-2.7 wxpython ctypes