Ian*_*oyd 48 delphi delphi-5 design-rationale
什么是TApplication.Handle
?
德尔福帮助说:
TApplication.Handle
提供对应用程序主窗体(窗口)的窗口句柄的访问.
Run Code Online (Sandbox Code Playgroud)property Handle: HWND;
描述
在调用需要父窗口句柄的Windows API函数时使用句柄.例如,显示其自己的顶级弹出窗口的DLL需要父窗口才能在应用程序中显示其窗口.使用Handle属性使这些窗口成为应用程序的一部分,以便使应用程序最小化,恢复,启用和禁用它们.
如果我专注于" 应用程序主窗体的窗口句柄 "这个词,我认为它是指应用程序主窗体的窗口句柄,那么我可以比较:
MainForm
的Application
但他们不一样:
Application.MainForm.Handle: 11473728
Application.Handle: 11079574
Run Code Online (Sandbox Code Playgroud)
那是什么Application.Handle
?
Application
的MainForm
,那么他们为什么不匹配?Application
's 的窗口句柄MainForm
,那么它是什么?我真正要问的是:Application.Handle存在的设计原理是什么?如果我能理解为什么,应该如何变得明显.
通过20个问题的游戏更新理解:
在谈到通过让它的主人在任务栏上出现一个窗口的解决方案时null
,Peter Below在2000年说:
这可能会导致从次要形式显示的模态形式出现一些问题.
如果用户在模态表单启动时从应用程序切换,然后返回到显示它的表单,则模式表单可能隐藏在表单下方.可以通过确保模态形式是父级来处理这个问题[原文如此; 他的意思是拥有]到表明它的形式(使用
params.WndParent
如上)但是对于
Dialogs
单元和异常的标准对话框来说这是不可能的,这需要更多努力才能使它们正常工作(基本上处理Application.OnActivate
,寻找通过应用程序的模式形式并通过GetLastActivePopup
它们将它们带到Z顺序的顶部SetWindowPos
) .
他还谈到了使用新的Windows扩展样式,通过添加扩展样式,强制窗口出现在任务栏上(当使其成为非拥有的常规规则不充分,不切实际或不合需要时)WS_EX_APPWINDOW
:
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams( params );
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;
Run Code Online (Sandbox Code Playgroud)
但他警告说:
如果您在另一个应用程序处于活动状态时单击辅助表单任务栏按钮,则仍会将所有应用程序表单放在前面.如果您不希望有选项
当表格的所有者还在时,谁将所有表格带到前面Application.Handle
.申请是这样做的吗?它为什么这样做?而不是这样做,不应该也不会做这个?不这样做的缺点是什么; 我看到这样做的缺点(系统菜单不能正常工作,任务栏按钮缩略图不准确,Windows®外壳无法最小化窗口.
在处理该问题的另一篇文章中Application
,Mike Edenfield说父窗口发送其他窗口的最小化,最大化和恢复消息:
这将为您的表单添加任务栏按钮,但还有一些其他小细节需要处理.最明显的是,您的表单仍然会收到最小化/最大化,并将其发送到父表单(应用程序的主要表单).为了避免这种情况,您可以通过添加以下行来为WM_SYSCOMMAND安装消息处理程序:
Run Code Online (Sandbox Code Playgroud)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;
Run Code Online (Sandbox Code Playgroud)
将删除Application
它的窗口处理干扰我的表单,Windows应该再次发送给我我的mimimize/maximize/restore消息?
也许如果我们比较和对比现在一个"正常"的Windows应用程序做的事情,Borland最初设计Delphi应用程序来做事情 - 关于这个Application
对象和它的主要循环.
Application
对象的解决方案是什么?很显然,Borland意识到了他们最初设计的缺陷.他们的初始设计是什么,解决了什么问题,缺陷是什么,重新设计是什么,以及它如何解决问题?
All*_*uer 50
应用程序窗口的原因有点肮脏的历史.在开发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必须通过几个环节来实现这一点,并且有一些微妙的边缘情况引起了问题,但大多数问题已经解决了.但是,对于您前进的任何应用程序,它将继续使用旧的停车窗口模型.
Ger*_*oll 12
所有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 的窗口句柄
如果它不是应用程序主变形的句柄那么它是什么?往上看
更重要的是:为什么它是每种形式的最终父母?假设你是最终的父母,我认为它是这样的,因为它可以很容易地找到你的应用程序中的所有表单(枚举这个"主"形式的孩子).
最重要的是:为什么一切都变得混乱,如果我试图让一个表格无表情我认为因为隐藏的"主"表单正在获取它应该传递给它的子节点和/或主表单的系统消息,但是找不到无表格的形式.
无论如何,这是我的看法.您可以通过查看TApplication声明和代码来了解更多信息forms.pas
.从我看到的底线是它是一个方便的抽象.
最好的祝福,
唐