我有一个奇怪的问题。
我正在使用 SendMessage 将字符串发送到同一 Windows 窗体应用程序的所有正在运行的实例。
我可以成功发送 IntPtr 指针的数值的字符串表示形式,如下所示:
unsafe private void SendString(IntPtr handle, IntPtr myHandle)
{
string s = handle.ToString(); // This will work and the value will be received.
// Try with "123553" which wont work.
// How can that be?
IntPtr lpData = Marshal.StringToHGlobalUni(s);
COPYDATASTRUCT data = new COPYDATASTRUCT();
data.dwData = 0;
data.cbData = s.Length * 2;
data.lpData = lpData;
IntPtr lpStruct = Marshal.AllocHGlobal(
Marshal.SizeOf(data));
Marshal.StructureToPtr(data, lpStruct, false);
int hTarget;
var succes = Int32.TryParse(s, out hTarget);
if (succes)
SendMessage(hTarget, WM_COPYDATA, handle, lpStruct);
}
接收应用程序正确输出类似“123553”的值。
但是,如果我手动将值分配给s
什么都没有收到:
string s = "123553";
有谁知道为什么在 IntPtr 上调用 ToString 并对值进行硬编码不会产生相同的行为?
自己运行应用程序的代码在这里:
public const int WM_COPYDATA = 0x004a;
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
[MarshalAs(UnmanagedType.I4)]
public int dwData;
[MarshalAs(UnmanagedType.I4)]
public int cbData;
[MarshalAs(UnmanagedType.SysInt)]
public IntPtr lpData;
}
[DllImport("User32.dll")]
private static extern bool SendMessage(int hWnd,
int wMsg, IntPtr wParam, IntPtr lParam);
public Form1()
{
InitializeComponent();
}
unsafe protected override void WndProc(ref Message message)
{
if (message.Msg == WM_COPYDATA)
{
COPYDATASTRUCT data = (COPYDATASTRUCT)
message.GetLParam(typeof(COPYDATASTRUCT));
string str = new string((char*)(data.lpData),
0, data.cbData / 2);
Debug.WriteLine(str);
}
base.WndProc(ref message);
}
unsafe private void SendString(IntPtr handle, IntPtr myHandle)
{
string s = handle.ToString();
IntPtr lpData = Marshal.StringToHGlobalUni(s);
COPYDATASTRUCT data = new COPYDATASTRUCT();
data.dwData = 0;
data.cbData = s.Length * 2;
data.lpData = lpData;
IntPtr lpStruct = Marshal.AllocHGlobal(
Marshal.SizeOf(data));
Marshal.StructureToPtr(data, lpStruct, false);
int hTarget;
var succes = Int32.TryParse(s, out hTarget);
if (succes)
SendMessage(hTarget, WM_COPYDATA, handle, lpStruct);
}
private void button1_Click(object sender, EventArgs e)
{
Process currentProcess = Process.GetCurrentProcess();
var handles = (from process in Process.GetProcesses()
where
process.Id != currentProcess.Id &&
process.ProcessName.Equals(
currentProcess.ProcessName,
StringComparison.Ordinal)
select process.MainWindowHandle).ToList<IntPtr>();
foreach (var handle in handles)
{
SendString(handle, this.Handle);
Debug.WriteLine(string.Format("Sending handle {0} from handle {1}", handle, this.Handle));
}
}
资料来源: