Delphi - 使用窗口消息发送记录

4
Delphi Tokyo - 我想通过Windows消息在窗体之间发送记录结构。具体而言,我有一个“显示运行状态”类型的窗口。当应用程序中发生其他行为时,我需要发送“更新状态窗口”类型的消息。我已经找到了一个通过Windows消息传递记录的示例(但仅在同一进程内),但是在使其工作方面遇到了问题。具体而言,在接收端,我无法编译Windows消息处理程序代码。我遇到了“Incompatible Type”错误,但我无法弄清楚如何进行类型转换以使其工作。以下是适用的代码片段。
在globals.pas单元中,所有窗体都可以访问。
// Define my message
  const WM_BATCHDISPLAY_MESSAGE = WM_USER + $0001;
...
// Define the record which is basically the message payload
type
 TWMUCommand = record
    Min: Integer;
    Max: Integer;
    Avg: Integer;
    bOverBudget: Boolean;
    Param1: Integer;
    Param2: String;
  end;

...
// define a global variable
PWMUCommand : ^TWMUCommand;

现在要发送消息。目前这只是一个按钮,用于测试。

procedure TMainForm.BitBtn1Click(Sender: TObject);
var
  msg_prm: ^TWMUCommand;
begin
  New(msg_prm);
  msg_prm.Min := 5;
  msg_prm.Max := 10;
  msg_prm.Avg := 7;
  msg_prm.bOverBudget := True;
  msg_prm.Param1 := 0;
  msg_prm.Param2 := 'some string';
  PostMessage(Handle, WM_BATCHDISPLAY_MESSAGE, 0, Integer(msg_prm));
end;

在接收表单上,也就是我的状态表单中...声明我的消息监听器。
procedure MessageHandler(var Msg: TMessage); message WM_BATCHDISPLAY_MESSAGE;

现在定义消息处理程序。
procedure TBatchForm.MessageHandler(var Msg: TMessage);
var
   msg_prm: ^TWMUCommand;
begin
  try

    // Next line fails with Incompatible types
    msg_prm := ^TWMUCommand(Msg.LParam);
    ShowMessage(Format('min: %d; max: %d; avg: %d; ovrbdgt: %s; p1: %d; p2: %s',
                [msg_prm.Min, msg_prm.Max, msg_prm.Avg, BoolToStr(msg_prm.bOverBudget, True),
                 msg_prm.Param1, msg_prm.Param2]));
  finally
    Dispose(msg_prm);
  end;
end;

如何将 Msg.LParam 转换回记录结构?
1个回答

9
首先,为该记录声明指针类型会更容易:
type
  PWMUCommand = ^TWMUCommand;
  TWMUCommand = record
    ...
  end;

在发布消息的方法中,声明指针为 PWMUCommand

你的 Integer 转换假定是32位代码。最好转换为该参数的真实类型 LPARAM

PostMessage(..., LPARAM(msg_prm));

在接收消息的函数中,使用指针类型声明本地变量:
var
  msg_prm: PWMUCommand;

像这样进行类型转换:

msg_prm := PWMUCommand(Msg.LParam);

请注意,当您调用PostMessage时,应检查返回值以防失败。如果它失败了,则需要立即处理内存。
if not PostMessage(..., LPARAM(msg_prm)) then
begin
  Dispose(msg_prm);
  // handle error
end;

最后,我认为你已经意识到了,这种方法只适用于发送者和接收者在同一个进程中的情况。


顺便提一下,如果没有失败,当然也要处理记录,但是只有在使用后才能处理。 - Rudy Velthuis
@David:哎呀,是的,确实有。 - Rudy Velthuis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接