1

コントロールが完全に初期化されているかどうかを確認するにはどうすればよいですか?
次のコードを検討してください(これを行うのは非常に悪い習慣であることはわかっています。例として取り上げてください)

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を知っています:-)
ありがとう!

4

1 に答える 1

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;

この話の教訓は、ログに記録しようとしているものと相互作用しない、より適切なログ フレームワークを使用する必要があるということです。

于 2012-01-02T12:29:18.700 に答える