【问题标题】:Calling Show() of embedded form should show parent form调用嵌入表单的 Show() 应该显示父表单
【发布时间】:2015-01-14 11:34:46
【问题描述】:

我在我的应用程序中使用嵌入式表单,我正在尝试这样的事情:

在设计时,表单是一个正常的表单,对嵌入/对接一无所知。 使用 ButtonClick,我可以通过调用表单的 Show() 方法使表单可见。 在运行时,表单可能会停靠到另一个表单并成为嵌入式表单。 当我按下按钮再次显示表单(现在是嵌入的)时,什么也没有发生,因为 我现在必须为包含嵌入表单的表单调用 Show()。

我正在寻找一种在调用嵌入表单的 Show() 方法时强制显示父表单的方法。我可以通过在调用 Show() 之前检查父表单的存在来处理这个问题,但我不想包含这个特定的处理。

我更愿意在父表单中进行此处理,当表单停靠时会收到通知。

Show() 方法仅将 Visible 属性设置为 true(RAD Studio 帮助),所以我认为不会触发消息...?

你知道实现这种东西的方法吗?

编辑

我想提供一些关于我的应用程序的信息,因为我猜这更像是一个设计问题而不是编程问题。

应用程序使用多个插件来适应连接的硬件。该 exe 提供了一个拖放环境,并包含一个可停靠表单的基类。插件对对接实现没有任何了解。通过创建可停靠表单并从插件嵌入表单,插件表单变得可停靠。这就是为什么我希望在某处调用嵌入表单的 Show() 方法时显示父表单的原因。

【问题讨论】:

  • 调用Show 不会做你想做的事。您想要做的事情需要通过父链找到顶层表单,并在上面调用Show。您希望显示顶级表单,但希望避免遍历父链。您是否已为您所要求的可能无法完成做好准备?
  • 一旦嵌入孩子,父母可以通过子类化并检查 WM_SHOW 等消息来挂钩到孩子窗体 WindowProc。 (最好使用GetParentForm <> nil 并简单地显示它)。
  • @DavidHeffernan 是的,我为此做好了准备 :) 我希望 vcl 有一个我还不知道的机制。
  • @kobik:即使没有触发 OnShow,WM_SHOW 也会被触发吗?

标签: delphi c++builder vcl tform


【解决方案1】:

您可以为您的嵌入式表单甚至应用程序中的所有表单创建一个共同的祖先,然后从中派生您的表单:

type
  TEmbeddedForm = class(TForm)
  public
    procedure Show;
  end;

procedure TEmbeddedForm.Show;
var
  ParentForm: TCustomForm;
begin
  inherited Show;
  ParentForm := GetParentForm(Self);
  if ParentForm <> Self then
  begin
    // Form is Embedded
    Update;        
    ParentForm.Show;
    // You might alternatively consider to send custom 
    // message to the Parent form, and let it decide what to do e.g.
    // SendMessage(ParentForm.Handle, CM_MY_EMBEDED_FORM_SHOW, 0, 0);
  end;
end;

然后当你打电话时:

procedure TForm1.Button1Click(Sender: TObject);
begin
  // MyEmbeddedForm is derived from TEmbeddedForm 
  MyEmbeddedForm.Align := alClient;
  MyEmbeddedForm.BorderStyle := bsNone;

  MyEmbeddedForm.Parent := Form3.Panel1;
  MyEmbeddedForm.Show;
end;

Form3 正在显示。


另一个选项(我只用 Spy++ 确认)是在TEmbeddedForm 中拦截WM_CHILDACTIVATEWM_WINDOWPOSCHANGING。它在子窗体调用TEmbeddedForm.Show 时发送给它,并采取相应的行动,即GetParentForm(Self).Show

【讨论】:

  • 谢谢,但这不是我想要的。我的应用程序在运行时被几个插件(bpls 和 dll)扩展。通过嵌入表单(包含在这些包中),如果我愿意,我可以给它们一个特殊的功能。当我将基类放在几个 bpls 中并加载它们时,它不会像已知的那样工作。
  • 我不确定我是否遵循最后一部分。如果你使用表单插件,建议使用一个共同的祖先,例如TPluginForm。请使用相关信息更新您的问题,因为现在我不确定您想要什么。
  • 这就是终极的意思。据我所知,我不敢告诉你,你所要求的是不可能的,不幸的是你将不得不放弃。由于您只会在嵌入表单上对Show 进行一次调用,因此您别无选择。
  • GetParentForm 永远不会为 TCustomForm 返回 nil。
  • 你不要覆盖它。你重新搽它。查看我发布的 Delphi 源代码,没有 override。我在新方法中调用inherited Show;
【解决方案2】:

在嵌入表单上使用SetFocus 而不是Show

这也将强制显示父表单。

【讨论】:

  • 很遗憾,我无法确认这一点。另外我必须先调用 Show() 否则会出现错误(不可见控件无法获得焦点 OSLT)。
  • 它要求两个表单都显示一次。这可以通过在设计器中设置Visible = True 来解决。
  • 你是对的。但是当我关闭父表单并再次调用它时,我遇到了同样的问题。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-13
  • 1970-01-01
  • 1970-01-01
  • 2013-06-15
  • 2014-03-16
相关资源
最近更新 更多