【问题标题】:Delphi - How to access a form from a childwindow in a mdi-applicationDelphi - 如何从 mdi 应用程序中的子窗口访问表单
【发布时间】:2025-12-21 21:40:12
【问题描述】:

我有一个带有子窗口的 MDI 程序,其中包含一个 TMemo 和一个按钮,应用程序中还有另一个 Form1。 点击按钮:

Unit1.Form1.Parent:=Form1;
Unit1.Form1.Show;

Form1 上也是一个按钮:

????.(FindComponent('dataMm') as TMemo).lines.append('hallo child');

我的问题是:替换 ???? 的正确语法是什么?访问子窗体上的 TMemo。

PS.:TMainForm 有以下过程:

Procedure TMainForm.CreateMDIChild(const Name: string);
var
  Child: TMDIChild;
begin
  Child := TMDIChild.Create(Application);
  MyChild:=Child;
end;

其中 MyChild 在公共部分中声明为

var MyChild: TForm;

感谢您的时间和关注 问候

【问题讨论】:

  • 如果为 yare 创建了多个子实例会怎样?
  • 感谢您提出一个好问题。但是,结构并不是很清楚。请编辑并列出相关单位及其各自的内容。您是否有 2 个名为 Form1 的表单(您说:还有 另一个 Form1)?你为什么不改名字?我不明白你为什么使用FindComponent。如果备忘录是在设计时创建的,您可以直接使用FormName.MemoName 参考备忘录。您可以按名称引用其他单位。所以,请澄清。如果实际类型是TMDIChild,为什么还要声明var MyChild: TForm;

标签: delphi mdi


【解决方案1】:

在撰写此答案时,您尚未回复我要求澄清的评论,但我相信我理解您的问题。

所以这里是主要形式的精髓:

unit UMain;

uses
  ..., UChild, ...
    
type
  TMDIMainForm = class(TForm)
    MainMenu1: TMainMenu;
    CreateChild1: TMenuItem;
    ShowForm11: TMenuItem;
    ...
  public
    MyChild: TMDIChild;

由于您通常有许多子表单实例,因此您需要使用列表或数组而不是 MyChild 变量,但这是您定义的。

以及那些菜单项的实现,以及CreateMDIChild方法:

procedure TMDIMainForm.CreateChild1Click(Sender: TObject);
begin
  CreateMDIChild('TheOneAndOnly');
end;

procedure TMDIMainForm.ShowForm11Click(Sender: TObject);
begin
  Form1.Show;
end;

procedure TMDIMainForm.CreateMDIChild(const name: string);
//var
//  Child: TMDIChild;  no need for this temporary variable
begin
  MyChild := TMDIChild.Create(Application);
  MyChild.Parent := self;
  MyChild.Visible := True;
//  MyChild:=Child;
end;

TMDIChild 类很简单:

unit UChild;

type
  TMDIChild = class(TForm)
    dataMm: TMemo;
  end;

因为它只包含备忘录(出于本次讨论的目的)。

最后是TForm1 类:

unit UForm1;

interface
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

implementation

uses UMain, UChild;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MDIMainForm.MyChild.dataMm.Lines.Add('hello child!')
end;

我想我们现在已经解决了您的实际问题,即如何处理 MyChild 表单中的备忘录。

因此,请注意您需要添加 uses UMain, UChild; 子句来引用这些单位。这个uses 子句必须在implementation 部分中。如果它在interfacepart 中,它会创建一个循环引用,这是被禁止的。

现在您可以在子窗体中引用备忘录,它在主窗体中有引用。


编辑

在您在评论中澄清后:(“实际上,使 Form1 可见的按钮在孩子身上,这可能发生在任何孩子身上。比在 Form1 上激活按钮:dataMm.Lines.Add('hello child!')。我需要一个引用或连接到这个当前活动的孩子”,您可以执行以下操作:

TForm1 类型中添加一个新的私有字段来保存MDIChild 引用,以及一个新方法,您可以在其中传递调用MDIChild 的引用,例如

TForm1 = class(TForm)
...
private
  CurrentMDIChild: TMDIChild;
public
  procedure DoActivate(Sender: TMDIChild);

DoActivate()的实现变成:

procedure TForm1.DoActivate(Sender: TMDIChild);
begin
  if (Sender is TMDIChild) then
  begin
    CurrentMDIChild := Sender;
    Show;
  end;
end;

TMDIChild.Button1Click 变成例如

procedure TMDIChild.Button1Click(Sender: TObject);
begin
  Form1.DoActivate(self); 
end;

【讨论】:

  • 实际上,使 Form1 可见的 Button 位于孩子身上,这可能发生在任何孩子身上。比在 Form1 上激活一个按钮:dataMm.Lines.Add('hello child!')。我需要对这个当前活跃的孩子的参考或联系。对不起我的英语,谢谢你的帮助。
最近更新 更多