2010-02-05 86 views
44

什么是TApplication.Handle德尔福:什么是Application.Handle?

  • 它从何而来?
  • 它为什么存在?
  • 而最重要的是:为什么所有表单都将它作为父窗口处理?

Delphi帮助说:

TApplication.Handle

提供对窗口办理 应用的主要形式(窗口)的 。调用Windows API的需要父窗口句柄 功能 时

property Handle: HWND; 

说明

用途把手。例如, 显示其自己的顶层弹出窗口 一个DLL需要一个父窗口 在 应用显示其窗口。使用手柄财产 使得 应用程序的窗口等部分,让他们 最小化,恢复,启用和 与应用程序禁用。

如果我专注于词“应用的主要形式的窗口句柄”,我认为这意味着应用的主要形式的窗口句柄,然后我可以比较:

  • “应用程序的主要形式的窗口句柄”,用
  • Application
MainForm的窗口句柄

,但他们是不一样的:

Application.MainForm.Handle: 11473728 
Application.Handle: 11079574 

那么,什么是Application.Handle

  • 它从何而来?
  • 什么窗口®窗口句柄是它?
  • 如果它的Windows ®窗口句柄的ApplicationMainForm,那他们为什么不匹配?
  • 如果是不是Application的窗口句柄MainForm,那么它是什么?
  • 更重要的是:为什么它是每种形式的最终父母?
  • 而且最重要的是:如果我试图让一个窗体没有显示(所以我可以显示在任务栏上),或者尝试使用类似IProgressDialog的东西,为什么一切都会失控?

真的,我问的是:什么是使Application.Handle存在的设计原理?如果我能理解为什么,那该如何变得明显。


更新通过的二十个问题游戏的认识:

此:

在谈论如何让一个窗口的解决方案通过使它的主人nullPeter Below in 2000 said出现在任务栏上可能会导致一些问题与 辅助形式显示的模态形式。

