当我输入这个问题时,我意识到它可能应该。
当 form.Create() 被调用和 form.ManualDock(pagecontrol,pagecontrol.alClient) 被调用时,将表单停靠到 TPageControl 调用 FormShow。
取消停靠表单也调用显示,我认为这是因为当您停靠/取消停靠时表单实际上是“重置”?
如果这是按设计的那样,我只会将我不想在那里触发的代码重构为 onCreate(除非那是糟糕的设计)。
当我输入这个问题时,我意识到它可能应该。
当 form.Create() 被调用和 form.ManualDock(pagecontrol,pagecontrol.alClient) 被调用时,将表单停靠到 TPageControl 调用 FormShow。
取消停靠表单也调用显示,我认为这是因为当您停靠/取消停靠时表单实际上是“重置”?
如果这是按设计的那样,我只会将我不想在那里触发的代码重构为 onCreate(除非那是糟糕的设计)。
是否应该比技术问题更具哲学性。该TForm.OnShow
事件是通过执行控制消息触发的,该控制消息CM_DOCKCLIENT
也由该ManualDock
函数使用。在内部,此消息称为CM_SHOWINGCHANGED
触发事件本身的内容。
在下面的示例中,我将使用两个表单,Form1(带有页面控件和按钮)和 Form2(空且可停靠)。我认为两者都是自动创建的。
下面的代码是控制消息OnShow
触发事件的证明。CM_DOCKCLIENT
单击该按钮,将执行消息并触发CM_DOCKCLIENT
Form2 的事件。OnShow
Form1 代码
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
事件中),而是由创建者停靠它,或者让我们说显示它的表单。在我之前的示例中,我在 Form1.OnShow 事件中显示了 Form2,因此我可以轻松地将其手动停靠在那里。
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;