如何根据变量中的窗体名创建TForm并传递参数?
动态创建窗体并传递参数的解决方案
下面几种方案可以解决你通过变量指定窗体名称创建实例时的参数传递问题:
方案1:通过公共属性/方法直接传递
这是最直观的方式,给需要接收参数的窗体类定义统一的公共属性或方法,创建窗体后强制类型转换并赋值/调用。
步骤1:给目标窗体定义公共属性
// 示例目标窗体类 type TMyForm = class(TForm) private FUserId: Integer; FUserName: string; public // 定义可写的公共属性 property UserId: Integer read FUserId write FUserId; property UserName: string read FUserName write FUserName; // 或者用方法批量传参 procedure InitParams(AUserId: Integer; AUserName: string); end; // 方法实现示例 procedure TMyForm.InitParams(AUserId: Integer; AUserName: string); begin FUserId := AUserId; FUserName := AUserName; // 这里可以直接用参数初始化控件,比如给Label赋值 lblUserName.Caption := AUserName; end;
步骤2:修改创建窗体的代码
procedure TFrmTeste.CriaForm(FormName: String); var FrmClass: TFormClass; Frm: TForm; begin FrmClass := TFormClass(FindClass(FormName)); Frm := FrmClass.Create(Application); try // 判断窗体类型,然后传递参数 if Frm is TMyForm then begin // 方式1:直接给属性赋值 TMyForm(Frm).UserId := 1001; TMyForm(Frm).UserName := '张三'; // 方式2:调用批量传参方法 // TMyForm(Frm).InitParams(1001, '张三'); end // 可以添加其他窗体类型的判断逻辑 else if Frm is TOtherForm then begin TOtherForm(Frm).SomeParam := '其他参数'; end; Frm.ShowModal; finally Frm.Free; end; end;
方案2:用接口统一规范参数传递
定义一个带参数设置方法的接口,让所有需要传参的窗体实现该接口,创建后通过接口传递参数,避免大量类型判断。
步骤1:定义接口
// 生成GUID可以用Delphi的Ctrl+Shift+G快捷键 type IFormParamSetter = interface ['{E8B5F6D3-4F1A-4C7D-9E2B-1A3F4D7C8E90}'] procedure SetUserParams(AUserId: Integer; AUserName: string); end;
步骤2:目标窗体实现接口
type TMyForm = class(TForm, IFormParamSetter) private FUserId: Integer; FUserName: string; public procedure SetUserParams(AUserId: Integer; AUserName: string); end; procedure TMyForm.SetUserParams(AUserId: Integer; AUserName: string); begin FUserId := AUserId; FUserName := AUserName; lblUserName.Caption := '当前用户:' + AUserName; end;
步骤3:修改创建代码
procedure TFrmTeste.CriaForm(FormName: String); var FrmClass: TFormClass; Frm: TForm; ParamSetter: IFormParamSetter; begin FrmClass := TFormClass(FindClass(FormName)); Frm := FrmClass.Create(Application); try // 尝试获取接口,支持就传参 if Supports(Frm, IFormParamSetter, ParamSetter) then begin ParamSetter.SetUserParams(1001, '张三'); end; Frm.ShowModal; finally Frm.Free; end; end;
方案3:用RTTI动态设置属性
如果不想修改窗体类的结构,可以借助RTTI(运行时类型信息)直接设置窗体的公共属性,适合参数较多且分散的场景。
代码示例(需引用RTTI单元)
uses RTTI; procedure TFrmTeste.CriaForm(FormName: String); var FrmClass: TFormClass; Frm: TForm; RttiCtx: TRttiContext; RttiType: TRttiType; TargetProp: TRttiProperty; begin FrmClass := TFormClass(FindClass(FormName)); Frm := FrmClass.Create(Application); try RttiCtx := TRttiContext.Create; try RttiType := RttiCtx.GetType(Frm.ClassType); // 设置UserId属性 TargetProp := RttiType.GetProperty('UserId'); if Assigned(TargetProp) and TargetProp.IsWritable then TargetProp.SetValue(Frm, 1001); // 设置UserName属性 TargetProp := RttiType.GetProperty('UserName'); if Assigned(TargetProp) and TargetProp.IsWritable then TargetProp.SetValue(Frm, '张三'); finally RttiCtx.Free; end; Frm.ShowModal; finally Frm.Free; end; end;
方案4:自定义构造函数(需统一窗体基类)
如果必须通过构造函数传参,可以定义一个带参数的构造函数,让所有目标窗体继承并实现该构造函数。
步骤1:定义带参数的窗体类引用
type TFormWithParamsClass = class of TForm public constructor CreateWithParams(AOwner: TComponent; AUserId: Integer; AUserName: string); reintroduce; virtual; end; // 基类构造函数实现 constructor TFormWithParamsClass.CreateWithParams(AOwner: TComponent; AUserId: Integer; AUserName: string); begin inherited Create(AOwner); // 基类逻辑留空,子类重写实现参数处理 end;
步骤2:目标窗体实现自定义构造函数
type TMyForm = class(TForm, TFormWithParamsClass) private FUserId: Integer; FUserName: string; public constructor CreateWithParams(AOwner: TComponent; AUserId: Integer; AUserName: string); override; end; constructor TMyForm.CreateWithParams(AOwner: TComponent; AUserId: Integer; AUserName: string); begin inherited CreateWithParams(AOwner, AUserId, AUserName); FUserId := AUserId; FUserName := AUserName; lblUserName.Caption := '用户:' + AUserName; end;
步骤3:修改创建代码
procedure TFrmTeste.CriaForm(FormName: String); var FrmClass: TFormWithParamsClass; Frm: TForm; begin FrmClass := TFormWithParamsClass(FindClass(FormName)); // 直接调用自定义构造函数传参 Frm := FrmClass.CreateWithParams(Application, 1001, '张三'); try Frm.ShowModal; finally Frm.Free; end; end;
内容的提问来源于stack exchange,提问作者Renato Benedetti
相关产品推荐
相关产品推荐

