You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 12:27:04