分享
 
 
 

在Delphi 中用程序实现自定义窗体的创建和显示顺序(2)

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

在Delphi 中用程序实现自定义窗体的创建和显示顺序(2)

以上方法虽然可以实现动态的有选择地创建和显示窗体,但是有一个致命的弱点,就是程序关闭权限的转移,不能保留Form1的程序关闭权限。怎样真正实现有选择的创建和显示窗体,并且能保持Form1为主窗体呢?方法如下:

把3个窗体都放置在Auto-create forms里面,即3个窗体都自动创建。

在Form1中设置一个全局变量

var

flag:Integer;

然后把上面Form1那段代码改成如下所示:

procedure TForm1.FormCreate(Sender: TObject);

var

randomnum:Integer;

begin

flag:=0;

Label1.Caption:='Form1 Create Complete!';

Randomize;

randomnum:=Random(10);

if (randomnum>0)and (randomnum<=4) then

flag:=2

else if (randomnum>4)and (randomnum<=8) then

flag:=3

else

flag:=1;

end;

(代码6)

然后,在Form2的OnCreate() 事件中加入以下代码:

procedure TForm2.FormCreate(Sender: TObject);

begin

Label1.Caption:='Form2 Create Completed!';

end;

在Form3的OnCreate() 事件中加入以下代码:

procedure TForm3.FormCreate(Sender: TObject);

begin

Label1.Caption:='Form3 Create Complete! (' +IntToStr(flag)+') ';

Form3.Hide;

if flag=3 then

Begin

Form3.Visible:=True;

End

else if flag=2 then

Begin

Form2.Visible:=true;

End

else if flag=1 then

Begin

Form1.Show;

end;

(代码7)

还要记得把Form2和Form3的FormStyle属性改成fsStayOnTop,把Form1的FormStyle属性设成fsNormal,否则无法在屏幕的最前端显示所需要的窗体。把Form2和 Form3的Visible属性设成False,否则程序将无法正确地Focus(聚焦)于所需窗体。经过这样的修改之后就能根据随机结果选择最终要显示的窗体。

分析一下上面的过程可知道,窗体1,2,3是按顺序创建的,但是在Form1的创建过程中设置了一个全局变量作为记录的标记,记录应该显示的是哪个窗体,Form2的创建过程没有做任何动作,只是简单的一个显示信息,而在Form3的创建过程中则判断标志flag的值,由此决定究竟应该显示哪个窗体。

注意到主窗体是一定会显示出来的,这也是Form1的Visible没有设置成 False的原因,因为即使设置成False,也是会显示出来的。

以上所说的方法,其中的3个窗体都是已经被完全创建的,只是其中一个或两个没显示出来而已(设置成Visible为False),如果现在打开Spy++,可以清楚地看到3个窗口都在。但是我们的目的不仅仅如此,我们还要实现窗体创建的动态性和选择性。

前面说过使用Appliation.CreateForm()的方法来动态创建窗体有它的局限性,就是所谓的权限的转移。实际上我们可以改变这种情形,方法如下:

在Project1.dpr中只创建Form1

begin

Application.Initialize;

Application.CreateForm(TForm1, Form1);

Application.Run;

end.

在Form1的OnCreate()中的代码和代码5一样。Form2,Form3的OnCreate()不需要任何代码, 这时程序的关闭权限还是没有回到Form1的手里,其实我们只要在Form1的OnClose()中加入一句就行了:

Application.Terminate;

如果不加入这一句,则关闭Form1是不会关闭整个应用程序的,必须关闭Form2或Form3才行。 有些人可能会问,为什么不是Free而是Terminate呢?查一下Delphi的帮助文件关于Free的描述,其中有一个注意事项如下所述:

Warning: Never explicitly free a component within one of its own event handlers or the event handler of a component it owns or contains. For example, don’t free a button, or the form that owns the button, in its OnClick event handler.

