Как проверить, когда элемент управления полностью инициализирован?
Как я могу проверить, полностью ли инициализирован элемент управления?
Рассмотрим следующий код (я знаю, что это очень плохая практика, пожалуйста, возьмите его в качестве примера)
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;
Мораль этой истории заключается в том, что вы должны использовать более подходящую структуру ведения журнала, которая не взаимодействует с тем, что вы пытаетесь зарегистрировать.