patternMinor
Sending a string from anonymous thread to UI with PostMessage
Viewed 0 times
anonymouswithsendingthreadfrompostmessagestring
Problem
I am sending a string from an anonymous thread to the UI with
This works seemingly well, but could this potentially create memory leaks? Or is there a better way to accomplish this?
PostMessage in the following code:unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
const
WM_SETCAPTION = WM_USER;
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure WMSetCaption(var msg: TMessage); message WM_SETCAPTION;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.WMSetCaption(var msg: TMessage);
begin
Self.Caption := PChar(msg.LParam);
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
System.Classes.TThread.CreateAnonymousThread(
procedure
begin
PostMessage(Handle, WM_SETCAPTION, 0, LParam(PChar('My new caption')));
end).Start;
end;
end.This works seemingly well, but could this potentially create memory leaks? Or is there a better way to accomplish this?
Solution
Create an object containing the string as a property and pass the pointer to the object as
Integer LParam. Then, in the message handler, use the string and free the object. In this way, you could not only send strings but also other data as well.unit SendingStringWithPostMessageUsingObjectMainForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
const
WM_STRINGMESSAGE = WM_USER;
type
TStrMsgObject = class(TObject)
private
fMsg: string;
public
constructor Create(const aMsg: string);
property Msg: string read fMsg;
end;
type
TForm2 = class(TForm)
btnSetCaption: TButton;
btnChangeCaption: TButton;
procedure btnChangeCaptionClick(Sender: TObject);
procedure btnSetCaptionClick(Sender: TObject);
private
{ Private declarations }
procedure WMStringMessage(var Msg: TMessage); message WM_STRINGMESSAGE;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
const
// WM_STRINGMESSAGE Actions:
ACTION_SETCAPTION = 0;
ACTION_CHANGECAPTION = 1;
constructor TStrMsgObject.Create(const aMsg: string);
begin
inherited Create;
fMsg := aMsg;
end;
procedure TForm2.WMStringMessage(var Msg: TMessage);
// Process WM_STRINGMESSAGE messages
var
mo: TStrMsgObject;
begin
mo := TStrMsgObject(Msg.LParam);
try
case Msg.WParam of
ACTION_SETCAPTION:
begin
Caption := mo.Msg;
end;
ACTION_CHANGECAPTION:
begin
Caption := Caption + mo.Msg;
end;
end
finally
mo.Free;
end;
end;
procedure TForm2.btnSetCaptionClick(Sender: TObject);
begin
System.Classes.TThread.CreateAnonymousThread(
procedure
begin
PostMessage(Handle, WM_STRINGMESSAGE, ACTION_SETCAPTION, Integer(TStrMsgObject.Create('My new caption')));
end).Start;
end;
procedure TForm2.btnChangeCaptionClick(Sender: TObject);
begin
System.Classes.TThread.CreateAnonymousThread(
procedure
begin
PostMessage(Handle, WM_STRINGMESSAGE, ACTION_CHANGECAPTION, Integer(TStrMsgObject.Create(' changed')));
end).Start;
end;
end.Code Snippets
unit SendingStringWithPostMessageUsingObjectMainForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
const
WM_STRINGMESSAGE = WM_USER;
type
TStrMsgObject = class(TObject)
private
fMsg: string;
public
constructor Create(const aMsg: string);
property Msg: string read fMsg;
end;
type
TForm2 = class(TForm)
btnSetCaption: TButton;
btnChangeCaption: TButton;
procedure btnChangeCaptionClick(Sender: TObject);
procedure btnSetCaptionClick(Sender: TObject);
private
{ Private declarations }
procedure WMStringMessage(var Msg: TMessage); message WM_STRINGMESSAGE;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
const
// WM_STRINGMESSAGE Actions:
ACTION_SETCAPTION = 0;
ACTION_CHANGECAPTION = 1;
constructor TStrMsgObject.Create(const aMsg: string);
begin
inherited Create;
fMsg := aMsg;
end;
procedure TForm2.WMStringMessage(var Msg: TMessage);
// Process WM_STRINGMESSAGE messages
var
mo: TStrMsgObject;
begin
mo := TStrMsgObject(Msg.LParam);
try
case Msg.WParam of
ACTION_SETCAPTION:
begin
Caption := mo.Msg;
end;
ACTION_CHANGECAPTION:
begin
Caption := Caption + mo.Msg;
end;
end
finally
mo.Free;
end;
end;
procedure TForm2.btnSetCaptionClick(Sender: TObject);
begin
System.Classes.TThread.CreateAnonymousThread(
procedure
begin
PostMessage(Handle, WM_STRINGMESSAGE, ACTION_SETCAPTION, Integer(TStrMsgObject.Create('My new caption')));
end).Start;
end;
procedure TForm2.btnChangeCaptionClick(Sender: TObject);
begin
System.Classes.TThread.CreateAnonymousThread(
procedure
begin
PostMessage(Handle, WM_STRINGMESSAGE, ACTION_CHANGECAPTION, Integer(TStrMsgObject.Create(' changed')));
end).Start;
end;
end.Context
StackExchange Code Review Q#162167, answer score: 4
Revisions (0)
No revisions yet.