声明错误,wParam 和 lParam 参数都是 IntPtr,不长。
有一个复杂性,因为您正在尝试发送字符串。目标窗口是否启用 Unicode 很重要。SendMessage 有两个版本,SendMessageA() 和 SendMessageW()。如果程序过时并使用 8 位字符串而不是 UTF-16 编码字符串,则需要使用前者。
您可以使用 Spy++ 找出答案。使用查找工具选择应用程序的窗口。在“常规”属性选项卡中,您将看到“Window proc”。如果窗口启用了 Unicode,它将显示 (Unicode)。如果您没有看到它,则必须将字符串转换为 8 位字符。
要生成需要传递的字符串指针,可以使用 Marshal.StringToHGlobalAnsi 或 StringToHGlobalUni(分别为 8 位和 Unicode)。但是,您可以使用一个技巧让 P/Invoke marshaller 为您翻译字符串。省去通话后必须释放字符串的麻烦。对于 Ansi 版本,您可以像这样声明 API 函数:
[DllImport("user32.dll", CharSet = CharSet.Ansi, EntryPoint = "SendMessageA", ExactSpelling = true)]
private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
像这样的Unicode版本:
[DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW", ExactSpelling = true)]
private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
最后一点:如果窗口属于另一个应用程序,这将无法正常工作,你会崩溃它。您传递的指针值仅在您自己的进程中有效,在 C++ 进程中无效。要解决这个问题,您必须在目标进程中分配内存以使指针有效。这需要 OpenProcess 获取进程的句柄,VirtualAllocEx() 在目标进程中分配内存,大到足以存储字符串,WriteProcessMemory 来写入字符串。现在您可以调用 SendMessage(),使用用 IntPtr 声明的版本作为 wParam 和 lParam 参数,传递您从 VirtualAllocEx 获得的值。接下来使用 VirtualFreeEx() 释放内存并使用 CloseHandle 进行清理。或者,如果您经常这样做,请保留下一次的记忆。
相当多的 P/Invoke 在那里出错。且不说安全问题,WriteProcessMemory 需要管理员权限,需要 UAC 提升。