当我输入这个问题时,我意识到它可能应该如此。
当调用 form.Create() 和调用 form.ManualDock(pagecontrol,pagecontrol.alClient) 时,将表单停靠到 TPageControl 会调用 FormShow。
取消停靠表单也会调用 show,我认为这是因为当您停靠/取消停靠时,表单实际上是“重置”的?
如果这是按照设计的,我将重构我不想在 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;
关于delphi - TForm.ManualDock 应该调用 onFormShow 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8410574/