一、双窗体
我们实现一个弹窗功能,Form1(主窗体)+ Form2(弹窗)
1. 操作步骤
- 新建项目,Form1 拖入 Button1,修改
Caption = Open Form2,生成OnClick事件(可以直接在设计窗体双击按钮也可以快速创建点击事件); - 顶部菜单
File → New Form,创建 Form2; - Form2 放 Button1,
Caption = Close,生成OnClick; - 切换窗体快捷键:
Shift+F12窗体列表 /F12切换设计/代码; - Unit1 引用 Unit2:在
interface uses添加Unit2。
Unit1(主窗体)
主要有两处要注意,Unit2; //引入Unit2
还有一个地方就是在点击函数里面,已模态框的方式打开窗口2,Form2.ShowModal; // 模态弹出Form2
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Unit2; //引入Unit2
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.ShowModal; // 模态弹出Form2
end;
end.
Unit2(子窗体)
在文件中添加第二个窗体

添加完后,编辑框中会多出一个选项卡
一个是主窗口的,一个是窗口2的的后台代码


如果你想设置窗口2,只需要选择Unit2,然后按F12就可以。就可以打开窗体2的设计窗口

然后像前面的课程一样,添加一个按钮,修改名字为Close,然后添加关闭功能。前面的课程学过,读者可以自己完成。
unit Unit2;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
{ TForm2 }
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form2: TForm2;
implementation
{$R *.lfm}
procedure TForm2.Button1Click(Sender: TObject);
begin
Close; // 关闭当前Form2
end;
end.

二、Show 与 ShowModal 核心区别(对比示例)
界面改造
Form1 添加两个按钮:
- btnShow:Caption = Show
- btnShowModal:Caption = ShowModal

// 非模态 Show
procedure TForm1.btnShowClick(Sender: TObject);
begin
Form2.Show;
ShowMessage('Form2 已打开,主窗体可操作');
end;
// 模态 ShowModal
procedure TForm1.btnShowModalClick(Sender: TObject);
begin
Form2.ShowModal;
ShowMessage('必须关闭Form2才会弹出此提示');
end;Code language: JavaScript (javascript)
差异说明
Show(非模态)
- 打开子窗体后代码继续往下执行;
- 主窗体可拖动、点击其他按钮;
- 等价
Form2.Visible := True;,且自动置顶。
ShowModal(模态弹窗)
- 代码暂停,直到子窗体关闭才继续执行;
- 主窗体锁定,无法操作;
- 是函数,可返回
ModalResult判断关闭方式。
一句话概括就是,模态框模式打开的话,子窗口必须关闭了才可以操作主窗口的任何东西,而非模态框打开子窗口后,还可以操作主窗口。
三、窗体互相调用:解决循环引用报错
需求:Form1 打开 Form2,Form2 打开 Form1
直接在 interface uses 互相引用会报循环单元错误,解决方案:把引用写到 implementation 段
Unit1
unit Unit1;
interface
uses Forms,StdCtrls;
type
TForm1=class(TForm)
Button1:TButton;
procedure Button1Click(Sender:TObject);
end;
var Form1:TForm1;
implementation
uses Unit2; // 引用放此处
{$R *.lfm}
procedure TForm1.Button1Click(Sender:TObject);
begin
Form2.Show;
end;
end.
Unit2
unit Unit2;
interface
uses Forms,StdCtrls;
type
TForm2=class(TForm)
Button1:TButton;
procedure Button1Click(Sender:TObject);
end;
var Form2:TForm2;
implementation
uses Unit1; // 互相引用放实现区
{$R *.lfm}
procedure TForm2.Button1Click(Sender:TObject);
begin
Form1.Show;
end;
end.
四、窗体之间传值(公用成员变量示例)
功能:主窗体点击打开子窗体时计数,子窗体可查看打开次数
Unit2 定义公共整型变量
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
Count: Integer; // 公共变量,Unit1可访问
end;
Unit1 点击按钮自增计数
procedure TForm1.Button1Click(Sender: TObject);
begin
Inc(Form2.Count); // 计数+1
Form2.ShowModal;
end;Code language: JavaScript (javascript)
Unit2 弹窗显示次数
procedure TForm2.Button1Click(Sender: TObject);
begin
ShowMessage('此窗体已打开 '+IntToStr(Count)+' 次');
end;Code language: JavaScript (javascript)
规范建议:尽量少用全局/公共变量,推荐使用属性 Property 传参。
五、动态创建窗体
不依赖项目自动生成全局Form变量
方式1:动态创建设计好的Form2
- 打开
Project.lpr,删除Application.CreateForm(TForm2, Form2); - Form1按钮代码:
procedure TForm1.Button1Click(Sender: TObject);
var
frm2: TForm2;
begin
frm2 := TForm2.Create(nil); // 手动创建
frm2.ShowModal;
FreeAndNil(frm2); // 释放内存,防止泄漏
end;Code language: JavaScript (javascript)
方式2:完全代码生成窗体(无需提前设计)
点击按钮生成全新窗体+内置关闭按钮
unit Unit1;
interface
uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
procedure DynamicBtnClick(Sender: TObject); // 自定义按钮点击事件
public
end;
var Form1: TForm1;
implementation
{$R *.lfm}
procedure TForm1.DynamicBtnClick(Sender: TObject);
begin
ShowMessage('即将关闭动态窗体');
TForm(TButton(Sender).Parent).Close;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MyForm: TForm;
MyBtn: TButton;
begin
MyForm := TForm.Create(nil);
MyForm.SetBounds(100,100,220,150);
MyForm.Caption := '动态生成窗体';
// 创建按钮,所有者为MyForm,释放时自动销毁按钮
MyBtn := TButton.Create(MyForm);
MyBtn.SetBounds(10,10,200,30);
MyBtn.Caption := '关闭窗体';
MyBtn.Parent := MyForm;
MyBtn.OnClick := @DynamicBtnClick;
MyForm.ShowModal;
FreeAndNil(MyForm);
end;
end.
出现Choose Debug Information format



设置一下调试格式就可以。
Previous: Lazarus IDE 编辑器窗口介绍