原创。通过窗体的类名(字符串)的情况下,创建一个该窗体实列

kuangning 2003-06-03 12:36:47
有朋友和我讨论过,已经知道一个类名,怎么才能创建一个实列。一个偶然的机会发现很好做。
用Tform来做个试验吧。
1、新建工程,主form为form1,保存为unit1,添加一个form2,保存为unit2。
2、 在unit2中TForm2 = class(TForm)前面加上
TmyForm = class of Tform2;//相当于给Tform2加上一个别名
3、 在form1的FormCreate中写入RegisterClasses([TForm2]);//注册Tform2类
4、 在form1的button的单击事件中加入
var
A : Tform ;
begin
if GetClass('TForm2') =nil then exit ;
a := TMyform(GetClass('TForm2')).Create(nil);
a.show;
end;
搞定!
当然很多情况下,大家不会这样做。不过也可以试验一下。
比如,我有很多地方都需要调用各种的参数配置对话框,然而,我想偷懒,不想写太多的代码。我就可以通过发自定义消息的办法。先将所有的对话框类名写入一个数组中去。在需要调用的参数配置对话框的时候,发一个消息。接收消息的模块,就通过他发送过来的值,比如是一个int类型的id,我可以根据这个id在数组中找到类名,然后用上面的方法就可以搞定了。当然就节约了很多的代码了。


-----------------
欢迎讨论
...全文
136 28 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
耙子 2003-06-07
  • 打赏
  • 举报
回复
TmyForm = class of Tform
这个在delphi里面就是

TFormClass = class of TForm; 在 Forms单元里面有的定义。

RegisterClasses的方便就是它能在已知类的名称(字符串)的情况下用GetClass方法,得到类。

但是通常这个可以回避。
下面是我在MDI程序里避免一个窗口被多次创建的代码

用到了 TFormClass.

