Если должен или нет, это более философский, чем технический вопрос. Событие TForm.OnShow
вызывается выполнением управляющего сообщения CM_DOCKCLIENT
, которое также используется функцией ManualDock
. Внутренне это сообщение вызывает CM_SHOWINGCHANGED
, которое вызывает само событие.
В следующем примере я буду использовать две формы: Form1 (с элементом управления страницей и кнопкой) и Form2 (пустой и закрепляемый). Я предполагаю, что оба они созданы автоматически.
Следующий код является доказательством того, что событие OnShow
вызывается управляющим сообщением CM_DOCKCLIENT
. При нажатии на кнопку появляется сообщение CM_DOCKCLIENT
и запускается событие Form2 OnShow
.
Код для формы 1
procedure TForm1.FormShow(Sender: TObject);
begin
Form2.Show;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
DockObject: TDragDockObject;
begin
DockObject := TDragDockObject.Create(Form2);
try
// sending the CM_DOCKCLIENT message internally performs also the
// CM_SHOWINGCHANGED message which triggers the TForm.OnShow event
PageControl1.Perform(CM_DOCKCLIENT, WPARAM(DockObject), LPARAM(SmallPoint(0, 0)));
finally
DockObject.Free;
end;
end;
И у Form2 есть только обработчик событий OnShow
procedure TForm2.FormShow(Sender: TObject);
begin
ShowMessage('FormShow');
end;
Простой обходной путь - не закреплять Form2 вручную самостоятельно (в событии OnShow
), а прикреплять его создателем или, скажем, формой, которая его отображает. В моем предыдущем примере я отобразил Form2 в событии Form1.OnShow, поэтому я могу легко закрепить его там вручную.
procedure TForm1.FormShow(Sender: TObject);
begin
Form2.Show;
Form2.ManualDock(PageControl1);
end;
procedure TForm2.FormShow(Sender: TObject);
begin
// no manual docking of this form by itself
end;