如果这是XY问题,我想做的是:
我有一个wxPython应用程序,它必须使用WM_COPYDATA windows消息与另一个进程通信。虽然使用ctypes
模块发送消息非常容易,但接收答案需要覆盖wx循环,因为wx没有为这种情况提供特定的事件
在python2上,我使用了ctypes.windll.user32.SetWindowLongPtrW
和ctypes.windll.user32.CallWindowProcW
函数来获得所需的行为。然而,在python3中,相同的代码导致OSError: exception: access violation writing
据我所知,python2ctypes
模块和python3ctypes
模块之间的唯一区别在于它们处理字符串的方式
我还读到,这两个版本在内存布局上存在差异,但由于我不是C专家,我在代码中找不到问题
我已经用python3.7(64位)、python2.7(64位)和wx4.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上工作,我很好奇这里发生了什么
这里有一个问题:
类型
LONG_PTR
是“指针大小的整数”,它在32位和64位进程之间变化。由于您使用的是64位Python,指针是64位的,LONG_PTR
应该是:如果您希望为32位和64位Python提供更多的可移植代码,
LPARAM
在Windows标头中也被定义为LONG_PTR
,因此下面的定义将为32位和64位Python正确定义LONG_PTR,因为ctypes
已经基于Python的构建正确定义了它:在那次更改之后,我用wxPython测试了您的脚本,但仍然有一个问题。我怀疑wxPython编译时没有
UNICODE/_UNICODE
定义,因此SetWindowLongPtr和CallWindowProc API必须使用A
版本来检索和调用旧的窗口过程。我做了那个更改,下面的代码可以正常工作另一方面,在MSDN documentation中有一个关于SetWindowLongPtr(和CallWindowProc类似)的注释暗示了这个解决方案:
相关问题 更多 >
编程相关推荐