[英]Delphi: What is Application.Handle?
什么是TApplication.Handle
?
德尔福帮助说:
TApplication.Handle
提供对应用程序主窗体(窗口)的窗口句柄的访问。
property Handle: HWND;
描述
在调用需要父窗口句柄的Windows API函数时使用句柄。 例如,显示其自己的顶级弹出窗口的DLL需要父窗口才能在应用程序中显示其窗口。 使用Handle属性使这些窗口成为应用程序的一部分,以便使应用程序最小化,恢复,启用和禁用它们。
如果我专注于“ 应用程序主窗体的窗口句柄 ”这个词,我认为它是指应用程序主窗体的窗口句柄 ,那么我可以比较:
Application
MainForm
的窗口句柄 但他们不一样:
Application.MainForm.Handle: 11473728
Application.Handle: 11079574
什么是Application.Handle
?
Application
的MainForm
的Windows®窗口句柄,那么为什么它们不匹配? Application
的MainForm
的窗口句柄,那么它是什么? 我真正要问的是: Application.Handle存在的设计原理是什么? 如果我能理解为什么,应该如何变得明显。
通过20个问题的游戏更新理解:
在谈到通过使其所有者为null
在任务栏上显示窗口的解决方案时,2000年的Peter Below说 :
这可能会导致从次要形式显示的模态形式出现一些问题。
如果用户在模态表单启动时从应用程序切换,然后返回到显示它的表单,则模式表单可能隐藏在表单下方。 可以通过确保模态形式是父级来处理这个问题[原文如此; 他的意思是拥有]到显示它的形式(使用
params.WndParent
如上)但是,这是不可能的从标准对话框
Dialogs
单元和例外 ,这需要更多的努力让他们的工作权利(基本处理Application.OnActivate
,寻找通过父级应用模式表单GetLastActivePopup
并把他们的顶通过SetWindowPos
Z顺序)。
他还谈到了使用新的Windows扩展样式,通过添加WS_EX_APPWINDOW
扩展样式,强制窗口出现在任务栏上(当使其成为非拥有的常规规则不充分,不切实际或不合需要时):
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams( params );
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;
但他警告说:
如果您在另一个应用程序处于活动状态时单击辅助表单任务栏按钮,则仍会将所有应用程序表单放在前面。 如果您不希望有选项
当表单的所有者仍然是Application.Handle
时,谁将所有表单带到前面。 申请是这样做的吗? 它为什么这样做? 而不是这样做,不应该也不能这样做呢? 不这样做的缺点是什么; 我看到这样做的缺点(系统菜单不能正常工作,任务栏按钮缩略图不准确,Windows®外壳无法最小化窗口。
在处理该Application
另一篇文章中, Mike Edenfield说父窗口发送其他窗口的最小化,最大化和恢复消息 :
这将为您的表单添加任务栏按钮,但还有一些其他小细节需要处理。 最明显的是,您的表单仍然会收到最小化/最大化,并将其发送到父表单(应用程序的主要表单)。 为了避免这种情况,您可以通过添加以下行来为WM_SYSCOMMAND安装消息处理程序:
procedure WMSysCommand(var Msg: TMessage); WM_SYSCOMMAND; procedure TParentForm.WMSysCommand(var Msg: TMessage); begin if Msg.wParam = SC_MINIMIZE then begin // Send child windows message, don't // send to windows with a taskbar button. end; end;
请注意,此处理程序将以您希望独立于应用程序其余部分的行为的PARENT形式进行,以避免传递最小化消息。 您可以为SC_MAXIMIZE,SC_RESTORE等添加类似的>代码。
如何最小化/最大化/恢复Windows®窗口的消息不会进入我的窗口? 这是因为发往窗口的邮件是由Windows®发送给窗口的所有者的吗? 在这种情况下,Delphi应用程序中的所有表单都由Application
“拥有”? 这不意味着让所有者为null:
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.WndParent := 0; //NULL
end;
将删除Application
和它的窗口处理干扰我的表单,Windows应该再次发送给我我的mimimize / maximize / restore消息?
也许如果我们比较和对比现在一个“正常”的Windows应用程序做的事情,Borland最初设计Delphi应用程序来做事情 - 关于这个Application
对象和它的主要循环。
Application
对象解决了什么解决方案? 很显然,Borland意识到了他们最初设计的缺陷。 他们的初始设计是什么,解决了什么问题,缺陷是什么,重新设计是什么,以及它如何解决问题?
应用程序窗口的原因有点肮脏的历史。 在开发Delphi 1时,我们知道我们想要为IDE使用“SDI”(遍布桌面的窗口)ui模型。 我们也知道Windows在该模型上吸引了(并且仍然存在)。 但是我们也注意到当时的Visual Basic使用了该模型,它似乎运行良好。 经过进一步检查,我们发现VB使用了一个特殊的“隐藏”停车窗口,用作所有其他可见窗口的“所有者”(Windows模糊了父级和所有者的概念,但区别类似于VCL) 。
这就是我们解决“问题”的方法,其中包含主菜单的窗口很少被聚焦,因此处理文件菜单的Alt-F根本不起作用。 通过使用这个中央停车窗口作为中介,我们可以更容易地跟踪消息并将消息路由到适当的窗口。
这种安排还解决了通常多个顶级窗口完全独立的另一个问题。 通过使应用程序处理所有这些窗口的“所有者”,它们都会表现得很好。 例如,您可能已经注意到,当您选择任何应用程序窗口时, 所有应用程序窗口都会移到前面并保持相对于彼此的z顺序。 这也可以使应用程序最小化并恢复为功能分组。
这是使用此模型的结果。 我们可以手动完成所有这些工作以保持平稳,但设计理念是不重新发明Windows,而是尽可能地利用它。 这也是为什么一个TButton或TEDIT是一个真正的Windows“用户”按钮,编辑窗口类和风格,分别。
随着Windows的发展,“SDI”模式开始失宠。 事实上,Windows本身开始变得对这种应用程序“充满敌意”。 从Windows Vista开始并继续到7,用户shell似乎无法与使用停车窗口的应用程序一起使用。 因此,我们开始在VCL中改变现状以消除停车窗口并将其功能转移到主窗体中。 这提出了几个“鸡和鸡蛋”问题,我们需要在应用程序初始化中尽早提供停车窗口,以便其他窗口可以“附加”到它,但主窗体本身可能不会很快构建。 TApplication必须通过几个环节来实现这一点,并且有一些微妙的边缘情况引起了问题,但大多数问题已经解决了。 但是,对于您前进的任何应用程序,它将继续使用旧的停车窗口模型。
所有VCL应用程序都有一个名为Application的“隐藏”顶级窗口。 这是在应用程序启动时自动创建的。 除此之外,它是VCL的主要Windows消息处理程序 - 因此是Application.ProcessMessages。
隐藏应用程序顶级窗口会导致一些奇怪的事情,显然是任务栏中显示的不完整的系统菜单,以及Vista中不正确的缩略图窗口。 更高版本的Delphi纠正了这一点。
但是,并非所有窗口都必须将它作为父级,Windows只是倾向于更好地工作。 但是,使用Application.CreateForm创建的任何表单都将将其作为父项,并且它也将由Application对象拥有。 由于它们是拥有的,因此一旦应用程序被释放,它们将被释放。 这发生在Forms.DoneApplication的幕后
通过查看forms.pas(Delphi 2009)中的源代码,看起来他们在win32 gui应用程序中创建了一个“主”窗口,允许调用
看来传递给Application.Handle
消息会根据需要转发给MainForm
(如果存在)。 如果尚未创建主窗口,这将允许应用程序响应最小化等。 通过修改项目源,您可以创建一个没有主窗口的delphi应用程序。
在这种情况下,即使您尚未创建主窗口, TApplication
方法仍然可以工作。 不确定我是否掌握了所有目的,但我没有时间完成所有的TApplication代码。
根据你的问题:
它从何而来? 它是在TApplication.Create
创建的窗口的句柄
窗户处理的是什么? 每个gui delphi应用程序需要的假窗口作为TApplication抽象的一部分
它是应用程序的主要形式 No 的窗口句柄
如果它不是应用程序主变形的句柄那么它是什么? 往上看
更重要的是:为什么它是每种形式的最终父母? 假设你是最终的父母,我认为它是这样的,因为它可以很容易地找到你的应用程序中的所有表单(枚举这个“主”形式的孩子)。
最重要的是:为什么一切都变得混乱,如果我试图让一个表格无表情我认为因为隐藏的“主”表单正在获取它应该传递给它的子节点和/或主表单的系统消息,但是找不到无表格的形式。
无论如何,这是我的看法。 您可以通过查看forms.pas
中的TApplication声明和代码来了解更多forms.pas
。 从我看到的底线是它是一个方便的抽象。
最好的祝福,
唐
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.