我正在使用外部DLL制作一些delphi程序。 DLL在请求发送窗口消息到客户端时支持。
我定义了如下所示的打包记录:
type
// Message Packet that send from DLL
TRECV_PACKET = Packed Record
nID: Integer;
lpData: Pointer;
end;
LPRECV_PACKET = ^TRECV_PACKET;
// Request record
ReqBlock = Packed Record
id: array [0..7] of Char
end;
LPReqBlock = ^ReqBlock;
// Response record
ResBlock = Packed Record
title: array[0..255] of Char; _dt: Char;
description: array[0..1204] of Char; _time: Char;
end;
LPResBlock = ^ResBlock;
如果我发送请求,DLL会向我的客户端发送一条窗口消息。
我在文件中找到了一些解释。
DLL在RECV_PACKET
中发送memory address
个Message.LParam
。
因此,我希望使用ResBlock
获取Message.LParam
的数据。
但我写的代码只是发送破碎的数据。
我想从中获取纯数据。我能怎么做?
接收消息程序如下:
procedure TForm.OnReceiveData(var Message: TMessage);
var
recvPacket: LPRECV_PACKET;
_resBlock: LPResBlock;
begin
// Actually, I don't know why Message.LParam is parameter of LPRECV_PACKET. How it
recvPacket := LPRECV_PACKET(Message.LParam); works?
_resBlock := LPResBlock(recvPacket^.lpData);
ShowMessage(_resBlock^.title); // Broken datas...
end;
更新:
原始API定义如下:
function ETK_Request(hWnd: HWND; pszTrCode: PAnsiChar; lpData: Pointer; nDataSize: Integer; bNext: Boolean; pszContinueKey: PAnsiChar; nTimeOut: Integer): Integer; stdcall; external API_DLL;
procedure OnReceiveData(var Message: TMessage); message WM_USER + XM_RECEIVE_DATA;
答案 0 :(得分:2)
我们没有您正在查看的文档。但我确实找到this online document(不是英文),以及this header file,以及VB,C#和C ++的各种在线示例/翻译。基于这些,您的Delphi代码看起来应该更像这样:
type
// Message Packet that send from DLL
TRECV_PACKET = packed record
nRqID: Integer;
nDataLength: Integer;
nTotalDataBufferSize: Integer;
nElapsedTime: Integer;
nDataMode: Integer;
szTrCode: array[0..10] of AnsiChar;
cCont: array[0..0] of AnsiChar;
szContKey: array[0..18] of AnsiChar;
szUserData: array[0..30] of AnsiChar;
szBlockName: array[0..16] of AnsiChar;
lpData: PByte;
end;
LPRECV_PACKET = ^TRECV_PACKET;
TMSG_PACKET = packed record
nRqID: Integer;
nIsSystemError: Integer;
szMsgCode: array[0..5] of AnsiChar;
nMsgLength: Integer;
lpszMessageData: PByte;
end;
LPMSG_PACKET = ^TMSG_PACKET;
TREAL_RECV_PACKET = packed record
szTrCode: array[0..3] of AnsiChar;
nKeyLength: Integer;
szKeyData: array[0..32] of AnsiChar;
szRegKey: array[0..32] of AnsiChar;
nDataLength: Integer;
pszData: PAnsiChar;
end;
LPRECV_REAL_PACKET = ^TRECV_REAL_PACKET;
// the following records are not documented or defined (where did you get them?),
// but if the above records are any indication, the fields in these records
// should be using AnsiChar fields...
// Request record
ReqBlock = packed record
id: array [0..7] of AnsiChar;
end;
LPReqBlock = ^ReqBlock;
// Response record
ResBlock = packed record
title: array[0..255] of AnsiChar;
_dt: AnsiChar;
description: array[0..1204] of AnsiChar;
_time: AnsiChar;
end;
LPResBlock = ^ResBlock;
...
const
XM_DISCONNECT = 1;
XM_RECEIVE_DATA = 3;
XM_RECEIVE_REAL_DATA = 4;
XM_LOGIN = 5;
XM_LOGOUT = 6;
XM_TIMEOUT_DATA = 7;
const
REQUEST_DATA = 1;
MESSAGE_DATA = 2;
SYSTEM_ERROR_DATA = 3;
RELEASE_DATA = 4;
function ETK_Request(hParentWnd: HWND; pszTrCode: PAnsiChar; lpData: Pointer; nDataSize: Integer; bNext: BOOL; pszContinueKey: PAnsiChar; nTimeOut: Integer): Integer; stdcall; external API_DLL;
procedure ETK_ReleaseMessageData(lp: LPARAM); stdcall; external API_DLL;
procedure ETK_ReleaseRequestData(nRequestID: Integer); stdcall; external API_DLL;
type
TForm1 = class(TForm)
private
procedure OnReceiveData(var Message: TMessage); message WM_USER + XM_RECEIVE_DATA;
...
end;
procedure TForm1.OnReceiveData(var Message: TMessage);
var
recvPacket: LPRECV_PACKET;
_resBlock: LPResBlock;
msgPacket: LPMSG_PACKET;
begin
case Message.WParam of
REQUEST_DATA: begin
recvPacket := LPRECV_PACKET(Message.LParam);
// make sure recvPacket^.nDataLength is actually >= SizeOf(ResBlock)
// before accessing the data...
_resBlock := LPResBlock(recvPacket^.lpData);
ShowMessage(_resBlock^.title);
end;
MESSAGE_DATA: begin
msgPacket := LPMSG_PACKET(Message.LParam);
//...
ETK_ReleaseMessageData(Message.LParam);
end;
SYSTEM_ERROR_DATA: begin
msgPacket := LPMSG_PACKET(Message.LParam);
//...
ETK_ReleaseMessageData(Message.LParam);
end;
RELEASE_DATA: begin
//...
ETK_ReleaseRequestData(Message.LParam);
end;
end;
end;