可以看到,在Delphi中不能在一个组件它自己的事件处理中明确地释放这个组件。这就是为什么不能用Application.Free的原因。必须用Application.Terminate这一句来释放窗体创建的资源,否则将出现资源没有释放的错误。如何知道资源没有释放呢?在Delphi编译器则体现为Project在Running状态,并且需要通过Run->Program Reset来结束程序;另外,如果把程序Build了之后,脱离Delphi编译器直接运行程序,然后关闭Form1,这时候打开Windows的任务管理器,在进程一页将显示Project仍然在,占用着内存和CPU,需要通过结束进程来去掉它。

关于Application.Terminate,Delphi的帮助文件有这样的描述:

Call Terminate to end the application programmatically. By calling Terminate rather than freeing the application object, you allow the application to shut down in an orderly fashion.

这里,Delphi很明确的告诉我们,调用Terminate而不是Free,可以让应用程序以整齐的方式关闭。

到这里我们的任务还没结束,我们只是让Form1 和Form2或者是Form3有同等的关闭程序的权限,我们还要剥夺Form2或是Form3的程序关闭权,方法是在Form2和Form3的OnClose()事件函数中加入一句Application.Run,这样按Form2和Fomr3的关闭按钮都不会有什么反应了,当然也就不会关闭程序了。我们再添加一个按钮用来“关闭”窗体,在其Onclik事件中加入一句

Form2.Visible:=False;

所谓的关闭其实是把显示关闭,而不是把窗体关闭,窗体的资源是没有释放的。Delphi的帮助文件中关于Application.Run的描述不鼓励我们使用Run,但是从实际使用情况来看,并没有什么坏处,只是窗体的关闭按钮的功能被屏蔽掉了,但是我们有替代的办法,把窗体的BorderStyle属性设置成bsNone就可以把窗体的Title标题栏取掉,用其他按钮或者其他控件,代替标题栏上的最小化,最大化,关闭按钮。

到此为止,我们可以说是基本解决了本文开始提出的问题,但是还有一个重要问题我们忽略了,Fom1总是会出现,聪明的你可能想到了在Project.dpr中编写一些代码来处理,对极了,请看下面代码:

program Project1;

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls,

Unit1 in 'Unit1.pas' {Form1},

Unit2 in 'Unit2.pas' {Form2},

Unit3 in 'Unit3.pas' {Form3};

{$R *.res}

var

randomnum:Integer;

begin

Application.Initialize;

Randomize;//设置随机器

randomnum:=Random(10);//在0到10之间取随机值

if (randomnum>0)and (randomnum<=4)then//如果随机值在0到4之间

Begin

Application.CreateForm(TForm2, Form2);

End

else if (randomnum>4)and (randomnum<=8)then//如果随机数在4到8之间

Begin

Application.CreateForm(TForm3, Form3);

End

Else //如果随机数在8到10之间

Begin

Application.CreateForm(TForm1, Form1);

End;

Application.Run;

end.

实现以上代码后,Form1,Form2,Form3不用写任何处理代码,不用修改任何属性,就能解决我们的问题,我们可能要慨叹了,为什么一开始没想到这样做。

三. 总结

使用Appliation.CreateForm()的方法来动态创建窗体有它的局限性,本文介绍了一个简单而实用的方法用来动态显示窗体,这种方法的关键是设置一个标志,根据实际情况给标志赋值,等到全部窗体创建完毕后,根据所设标志决定需要显示的窗体。但是这种方法的缺点是所有的窗体都将被创建。本文介绍了另外一种方法,这种方法能真正实现动态选择创建窗体,但是同样存在缺点,就是程序关闭权限被平均化了,但是我们有相应的解决办法。这两种方法各有其优缺点,为此我们用到第三种方法,在Project.dpr中编写代码实现窗体的动态选择创建,到此则完满地解决了本文开始提出的问题。

如果读者有更好的建议或解决办法,欢迎指教,我的Email是allencnj@163.com.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有