2

当我输入这个问题时,我意识到它可能应该。

当 form.Create() 被调用和 form.ManualDock(pagecontrol,pagecontrol.alClient) 被调用时,将表单停靠到 TPageControl 调用 FormShow。

取消停靠表单也调用显示,我认为这是因为当您停靠/取消停靠时表单实际上是“重置”?

如果这是按设计的那样,我只会将我不想在那里触发的代码重构为 onCreate(除非那是糟糕的设计)。

4

1 回答 1

2

是否应该比技术问题更具哲学性。该TForm.OnShow事件是通过执行控制消息触发的,该控制消息CM_DOCKCLIENT也由该ManualDock函数使用。在内部,此消息称为CM_SHOWINGCHANGED触发事件本身的内容。

在下面的示例中,我将使用两个表单,Form1(带有页面控件和按钮)和 Form2(空且可停靠)。我认为两者都是自动创建的。

下面的代码是控制消息OnShow触发事件的证明。CM_DOCKCLIENT单击该按钮,将执行消息并触发CM_DOCKCLIENTForm2 的事件。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;
于 2011-12-08T18:20:55.387 回答