function TFrmMain.ShowMDIChildWindowEx(ClsFrm: TFormClass;
bRestore: boolean): boolean;
var
i: integer;
frm: TForm;
begin
result:= false;
frm:= nil;
for i:=0 to self.MDIChildCount-1 do
if (Self.MDIChildren[i].ClassNameIs(ClsFrm.ClassName)) then begin
frm:= Self.MDIChildren[i];
break;
end;
try
if (frm = nil) then begin
frm:= ClsFrm.Create(self);
if self.MDIChildCount <= 1 then
frm.WindowState:= wsMaximized;
end; // end of if
with frm do begin
if (bRestore) then begin
if (WindowState = wsMinimized) then
WindowState:= wsNormal;
end;
Show;
end;
Result:= true;
except
on E: Exception do
MessageBox(0, pchar('错误。'#10#13'' + E.Message),'', MB_ICONERROR);
end;
end;


使用方法
procedure TFrmMain.actSLogManagerExecute(Sender: TObject);
begin
ShowMDIChildWindowEx(TFrmLogManager, true);
end;
kuangning 2003-06-07
  • 打赏
  • 举报
回复
同意zjybestzjybest(zjybestzjybest)
FrameSniper 2003-06-07
  • 打赏
  • 举报
回复
呵呵,关注....
cnhgj 2003-06-07
  • 打赏
  • 举报
回复
type
a:TForm2;
end;


a:=TForm2.create(nil);
a.show;
zjybestzjybest 2003-06-04
  • 打赏
  • 举报
回复
最好这样TmyForm = class of Tform通用性强
wangwei_egw 2003-06-04
  • 打赏
  • 举报
回复
……
RegisterClasses([TForm_ManWellInfo_Mode,TForm_Pole_Mode,TForm_Pipe_Mode,
TForm_ExBox_Mode,TForm_SubBox_Mode,TForm_LCable_Mode]);
……
procedure TBasic_Form.Bbtn_OpenModeClick(Sender: TObject);
var
sModeName:string;
FormClass: TFormClass;
FormObject: TObject;
begin
sModeName:=Self.Name+'_Mode';
FormClass := TFormClass(GetClass(sModeName));
FormObject := FormClass.Create(nil);
TForm_Basic_Mode(FormObject).ShowModal;
end;
foreveryday007 2003-06-04
  • 打赏
  • 举报
回复
學習
linzhisong 2003-06-04
  • 打赏
  • 举报
回复
实际应用很有用得!

特别在菜单控制方面!
wjlsmail 2003-06-04
  • 打赏
  • 举报
回复
需要动态载入窗体时这种做法好 :)
ihihonline 2003-06-04
  • 打赏
  • 举报
回复
个人认为这样的坐法没有什么意义,只是用为学习。学习。。。。。

FForm : TForm;
...
Property vForm : TForm Read FNext Write FNext;

...
var
Form1 : TForm1;
implementation
Uses
Unit2;
...
....
Procedure TForm1 -> Button OnClick(Sender : TObject);
begin
if Assigned(FForm) then
TForm2(FForm).Show;
end;


Program Project1
uses
.....

begin
Application.Initialize;
.........
Form1.vForm := Form2;
Application.Run;
end.


----------------
沉沦中..........
microjuz 2003-06-04
  • 打赏
  • 举报
回复
贴一段代码给大家看看

function THWDataSetProvider.DoDBProcess(LPName, MethodName, LParam,
WParam: string): Integer;
type
THWLPClass = class of THWLogicProcessor;
var
aHWLPClass: THWLPClass;
bHWLPClass: THWLogicProcessor;
begin
aHWLPClass := THWLPClass(FindClass(LPName));
bHWLPClass := aHWLPClass.Create;
try
bHWLPClass.Provider := Self;
bHWLPClass.DBAccess := ServerDBAccess;
Result := bHWLPClass.Execute(MethodName, LParam, WParam);
finally
bHWLPClass.Free;
end;
end;

中间层封装业务逻辑的例子,LPName是业务逻辑的功能unit,MethodName是unit中的函数, LParam, WParam是参数.

和楼主差不多的例子,不过registerclasses我还是觉的写在类单元里比较好
具体的技术我不太清楚,听大家讨论~~
microjuz 2003-06-04
  • 打赏
  • 举报
回复
算不算使用rtti的例子
不过
3、 在form1的FormCreate中写入RegisterClasses([TForm2]);//注册Tform2类
对TForm2类有什么要求,只要uses包含这个类的unit就可以了吗
kuangning 2003-06-03
  • 打赏
  • 举报
回复
可以,有用。只要form3被注册了就可以。
kuangning 2003-06-03
  • 打赏
  • 举报
回复
TmyForm = class of Tform2
也可以改成Tform2的父类
TmyForm = class of Tform,效果是一样的

flyingkiller 2003-06-03
  • 打赏
  • 举报
回复
4、 在form1的button的单击事件中加入
var
A : Tform ;
begin
if GetClass('TForm2') =nil then exit ;
a := TMyform(GetClass('TForm2')).Create(nil);
a.show;
end;
上面的这段代码对另外的Form,如form3也能用吗?
whitetiger8 2003-06-03
  • 打赏
  • 举报
回复
关注了
蓝色光芒 2003-06-03
  • 打赏
  • 举报
回复
受启发,谢谢。
kuangning 2003-06-03
  • 打赏
  • 举报
回复
+1
mrtxc 2003-06-03
  • 打赏
  • 举报
回复
很好,学习,
我也去试试!!
windwather 2003-06-03
  • 打赏
  • 举报
回复
学习再学习
加载更多回复(8)
MsgInfo V1.00(一)、说明一个用来察看当前进程中消息的控件,D6环境编译。(二)、属性1、ShowType: MSGHex: 是否显示消息ID(16进制) MSGDec: 是否显示消息ID(10进制) MSGStr: 是否显示消息ID(字符串) MsgClassName:是否显示窗体类名 MsgHwnd: 是否显示窗体句柄 MsgWParam: 是否显示消息WParam值 MsgLParam: 是否显示消息LParam值2、DefineClassName: 允许(禁止)显示消息的窗体类名,如TForm13、DefineMsg: 允许(禁止)显示的消息ID,如$0005、wm_paint4、DefineState: EnableMsg: DefineMsg不为空串时,False禁止显示加入DefineMsg的消息,True只显示加入DefineMsg的消息 EnableClassName: DefinClassName不为空串时,False禁止显示加入DefineClassName的消息,True只显示加入DefineMsg的消息 EnableHwnd: 设置了AddDefineHwnd后,False禁止显示ADDDefineHwnd加入的窗体句柄消息,True则只显示加入的窗体句柄消息 EnableClassName和EnableHwnd设置不一致时,以EnableClassName为准5、DisableFrequent:是否过滤掉WM_NCHITTEST、WM_SETCURSOR、WM_ENTERIDLE、WM_NOTIFY出现频繁的消息6、HookType: 设置钩子类型7、Activate: 是否激活钩子(三)、方法1、AddDefineHwnd(): 加入的句柄为允许(禁止)显示消息的窗体句柄(可加入多个)2、Clear: 清空消息信息(四)、事件HookMethod: 可以在此事件中自行处理钩子,钩子返回值Result默认为0 注意在处理CBT钩子的HCBT_CreateWnd时,设计期拖放到窗体的控件还未创建,使用这些控件的属性和方法会出现异常。 (五)、文件MsgInfo.txt是参考文件,必须放入执行程序当前目录。此文件可自定义或扩充,无需排序格式:第一行表示消息ID的十六进制字符串,如$0005,必须$开头 第二行表示消息ID的字符串常量,如WM_Size 第三行表示该消息的说明(可省略)MsgResult.txt显示结果(六)、制作双元软件工作室http://shuangyuan.wx-e.com/
这是一个比较复杂的数据库 包含图书管理 借书还书 学生管理 老师管理 和数据连接的相关应用 代码有详细的解释 压缩包里面也有 数据库的文件 代码里设置的数据库 用户是 sa 密码是 123456 请使用的时候做相关的修改 下面给出 一部分的代码 请继续关注本资源的发布 会后面有很多实用的代码上传 using System.Windows.Forms; namespace LibraryMis { public class DatabaseAccess { /* 声明成员变量,这样这个类中的所有方法就可是使用这些变量了 */ private SqlConnection myConnection; private SqlCommand myCommand; private SqlDataAdapter myDataAdapter; private DataSet mySet = new DataSet(); /* 写该类的构造方法,该方法名要跟类名相同,无返回值 * 当new这个类时就会执行这个构造方法 */ public DatabaseAccess() { /* 获得保存连接字符串的文件名及路径 */ //获得应用程序路径 string exePath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; //根据路径和文件名构建FileInfo对象 string fileName = exePath + "connectionString.txt"; //建立FileInfo对象 FileInfo f = new FileInfo(fileName); //判断该文件是否存在 if (f.Exists)//文件存在 { //获得文件内容即存在文件中的连接字符串 //打开文件,获得读文件的数据流对象 StreamReader sr = f.OpenText(); //读文件到变量中 string connectionString = sr.ReadToEnd(); //关闭流 sr.Close(); //由读出的连接字符串创建Connection对象 myConnection = new SqlConnection(connectionString); //由Connection对象创建Command对象 myCommand = myConnection.CreateCommand(); //创建DataAdapter对象 myDataAdapter = new SqlDataAdapter(); myDataAdapter.SelectCommand = myCommand; //创建CommandBuilder对象 SqlCommandBuilder cb = new SqlCommandBuilder(myDataAdapter); //尝试是否能够打开连接 try { myConnection.Open(); } catch (Exception ex) //打开连接出错,可能是连接字符串有问题,这里调用数据库访问设置窗体来重新设置服务器名和数据库名 { MessageBox.Show("连接不到数据库LibraryMis,请在“数据库访问设置窗体中对数据库访问进行正确的设置”" + ",取消登录后重新启动图书馆管理系统!","警告",MessageBoxButtons.OK,MessageBoxIcon.Warning ); //创建 数据库访问设置窗体,并显示 FormSetDatabase fmsd = new FormSetDatabase(); fmsd.ShowDialog(); } finally { try { myConnection.Close(); } catch (Exception ex) { } } return; } else //文件不存在 { //设置默认的连接字符串 string connectionString = "server=.;database=LibraryMis;uid=sa;pwd=123456"; //把这个字符串写入文件 StreamWriter sw = new StreamWriter(fileName); sw.Write(connectionString); sw.Close(); MessageBox.Show("文件" + fileName + "不存在,已创建该文件,请重新启动图书馆管理系统","警告",MessageBoxButtons.OK, MessageBoxIcon.Information); return; } } /*创建查询的方法,返回数据集对象DataSet,参数SelectString表示查询的Sql语句,TableName表示要查询的表名*/ public DataSet FillDataSet(string SelectString, string TableName) { myDataAdapter.SelectCommand.CommandText = SelectString;//设置查询的Sql语句 myDataAdapter.Fill(mySet,TableName); return mySet; } /*执行插入,更新,修改的操作,参数CommandString表示Sql语句*/ public void ExeCommand(string CommandString) { myCommand.CommandText = CommandString; myConnection.Open(); try { myCommand.ExecuteNonQuery(); } catch (Exception ex) { MessageBox.Show(ex.ToString(),"警告",MessageBoxButtons.OK,MessageBoxIcon.Warning); } finally { myConnection.Close(); } } /*执行存储过程的方法,参数为Command对象*/ public void ExeStoreProcedure(SqlCommand command) { command.Connection = myConnection; myCommand = command; myConnection.Open(); try { myCommand.ExecuteNonQuery(); } catch (Exception ex) { MessageBox.Show(ex.ToString(), "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); } finally { myConnection.Close(); } }

5,928

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