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

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

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: -)
Спасибо!

1 Ответ

4 голосов
/ 02 января 2012

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

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

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

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

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

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;

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

...