我想发送一条记录,现在只有一个字符串,但我会添加更多的变量。这是我第一次使用记录,所以这可能是一个愚蠢的问题。但是,为什么这样做:
type
TDataPipe = record
WindowTitle: String[255];
end;
var
Data: TDataPipe;
copyDataStruct : TCopyDataStruct;
begin
Data.WindowTitle:= String(PChar(HookedMessage.lParam));
copyDataStruct.dwData := 0;
copyDataStruct.cbData := SizeOf(Data);
copyDataStruct.lpData := @Data;
SendMessage(FindWindow('TForm1', nil), WM_COPYDATA, Integer(hInstance), Integer(@copyDataStruct));
end;
接收方:
type
TDataPipe = record
WindowTitle: String[255];
end;
procedure TForm1.WMCopyData(var Msg: TWMCopyData);
var
sampleRecord : TDataPipe;
begin
sampleRecord.WindowTitle:= TDataPipe(Msg.CopyDataStruct.lpData^).WindowTitle;
Memo1.Lines.Add(sampleRecord.WindowTitle);
end;
- 为什么在记录中,我使用:**
WindowTitle: String; //removed the fixed size
在发送端我使用:
Data.WindowTitle:= PChar(HookedMessage.lParam); //removed String()
它就这么不走了
我收到访问违规/应用程序冻结...
场景是:发送端是使用SetWindowsHookEx挂钩的DLL,接收端是加载/调用SetWindowsHookEx的简单exe ...
2条答案
按热度按时间vbopmzt11#
String[255]
是一个固定的256字节内存块,其中字符数据直接存储在该内存中。因此,无需序列化即可安全地跨进程边界传递。另一方面,
String
是一个动态类型。它只包含一个指向存储在内存中其他地方的字符数据的指针。因此,您不能将String
原样传递到进程边界,您传递的只是指针值,它对接收进程没有任何意义。您必须将String
数据序列化为一个平面格式,以便可以安全地传递到并由接收进程反序列化。例如:发送方:
接收方:
也就是说,在任何一种情况下,您都应该为
copyDataStruct.dwData
字段分配自己的自定义ID号。VCL本身在内部使用WM_COPYDATA
,因此您不希望这些消息与您的消息混淆,反之亦然。您可以使用RegisterWindowMessage()
创建一个唯一ID,以避免与其他WM_COPYDATA
用户使用的ID冲突:最后,
WM_COPYDATA
的WPARAM
参数是一个HWND
,而不是一个HINSTANCE
,如果发送方没有自己的HWND
,只需传递0即可,不要传递发送方的HInstance
变量。carvr3hs2#
准备:
发送人:
接收者: