注:此文已有更好的方法,稍后发布
2004年9月16日
Delphi的确是功能非常强的RAD工具,所以我下面要说的不算是“缺陷”的一个小问题丝毫不会影响它在程序员心目中的地位,相反,大家会发现,它的确是不愧为一个功能非常强的RAD工具。
先来看两幅图,比较一下它们的不同之处。
左边是HtmlViewer的任务栏菜单,它和在窗口标题栏上点右键弹出的菜单一模一样。
右边一幅是一个标准的Delphi程序。可以看到,在任务栏上弹出的菜单是TApplication对象的菜单,缺省地,它只有三项:还原、最小化和关闭。
当然,菜单一不一样并非关键所在,区别在于两点:
1、在Delphi 3.0和Delphi 4.0中,象右图这样的程序在最小化和还原的时候,窗口是瞬间消失的,并没有象用VC或VB等开发工具编制的程序那样有动态的渐变效果(不过,在Inprise意识到这个问题之后,Delphi 5.0中已经解决)。
2、我用过的Delphi的三个版本编制的程序,都无法和标准的Windows程序正常地排列平铺(这一点才是最重要的),就是因为有了TApplication对象,我猜测,Windows在将Delphi程序和桌面上的其它窗口排列平铺的时候,得到的是应用程序句柄,而不是程序主窗口的句柄,而TApplication对象是一个没有高度和宽度的特殊窗口,所以问题就出来了。
----------------------------------------------------------------------------------------------------------
其实我最初并没有一门心思地想解决这两个问题,相反,经历是相当偶然的。
有一次我看《Delphi 3从入门到精通》学习编写通知栏程序,书上的例子先用了一个方法使得应用程序不显示在任务栏上,之后又说明,在应用程序建立的过程中,有一瞬间是会在任务栏上看到它生成的(尤其是机器较慢的时候),这样显得应用程序不够专业。所以Marco Cantu(《Delphi 3从入门到精通》书的作者) 用了一个办法,在所有窗口初始化之前把应用程序声明为一个动态链接库,等到Application.Initialize执行之后,再恢复为正常的应用程序声明。因为动态链接库不是应用程序,所以从根本上消除了应用程序在任务栏上的生成过程。
我当然照做。不过,我忽然发现,我的程序有一个窗口的系统菜单和它在任务栏上弹出的系统菜单变得一样了,于是灵感一来,瞬间我便意识到,我有可能做出我要的效果。
后面的工作当然还很多,简单说来就是:在我尝试了各种各样的情况之后,终于找到了一种方法,可以解决上面的第一个问题(有意思的是,我的Delphi程序从此能够正常排列平铺我事先根本没有想到)。
----------------------------------------------------------------------------------------------------------
ok,说了这么多,该把解决方案拿出来了,步骤如下:
本文例子源代码下载:1.88k1、New Application,保存之,假设Form1保存为“VirMain.Pas”(建议不要保存为Main之类的名字,因
为它并不是主窗体,实际编程中它可以是没有用的)。
2、New Form,生成Form2(这才是主窗体)。
3、New Unit,在implementation后面加上:
initialization
islibrary :=true;
4、Save All,为工程取好名字,Unit1建议取名为“RunFirst.pas”,主窗口Form2保存为“Main.Pas”。
5、打开工程文件,把“RunFirst in 'RunFirst.pas';”一句移到第一行,并在Application.Initialize语句后添上下面黑色的两句话,如下:
program Project1;
uses
RunFirst in 'RunFirst.pas',//注意分号改为逗号
Forms,
VirMain in 'VirMain.Pas' {Form1},
Main in 'Main.Pas' {Form2};
{$R *.RES}
begin
Application.Initialize;
Application.ShowMainForm :=false;
islibrary :=true;
Application.CreateForm(TForm1, Form1);
Form2 :=TForm2.Create(Application) ;
Form2.Show;
Form2.Update ;
Application.Run;
end.
6、在Form2的OnClose事件中写如下语句:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Application.Terminate
end;
发表于“阿甘的家”
2000年8月14日