如何检查控件是否已完全初始化?
请考虑以下代码(我知道这样做非常糟糕,请以此为例)
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。我知道OutputDebugString :-)
谢谢!
答案 0 :(得分:4)
你的问题让我很困惑。当你说:
将消息记录到备忘录
您的意思是您希望通过将文本写入备忘录来将消息记录到表单中。
这种方法充满了危险,因为当您写入备忘录时,表单会发送消息,导致您写入备忘录,并且堆栈溢出是不可避免的后果。
我设法通过提供重新保护来让你的想法变得有意义。我还引入了一个瞬态非可视字符串列表来捕获在控件准备好显示它们之前传递的任何消息。一旦你介绍了这个,你就不再需要担心找到可以安全添加到备忘录的最早时刻了。
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;
故事的寓意是你应该使用一个更合适的日志框架,不会与你想要记录的内容进行交互。