如果用户在模态 表单启动时切换离开应用程序,然后回到显示它的表单,模式表单可能会隐藏在表单下方 。这是可能通过确保 模式窗体父到显示了它的形式( `params.WndParent``如上使用)

应对这种但这是不可能的从标准 对话Dialogs单元和例外,这就需要更多的努力 让他们的工作权利(基本处理Application.OnActivate, 通过GetLastActivePopup 寻找父对象应用模式表单,并通过SetWindowPos将他们的Z顺序的顶部) 。

  • 为什么模式表单最终会被卡在其他表单之后?
  • 什么机制通常将模态形式带到前面,为什么它在这里不起作用?
  • Windows ®负责显示窗口堆叠。 Windows ®没有显示正确的窗口出了什么问题?

他还谈到使用新的Windows扩展样式,迫使一个窗口出现在任务栏上(当使它无主的一般规则是不够的,不切实际的,或不希望),通过添加WS_EX_APPWINDOW扩展风格:

procedure TForm2.CreateParams(var Params: TCreateParams); 
begin 
    inherited CreateParams(params); 

    Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW; 
end; 

但他警告:

如果您在辅助形式单击任务栏按钮,而另一个应用是 活跃,这将仍然把所有的应用程序˚F orms前面。如果您 不希望有选择

谁把所有形式的前面,当窗体的所有者仍然是Application.Handle。是应用程序这样做?它为什么这样做?而不是这样做,不应该不是要做到这一点吗? 不是这样做的缺点是什么;我看到的的缺点做它(系统菜单的不propertly工作,任务栏按钮的缩略图是不准确时,Windows ®外壳无法最小化窗口


在另一篇文章中涉及的ApplicationMike Edenfield says that the parent window sends other window's their minimize, maximize and restore messages

这将增加任务栏按钮的形式,但也有其他一些小的细节 手柄。最明显的是,你的表格仍收到最小化/最大化获取发送到父 形式(理论上的主要形式e应用程序)。

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; 

注意,此处理云在家长形式要表现的一个independantly的>:为了避免这种情况,你可以通过添加一条线,如安装WM_SYSCOMMAND消息 处理器应用程序的其余部分,以避免传递最小化消息。您可以添加类似>代码SC_MAXIMIZE,SC_RESTORE等

它是如何最小化/最大化/还原我的Windows ® Windows消息都不会到我的窗口?这是否是因为发往窗口的消息是由Windows ®发送给窗口的所有者?在这种情况下,Delphi应用程序中的所有表单均由Application“拥有”?这是否并不意味着让车主空:

procedure TForm2.CreateParams(var Params: TCreateParams); 
begin 
    inherited; 
    Params.WndParent := 0; //NULL 
end; 

将删除Application,并从我的形式,干扰它的窗口句柄,和Windows应该再次发出我mimimize /最大化/还原邮件?


或许,如果我们比较和对照现在“正常”的Windows应用程序做的事情,与Borland如何最初设计Delphi应用程序做的事情 - 对于此Application对象和它的主循环。

  • 什么解决方案是Application对象解决?
  • Delphi的后续版本做了哪些修改,以便这些相同的问题不存在?
  • Delphi的后续版本中的更改是否引入了其他问题,即初始应用程序设计如何努力解决?
  • 这些较新的应用程序如何在没有Application干扰的情况下仍能正常工作?

很明显,Borland意识到了他们最初设计中的缺陷。他们最初的设计是什么?它解决了什么问题?缺陷是什么?重新设计了什么?它是如何解决问题的?

+0

我想你会有兴趣了解这两个技巧:http://yoy.be/item.asp?i89 http://yoy.be/item.asp?i87 – 2010-02-05 07:12:30

+2

@Stinh桑德斯:我'已经看到了这些,他们不解决问题。此外,绝对不要将GetDesktopWindow作为窗口的所有者传递,因为这些主题和其他帖子都暗示了这一点。这样做会导致Windows冻结。这是微软修补CreateWindow的一个问题,因此任何传递GetDesktopWindow作为所有者的人都改为使用NULL。如果我可以在** yoy.com **上编辑该帖子,我会的。 – 2010-02-05 14:52:39

回答

47

应用程序窗口的原因有点肮脏的历史。在开发Delphi 1时,我们知道我们想要使用IDE的“SDI”(分布在整个桌面上的窗口)ui模型。我们也知道Windows在该模型中吸引(并且仍然如此)。但是我们也注意到当时的Visual Basic使用了这个模型,它似乎运行良好。经过进一步检查,我们发现VB使用了一个特殊的“隐藏”停车窗口,用作所有其他可见窗口的“所有者”(Windows有时会模糊父母和所有者的概念,但区别与VCL类似) 。

这就是我们如何解决包含主菜单的窗口很少聚焦的“问题”,因此处理文件菜单的Alt-F根本行不通。通过使用此中央停车窗口作为中介,我们可以更轻松地跟踪消息并将消息路由到适当的窗口。

这种安排也解决了另一个问题,即通常多个顶级窗口完全独立。通过让应用程序处理所有这些窗口的“所有者”,它们都将表现得一致。例如,您可能已经注意到,当您选择任意的应用程序窗口,全部时,应用程序窗口将移动到前面并保持其相对于彼此的z顺序。这也将使应用程序最小化和恢复为一个功能分组。

这是使用此模型的结果。我们可能已经手动完成所有这些工作,以保持事情的顺利,但设计理念是不重新发明Windows,而是在可能的地方利用它。这也是为什么TButton或TEdit分别是真的一个Windows“用户”按钮和编辑窗口类和样式。随着Windows的发展,这个“SDI”模型开始失宠。事实上,Windows本身开始对这种应用风格产生“敌意”。从Windows Vista开始,继续到7,用户外壳似乎不适用于使用停车窗口的应用程序。所以,我们着手在VCL中进行混洗,以消除停车窗口并将其功能移到主窗体中。这提出了几个“鸡和鸡蛋”的问题,我们需要在应用程序初始化时足够早地提供停放窗口,以便其他窗口可以“附加”到它,但主窗体本身可能不会很快构建。应用程序必须通过几个环节才能实现这一目标,并且出现了一些引起问题的微妙边缘案例,但大部分问题已经解决。但是,对于您前进的任何应用程序,它将继续使用较旧的停车窗模型。

+3

+1互联网。并被接受。 – 2010-02-06 03:56:52

+1

+1,因为它是肮脏的。而添加到微软窗口管理层的Windows XP黑客是这个系统死亡的一部分,因为当你在XP上运行Delphi 7应用程序时,可怕的Z-Order错误开始出现。 – 2010-02-10 16:51:03

7

从看着forms.pas(德尔福2009)源,它似乎是在Win32 GUI应用创建一个“主”窗口允许

  • TApplication的电话。最小化
  • TApplication.Restore

看来,传递给Application.Handle消息转发酌情向MainForm,如果它存在。如果主窗口尚未创建,这将允许应用程序响应最小化等。通过修改项目源代码,您可以创建一个delphi应用程序而不需要一个主窗口。

在这种情况下,即使您尚未创建主窗口,TApplication方法仍然可以工作。不知道我是否抓住了所有的目的,但我没有时间去浏览所有的TApplication代码。

根据您的问题:

  • 它从何而来?它是在TApplication.Create

  • 创建的窗口句柄是什么窗口句柄?每个GUI Delphi应用程序需要为TApplication的抽象

  • 的一部分假的窗口是它appliation的主要形式的窗口句柄没有

  • 如果它不是应用程序的MainForm中的手柄,然后什么是吗?见上面

  • 更重要的是:为什么它是每种形式的最终父母?假设你是对的,它的最终父母,我认为它是如此,因为它可以很容易地找到你的应用程序中的所有形式(列举这个“主”形式的孩子)。

  • 和最重要的是:为什么一切就会失控,如果我尝试有一个表格是unparented我想是因为隐藏的“大师”的形式获取系统信息,它应该传给其子和/或者mainform,但是找不到未登录的表单。

无论如何,这是我的承担。您可以通过查看forms.pas中的TApplication声明和代码了解更多信息。我看到的底线是一个方便的抽象。

最好的问候,

+1

在Delphi 2007中,VCL更改为默认为没有隐藏窗口,但如果有帮助,您也可以选择旧的方式。隐藏的窗口阻止Windows 7预览正常工作。 – mj2008 2010-02-05 09:00:37

+0

@ mj2008:你有链接了解更多关于这方面的信息吗?我目前正在从C++ Builder 2006 - > C++ Builder 2009更新项目,我相信我看到我的Application-> Handle ptr为NULL。现在在Builder 2009中是这种情况吗?如果是这样,将使用MainForm-> Handle是一个很好的替代品? – 2010-06-07 00:38:04

+0

@Rob这个Delphi控件是Application.MainFormOnTaskbar,但我不知道它是否适用于你。通常,升级后的应用程序没有更改。 – mj2008 2010-06-09 10:32:58

11

所有VCL的应用程序有一个叫做应用程序 “隐藏” 的顶层窗口。这是在应用程序启动时自动创建的。除此之外,它是VCL的主要窗口消息处理程序 - 因此是Application.ProcessMessages。

隐藏应用程序顶层窗口确实会导致一些奇怪的事情,显然是任务栏中显示的不完整系统菜单以及Vista中不正确的缩略图窗口。 Delphi的更新版本纠正了这一点。

但是,并非所有的窗口都必须将其作为父窗口,否则Windows会更好地工作。 但是,使用Application.CreateForm创建的任何表单都将其作为父级,并且它也将由Application对象拥有。由于他们是拥有的,他们将被释放,一旦应用程序被释放。这发生在Forms.DoneApplication的幕后。

+3

应用程序的顶级表单没有将其父属性设置为“应用程序”窗口!只有所有者被设置为应用程序对象。 只是澄清:Application.ProcessMessages处理主线程(所有VCL窗口)中所有窗口的消息,它实际上是在所有Windows GUI应用程序中找到的正常消息处理循环中的一个步骤。 – 2010-02-05 07:06:18

+0

@Ritsaert Hornstra:我的应用程序的顶级表格有哪些处理**?还要注意,我创建的任何表单都具有'Application.Handle'作为它们的父类。 – 2010-02-05 14:02:50

+0

所以这可能是为什么http://www.saphua.com/minime/minime.aspx与我的delphi(7)应用程序无法正常工作。 +1的信息的金块。 – cmw 2010-02-05 14:17:03