如何在Delphi中访问父窗体

9

我正在编写一个继承自TButton的组件。我需要在我的新组件所放置的父窗体中进行一些操作。

那么,如何从我的组件代码中访问父窗体呢?

示例代码(MyComponentCode.pas):

ButtonParent.Canvas.Pen.Color := RGB(255,255,255); // where "ButtonParent" have to be a parent form

帮我解决这个问题。谢谢。


父控件不一定是一个表单,例如它可以是TPanel。请明确您需要的是父控件还是拥有者表单。 - kludg
@user246408 我需要所有者表单。 - Alexander Seredenko
然后你需要组件的 Owner 属性;当你将一个组件拖放到窗体上时,IDE 会自动设置它;我猜你需要学习 Delphi 中 OwnerParent 的区别。 - kludg
@user246408 谢谢,对我有效。 - Alexander Seredenko
1
@user246408:如果组件在设计时被放置在TForm上,则可以保证Owner仅为TForm。如果它被放置在TFrame上,则Owner将是TFrame。如果组件在运行时通过代码动态创建,则Owner将是调用者传递给组件构造函数的对象。组件不应该对其Owner(或其Parent)做出任何假设。 - Remy Lebeau
2个回答

25

要访问您的组件所在的父级 TForm,即使您的组件实际位于另一个容器控件(如 TPanelTFrame)上,也可以使用 Vcl.Forms 单元中的 GetParentForm() 函数:

uses
  ..., Forms;

var
  Form: TCustomForm;
begin
  Form := GetParentForm(Self);
  //...
end;

2
父控件是持有该控件的控件。
如果你将控件放在一个面板上,那么该面板将成为父控件。
控件的所有者通常是包含它的表单,但这并非总是如此。如果你使用了框架,则框架将拥有其中的控件。
获取拥有控件的 表单 的方法是一直向上遍历树,直到找到真正的表单。
你可以调用 VCL.Forms.GetParentForm 方法,其代码如下:
function GetParentForm(Control: TControl; TopForm: Boolean = True): TCustomForm;
begin
  while (TopForm or not (Control is TCustomForm)) and (Control.Parent <> nil) do
    Control := Control.Parent;
  if Control is TCustomForm then
    Result := TCustomForm(Control) else
    Result := nil;
end; 

或者如果您想通过所有者进入,可以执行以下操作:

function GetOwningForm(Control: TComponent): TForm;
var
  LOwner: TComponent;
begin
  LOwner:= Control.Owner;
  while Assigned(LOwner) and not(LOwner is TCustomForm) do begin
    LOwner:= LOwner.Owner;
  end; {while}
  Result:= LOwner;
end;

重要的是要理解父级和所有者之间的区别,参见:
http://delphi.about.com/od/objectpascalide/a/owner_parent.htm 当然,您可以使用相同的技巧来使用“parent”属性。 如果一直向上遍历树(几乎)每个控件都将具有其窗体作为其父级。
(1)某些控件没有父级。

2
假设Owner链最终会导致一个TForm,但这并不是保证的。你应该使用GetParentForm()代替。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接