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

原创 2003年07月31日 10:24:00

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

 

 

 

 

以上方法虽然可以实现动态的有选择地创建和显示窗体,但是有一个致命的弱点,就是程序关闭权限的转移,不能保留Form1的程序关闭权限。怎样真正实现有选择的创建和显示窗体,并且能保持Form1为主窗体呢?方法如下:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

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

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

procedure TForm2.FormCreate(Sender: TObject);

begin

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

end;

Form3OnCreate() 事件中加入以下代码:

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

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

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

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

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

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

Project1.dpr中只创建Form1

begin

  Application.Initialize;

  Application.CreateForm(TForm1, Form1);

  Application.Run;

end.

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

  Application.Terminate;

如果不加入这一句,则关闭Form1是不会关闭整个应用程序的,必须关闭Form2Form3才行。 有些人可能会问,为什么不是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编译器则体现为ProjectRunning状态,并且需要通过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的程序关闭权,方法是在Form2Form3OnClose()事件函数中加入一句Application.Run,这样按Form2Fomr3的关闭按钮都不会有什么反应了,当然也就不会关闭程序了。我们再添加一个按钮用来“关闭”窗体,在其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);//010之间取随机值

  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.

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

 

三.  总结

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

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

 

 

delphi 窗体的创建和释放

http://www.cnblogs.com/chenmfly/p/4770490.html delphi 窗体的创建和释放 Delphi中的窗体分为模式窗体和无模式窗体。二者...
  • y13156556538
  • y13156556538
  • 2016年10月21日 10:09
  • 3256

delphi 创建启动窗体

  Delphi在启动时会首先显示一个图片,等到将所有的初始化工作全做完后该图片自动消失。为达到这一效果,建立一个示例程序。      建立一个新Application,包括两个Form,其中Form...
  • happypolo
  • happypolo
  • 2008年12月24日 13:00
  • 1670

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

在Delphi 中用程序实现自定义窗体的创建和显示顺序(2)    以上方法虽然可以实现动态的有选择地创建和显示窗体,但是有一个致命的弱点,就是程序关闭权限的转移,不能保留Form1的程序关闭权限。怎...
  • allencnj1980
  • allencnj1980
  • 2003年07月31日 10:24
  • 1227

改变窗口层叠的顺序

BringWindowToTop The BringWindowToTop function brings the specified window to the top of the Z order...
  • del123
  • del123
  • 2006年06月16日 16:29
  • 3068

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

在Delphi 中用程序实现自定义窗体的创建和显示顺序(1) 摘要:本文介绍了一种简单而实用的方法用来动态创建和显示窗体,在Project.dpr中编写代码实现窗体的动态选择创建,同时对 Delphi...
  • allencnj1980
  • allencnj1980
  • 2003年07月31日 10:22
  • 1642

-创建和显示窗体实例

本例在SDK下使用API函数实现窗体的创建、销毁、显示和隐藏! 1、打开VC6,单击File/New菜单,选择Win32  Application ,建立工程名为WindowDemo的应用程序。 ...
  • yaoxinchao
  • yaoxinchao
  • 2012年12月01日 16:52
  • 3967

delphi SetWindowPos改变窗体位置和状态

//声明:SetWindowPos(hWnd: HWND;            {窗口句柄}hWndInsertAfter: HWND; {窗口的 Z 顺序}X, Y: Integer;      ...
  • chenday
  • chenday
  • 2010年08月07日 23:28
  • 958

delphi SetWindowPos改变窗体位置和状态

//声明:SetWindowPos(hWnd: HWND;            {窗口句柄}hWndInsertAfter: HWND; {窗口的 Z 顺序}X, Y: Integer;      ...
  • fromciom3
  • fromciom3
  • 2011年05月02日 11:49
  • 396

DELPHI 让子窗体显示在任务栏上

重载 CreateParams 方法 procedure CreateParams(var Params: TCreateParams);override; procedure TForm2.Cr...
  • lovewjp
  • lovewjp
  • 2015年10月20日 19:50
  • 2098

delphi 刷新子窗体,导致父窗体闪烁

父窗体上的按钮都有背景图片,窗体本身也有背景图片,貌似都是这些图片在闪烁,不做去图片测试了。。 转载:http://blog.csdn.net/dd_zhouqian/article/details/...
  • haibin_hu
  • haibin_hu
  • 2013年08月28日 11:17
  • 1801
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在Delphi 中用程序实现自定义窗体的创建和显示顺序(2)
举报原因:
原因补充:

(最多只允许输入30个字)