大雀软件园

首页 软件下载 安卓市场 苹果市场 电脑游戏 安卓游戏 文章资讯 驱动下载
技术开发 网页设计 图形图象 数据库 网络媒体 网络安全 站长CLUB 操作系统 媒体动画 安卓相关
当前位置: 首页 -> 技术开发 -> Script -> Delphi中正常窗口的实现

Delphi中正常窗口的实现

时间: 2021-07-31 作者:daque

纲要 在delphi的vcl库中,为了运用以及实行的简单,运用东西application创造了一个用来处置动静相应的湮没窗口。而恰是这个窗口,使得用vcl开拓出来的步调生存着与其余窗口不许平常陈设平铺等显得有些反常的题目。正文经过对vcl的深刻领会,给出了一个只须要对运用步调名目文献作3行代码的窜改就能处置题目的计划,且不须要原有的编制程序办法作任何变换。

1 弁言用delphi所供给的vcl类库编写的windows运用步调,有一个鲜明各别于规范windows窗口的特性--主窗口的体例菜单与工作栏上的体例菜单不沟通。普遍情景下,主窗口的体例菜单有六个菜单项而工作栏体例菜单惟有三个菜单项。本质运用中咱们创造用vcl开拓的步调有以次几个上面的为难:1)不够场面。这是确定的,与规范不符天然会显得有些反常。2)主窗口最小化时没有动画功效。3)窗口不许平常与其它窗口陈设平铺。4)工作栏体例菜单具备最高的优先级。在生存模态窗口的情景下所有步调仍旧不妨被最小化,与模态窗口的安排相违反。主窗口最小化动画功效的题目在delphi 5.0此后的本子中已经过forms.pas中的showwinnoanimate因变量处置,但其他几个题目则从来生存。纵然普遍情景下这不会对运用步调带来什么感化,但在少许探求专科功效的场所真实不行接收的。因为c++ builder与delphi运用的是同一套类库,以是上述题目同样生存于运用c++ builder编写的windows运用步调中。在往日的作品里(阿甘的家中不妨找到),我已计划过这个题目,其时的报告看上去基础上是一种取巧的本领,而我也是在偶尔之中才找到谁人本领的。正文的工作即是经过对vcl类库作少许领会,证明那么做的道理,其次再给出一个只用3行代码的本领,完实足全地处置delphi中这个"非平常窗口"的题目。

2 道理2.1 运用步调的创造进程底下是一个典范的运用步调的delphi工程文献,咱们提防到一发端就有一个对application东西的initialize本领的援用,咱们的领会也就从这边发端:

program project1;

uses  forms,  unit1 in 'unit1.pas' {form1};

{$r *.res}

begin  application.initialize;  application.createform(tform1, form1);  application.run;end.

湮没的窗口是由application东西创造的,那么application东西又从何而来呢?在delphi的代码编纂窗口中按住ctrl点击application就会创造,application东西是在forms.pas单位中设置的几个全部东西之一。这还不够,咱们想要领会的是application东西是在什么场合创造的,由于必需胜利创造了tapplication类的范例咱们本领援用它。想一下,有什么代码会在application.initialize之前实行呢?对了,是initialization代码段中的代码。刻意调节和测试过vcl源码就不妨领会,vcl中很多单位都有initialization代码段,启用delphi步调时,先是依照uses的程序实行每个单位中initialization代码段的代码,实行一切的初始化举措之后才实行application的initialize本领以初始化application,以是很明显,application东西是在某个单位的initialization代码段中创造的。以"tapplication.create"为要害字在vcl源码目次中探求一番,咱们居然在controls.pas单位中找到了创造application东西的代码。在controls.pas单位的initialization代码段,有一句对initcontrols进程的挪用,而initcontrols的实行则如次所示:

unit controls;…initialization    ...    initcontrols;

procedure initcontrols;begin...  mouse := tmouse.create;  screen := tscreen.create(nil);  application := tapplication.create(nil);...end;

好,到这边咱们的领会就实行了第一步,由于要处置非平常窗口的题目,咱们必需要在application东西初始化之前做一件事,所以领会运用步调的初始化进程就特殊要害了。2.2 islibrary变量islibrary变量是在system.pas单位中设置的全部标记变量之一。即使islibrary的值为true则表白步调模块是一个动静链接库,反之即是一个可执路途序。vcl类库中的某些进程就按照这个标记变量的各别值实行各别的举措。也即是这个变量,在处置delphi的非平常窗口题目中起到了要害性的效率。前方说过,为了简单,application东西初始化时创造了一个看不见的窗口(也即是用spy++之类的东西看到的谁人以"tapplication"为类名的窗口),但也恰是由于这个看不见的窗口,才使得用delphi开拓出来的步调表露诸多反常。好了,即使咱们不妨去掉这个看不见的窗口(同声去掉工作栏体例菜单),代之以咱们的运用步调主窗口,岂不是一切的题目都处置了?说说大略,但实行起来须要对vcl源代码动大手术吗?即使那么岂不是有点舍本逐末了?谜底固然是不会,要不也不会有这篇作品了。在此我想说的是,在接下来的领会中,咱们将会看到,所谓"编制程序之道,存乎潜心",tapplication安排中无意插柳的做法,实则为咱们处置这一题目留住了接口。不做源代码的领会,你大概要绕打圈子,而本质上咱们会看到,天性的安排留给咱们用的货色,不多也不少,方才好。翻开tapplication类的结构因变量create,咱们会创造如许一条龙代码。

