Reputation: 3238
Delphi Tokyo - I am wanting to send a record structure between forms via Windows Messages. Specifically, I have a "display running status" type of window. When behaviors occur elsewhere in my application, I need to send an "update the status window" type of message. I have found an example which passes a record via windows messages (but only within the same process), but am having issues making it work. Specifically, on the receiving side, I am having trouble compiling the windows message handler code. I have an 'Incompatible Type' error, but I can't figure out how to typecast to get it working. Here are the applicable code snippets.
In a globals.pas unit, which all forms access.
// 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;
Now for the sending of the message. This is currently just a button in order to test.
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;
On the receiving form, aka my status form... declare my message listener
procedure MessageHandler(var Msg: TMessage); message WM_BATCHDISPLAY_MESSAGE;
Now define the message handler.
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;
How do I cast Msg.LParam back into the record structure?
Upvotes: 4
Views: 2487
Reputation: 612804
First of all, it's easier to declare a pointer type for the record:
type
PWMUCommand = ^TWMUCommand;
TWMUCommand = record
...
end;
Then in the method that posts the message, declare the pointer to be PWMUCommand
.
Your Integer
cast assumes 32 bit code. Better to cast to the true type of that argument which is LPARAM
.
PostMessage(..., LPARAM(msg_prm));
In the function the receives the message, declare the local variable using the pointer type:
var
msg_prm: PWMUCommand;
Cast it like this:
msg_prm := PWMUCommand(Msg.LParam);
Note that when you call PostMessage
you should check the return value in case of failure. If it fails, then you need to dispose of the memory then.
if not PostMessage(..., LPARAM(msg_prm)) then
begin
Dispose(msg_prm);
// handle error
end;
Finally, as I think that you are aware, this approach only works if the sender and receiver are in the same process.
Upvotes: 9