Как проверить, когда элемент управления полностью инициализирован?

Как я могу проверить, полностью ли инициализирован элемент управления?
Рассмотрим следующий код (я знаю, что это очень плохая практика, пожалуйста, возьмите его в качестве примера)

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;

PS я знаю OutputDebugString:-)
Спасибо!

1 ответ

Решение

Ваш вопрос скорее смутил меня. Когда вы сказали:

записывать сообщения в заметку

Вы имеете в виду, что вы хотите записывать сообщения в форму, записывая текст в заметку.

Такой подход чреват опасностью, поскольку при записи в заметку форма получает отправленные сообщения, в результате чего вы записываете в заметку, и переполнение стека является неизбежным следствием.

Мне удалось воплотить вашу идею в жизнь, включив защиту от повторного входа. Я также представил временный список невизуальных строк для захвата любых сообщений, которые доставляются до того, как элемент управления будет готов их отобразить. После того, как вы это введете, вам больше не нужно беспокоиться о том, чтобы найти точный самый ранний момент, когда его можно безопасно добавить в заметку.

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;

Мораль этой истории заключается в том, что вы должны использовать более подходящую структуру ведения журнала, которая не взаимодействует с тем, что вы пытаетесь зарегистрировать.

Другие вопросы по тегам