constructor tapplication.create(aowner: tcomponent);begin    ...    if not islibrary then createhandle;    ...end;

这边说的是,即使步调模块不是动静链接库,那么就实行createhandle,而createhandle所做的处事在扶助中是如许说的:"即使不生存运用步调窗口,那就创造一个",这边的"运用步调窗口"即是上头所说的看不见的窗口,也即是首恶罪魁之地方,在tapplication类顶用fhandle变量来生存其窗口句柄。这边即是按照islibrary的值实行了各别的举措,由于在动静链接库中普遍并不须要动静轮回的,但用vcl开拓动静链接库仍旧要用到application东西,以是有了这边的安排。好,咱们只须要捉弄一下application东西,在它创造之前把islibrary赋值为true,即可滤掉createhandle的实行,去掉这个腻烦的窗口了。为islibrary赋值的代码明显也该当放在某个单位的initialization代码段中,并且因为initialization代码段中的代码是依照包括的单位的程序实行的,为了保护在application东西创造之前把islibrary赋值为true,在工程文献中咱们必定将包括赋值代码的单位放在forms单位之前,如次(假如该单位名为unitdllexe.pas):

program template;

uses  unitdllexe in 'unitdllexe.pas',  forms,  formmain in 'formmain.pas' {mainform},  ...

unitdllexe.pas代码清单如次:

unit unitdllexe;

interface

implementation

initialization  islibrary := true;  //报告applciation东西,这是一个动静链接库,不须要创造湮没窗口。end.

好了,编写翻译运转一下,咱们看到,因为没有创造湮没窗口,向来工作栏上的体例菜单消逝了,换成了主窗口的体例菜单,主窗口也不妨与其它windows窗口平常陈设平铺。但带来的题目是窗口没辙最小化。如何回事呢?仍旧老本领,盯梢一下。2.3 主窗口最小化最小化属于体例吩咐,最后必然是挪用api因变量defwindowproc来将窗口最小化,以是咱们毫无艰巨地就找到了tcustomform中相应wm_syscommand动静的因变量wmsyscommand,个中领会地写到将最小化的动静重定向到application.wndproc去向理:procedure tcustomform.wmsyscommand(var message: twmsyscommand);begin  with message do  begin    if (cmdtype and $fff0 = sc_minimize) and (application.mainform = self) then      application.wndproc(tmessage(message))  ...  end;end;

而在application.wndproc中,相应最小化动静时又挪用了application的minimize本领,以是毛病确定是在minimize进程。

procedure tapplication.wndproc(var message: tmessage);  ...begin  ...    with message do      case msg of        wm_syscommand:          case wparam and $fff0 of            sc_minimize: minimize;            sc_restore: restore;          else            default;  ...end;

结果,找到tapplication.minimize,就十足都领会了。这边对于defwindowproc因变量的挪用没有爆发任何功效,干什么呢?因为前方咱们捉弄application东西,滤掉了createhandle的挪用,没有创造application东西相应动静所须要的窗口,所以引导其句柄fhandle为0,挪用固然不可功了。即使能将fhandle指向咱们的运用步调主窗口就能处置题目。

procedure tapplication.minimize;begin  ...      defwindowproc(fhandle, wm_syscommand, sc_minimize, 0);      //这边fhandle值为0  ...end;

3 实行borland的天性们无意插柳的安排再一次让咱们找到领会决题目的方法。由前方的领会咱们领会,在用vcl开拓的动静链接库中并没有创造湮没的窗口来接受windows动静(createhandle不实行),但在动静链接库中即使要表露窗口的话又须要一个父窗口。怎样处置这个题目呢?vcl的安排者将生存看不见的窗口句柄的fhandle变量安排为可写,所以咱们本质上不妨大略地给fhandle赋一个值来为须要表露的子窗口供给一个父窗口。比方,在某个动静链接库插件中要表露窗体,咱们常常会在主模块可实行文献中将application东西的句柄经过动静链接库的某个因变量传入并赋值给动静链接库的application.handle,一致于:

procedure setapplicationhandle(mainappwnd: hwnd)begin  application.handle := mainappwnd;end;

好了,既是aplication.handle本质上不过一个在里面用来相应动静的窗口句柄,而本来该当创造的看不见的窗口被咱们去掉了,那咱们只须要给出一个窗口的句柄,用来包办谁人本来过剩的湮没窗口的句柄不就行了?如许的窗口去何处找?运用步调的主窗口恰是上上之选,所以有了底下的代码。

program template;

uses  unitdllexe in 'unitdllexe.pas',  forms,  formmain in 'formmain.pas' {mainform};

{$r *.res}

begin  application.initialize;  application.createform(tformmain, formmain);  application.handle := formmain.handle;  application.run;end.

所以,十足题目都处置了。你不须要对vcl源码作任何窜改,不须要对原有的步调作任何窜改,只有在工程文献中减少两行代码,加上unitdllexe.pas中的一条龙,共三行代码,即可使得你的运用步调窗口实足和任何一个规范windows窗口一律平常。1)工作栏和窗口题目栏具有普遍的体例菜单。2)主窗口最小化时有动画功效。3)窗口不妨平常与其它窗口陈设平铺。4)生存模态窗口时不许对其父窗口举行操纵。

之上实行代码运用于delphi的一切本子。

热门阅览

最新排行

Copyright © 2019-2021 大雀软件园(www.daque.cn) All Rights Reserved.