Python调用SendMessage发送WM_COPYDATA仅传输字符串首字符问题
问题原因与修复方案
这个问题90%以上是收发两端字符编码处理不匹配导致的,以下是分步排查和修复方法:
1 优先排查接收端(C++ Builder端)代码
只收到第一个字符的典型场景是:接收端处理WM_COPYDATA消息时,把COPYDATASTRUCT的lpData字段当成了单字节ANSI字符串(char*)处理。你发送的是UTF-16宽字符,每个英文字符占2字节,低字节是ASCII码、高字节是0,接收端按ANSI读的时候碰到第一个0就直接截断,所以只剩首字符。
接收端修复示例:
// C++ Builder 处理WM_COPYDATA的函数 void __fastcall TForm1::WMCopyData(TMessage& Msg) { COPYDATASTRUCT* cds = (COPYDATASTRUCT*)Msg.LParam; // 这里必须用宽字符指针接收,不要用char* wchar_t* recvStr = (wchar_t*)cds->lpData; // 后续直接用recvStr即可,已经是完整宽字符串 ShowMessage(recvStr); }
如果接收端必须用ANSI处理,将发送端改成发送ANSI字符串即可。
2 发送端可选优化(避免潜在异常)
当前发送端代码有两处可优化,避免参数传递错误:
- 显式指定
SendMessageW的参数类型,防止ctypes默认类型转换出错 - 直接用Unicode缓冲区作为
lpData值,减少指针转换风险
优化后的发送端代码:
import win32con import win32gui import ctypes import ctypes.wintypes FindWindow = win32gui.FindWindow SendMessage = ctypes.windll.user32.SendMessageW # 显式指定SendMessageW的参数类型,避免ctypes默认转换错误 SendMessage.argtypes = (ctypes.wintypes.HWND, ctypes.wintypes.UINT, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM) SendMessage.restype = ctypes.wintypes.LRESULT class COPYDATASTRUCT(ctypes.Structure): _fields_ = [ ('dwData', ctypes.wintypes.LPARAM), ('cbData', ctypes.wintypes.DWORD), ('lpData', ctypes.c_void_p) # 改成void_p避免类型校验问题 ] hwnd = FindWindow(None, "SIGNAL") if not hwnd: raise Exception("未找到目标窗口") mystr = "This is a message to signal..." # 直接创建Unicode缓冲区,包含末尾的结束符 buf = ctypes.create_unicode_buffer(mystr) cds = COPYDATASTRUCT() cds.dwData = 0 cds.cbData = ctypes.sizeof(buf) cds.lpData = ctypes.cast(buf, ctypes.c_void_p) SendMessage(hwnd, win32con.WM_COPYDATA, 0, ctypes.byref(cds))
内容的提问来源于stack exchange,提问作者D.Moore
相关产品推荐
相关产品推荐

