How can I check if the control is fully initialized ?
Consider the following code (I know it's very bad practice to do this, please take it as an example)
type
TForm1 = class(TForm)
Memo1: TMemo;
private
procedure WndProc(var Message: TMessage); override;
public
{ Public declarations }
end;
procedure TForm1.WndProc(var Message: TMessage);
begin
{
I'd like to log the messages to the memo as soon
as it's possible so I need to find out how to
check if the memo box is ready to use; the following
code stuck the application, so that the form is not
even displayed. How would you fix this code except
"avoid using of component access in window proc" ?
}
if Assigned(Memo1) then
if Memo1.HandleAllocated then
Memo1.Lines.Add('Message: ' + IntToStr(Message.Msg));
inherited WndProc(Message);
end;
P.S. I know OutputDebugString :-)
Thanks!
Your question rather confused me. When you said:
log messages to the memo
What you mean is that you want to log messages to the form by writing text to the memo.
That approach is fraught with danger since when you write to the memo, the form gets sent messages which results in you writing to the memo and a stack overflow is the inevitable consequence.
I managed to make your idea sort of work by putting in re-entrancy protection. I also introduced a transient non-visual string list to capture any messages that are delivered before the control is ready to display them. Once you introduce this then you no longer need to worry about finding the precise earliest moment at which it is safe to add to the memo.
unit LoggingHack;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TLoggingForm = class(TForm)
Memo1: TMemo;
private
FLog: TStringList;
FLogging: Boolean;
protected
procedure WndProc(var Message: TMessage); override;
public
destructor Destroy; override;
end;
var
LoggingForm: TLoggingForm;
implementation
{$R *.dfm}
{ TLoggingForm }
destructor TLoggingForm.Destroy;
begin
FreeAndNil(FLog);
inherited;
end;
procedure TLoggingForm.WndProc(var Message: TMessage);
var
Msg: string;
begin
if not FLogging then begin
FLogging := True;
Try
Msg := IntToStr(Message.Msg);
if Assigned(Memo1) and Memo1.HandleAllocated then begin
if Assigned(FLog) then begin
Memo1.Lines.Assign(FLog);
FreeAndNil(FLog);
end;
Memo1.Lines.Add(Msg);
end else if not (csDestroying in ComponentState) then begin
if not Assigned(FLog) then begin
FLog := TStringList.Create;
end;
FLog.Add(Msg);
end;
Finally
FLogging := False;
End;
end;
inherited;
end;
end.
end;
The moral of the story is that you should use a more appropriate logging framework that does not interact with what you are trying to log.