【问题标题】:Delphi - Sending Records as Window MessagesDelphi - 将记录作为窗口消息发送
【发布时间】:2018-09-03 15:26:58
【问题描述】:

Delphi Tokyo - 我想通过 Windows 消息在表单之间发送记录结构。具体来说,我有一个“显示运行状态”类型的窗口。当我的应用程序的其他地方发生行为时,我需要发送“更新状态窗口”类型的消息。我找到了一个通过 Windows 消息传递记录的示例(但仅在同一进程中),但在使其工作时遇到问题。具体来说,在接收端,我无法编译 Windows 消息处理程序代码。我有一个“不兼容的类型”错误,但我不知道如何进行类型转换以使其正常工作。这是适用的代码sn-ps。

在所有表单都可以访问的 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 转换回记录结构?

【问题讨论】:

    标签: delphi message record


    【解决方案1】:

    首先,为记录声明一个指针类型更容易:

    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;
    

    最后,我认为您知道,这种方法仅在发送者和接收者在同一进程中时才有效。

    【讨论】:

    • FWIW,如果没有失败,你当然也应该处理记录,但只有在你使用它之后。
    • @David:哎呀,是的,确实如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多