delphi - 如何检查控件何时完全初始化?

标签 delphi winapi logging delphi-7 wndproc

如何检查控件是否已完全初始化?
考虑下面的代码(我知道这样做是非常不好的做法,请以它为例)

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;

附注我知道 OutputDebugString :-)
谢谢!

最佳答案

你的问题让我很困惑。当你说:

log messages to the memo

您的意思是您希望通过将文本写入备忘录来将消息记录到表单中。

这种方法充满了危险,因为当您写入备忘录时,表单会收到消息,这会导致您写入备忘录,并且堆栈溢出是不可避免的结果。

我设法通过添加重入保护来使你的想法发挥作用。我还引入了一个 transient 非可视字符串列表来捕获在控件准备好显示消息之前传递的任何消息。一旦介绍了这一点,您就不再需要担心找到可以安全添加到备忘录的准确最早时刻。

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;

这个故事的寓意是,您应该使用一个更合适的日志框架,该框架不会与您尝试记录的内容进行交互。

关于delphi - 如何检查控件何时完全初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8700742/

相关文章:

mysql - DELPHI 用 ADO 查询的结果填充一个列表框

delphi - 减少绘制的TChart点数

msbuild - 如何在 MSBuild 中使用特定的 Windows SDK?

c++ - 如何在 MFC 中使用 CfileDialog 选择特定文件

linux - 我如何让 VLC 2.x 在我的 Linux 下工作?

delphi - 如何让欢迎页面浏览器从 OTA 包向导中导航到某个 URI?

c++ - 使用 Win32/MFC 将 HTML 文件转换为 PDF

Python 日志记录 StreamHandler 不从模块记录日志

java - 奇怪的 JUnit 日志记录行为

delphi - 为什么 Themes.pas 在链接到 DLL 时会泄漏 TThemeServices 单例