Delphi: What is Application.Handle?

左心房为你撑大大i 提交于 2019-11-28 16:04:57

The reason for the application window has a bit of a sordid history. When developing Delphi 1, we knew we wanted to use "SDI" (windows scattered all over the desktop) ui model for the IDE. We also knew that Windows sucked (and still does) at that model. However we also noticed that Visual Basic at that time employed that model and it seemed to work well. Upon further examination, we found that VB used a special "hidden" parking window which was used as the "owner" (Windows blurs the notion of parent and owner at times, but the distinction is similar to VCL) for all the other visible windows.

This is how we solved the "problem" where the windows containing the main menu was rarely ever focused so processing Alt-F for the File menu simply wouldn't work. By using this central parking window as an intermediary, we could more easily keep track of and route messages to the appropriate windows.

This arrangement also solved another issue where normally multiple top level windows were entirely independent. By making the application handle the "owner" of all these windows, they would all behave in concert. For instance, you may have noticed that when you select any of the application windows, all the application windows move to the front and retain their z-order relative to each other. This would also make the application minimize and restore as a functional grouping.

That is a consequence of using this model. We could have manually done all this work to keep things straight, but the design philosophy was to not re-invent Windows, but to leverage it where we could. That is also why a TButton or a TEdit is really a Windows "User" BUTTON and EDIT window class and style, respectively.

As Windows evolved, that "SDI" model began to fall out of favor. In fact Windows itself began to become "hostile" to that style of application. Starting with Windows Vista and continuing to 7, the user shell doesn't seem to work well with an application using a parking window. So, we set out to shuffle things around in VCL to eliminate the parking window and move its function into the main form. This presented several "chicken and egg" problems whereby we need to have the parking window available early enough in the application initialization so that other windows can "attach" to it, but the main form itself may not be constructed soon enough. TApplication has to jump through a few hoops to get this to work, and there have been a few subtle edge cases that have caused issue, but most of the problems have been worked out. However, for any application you move forward, it will remain using the older parking window model.

All VCL apps have a "hidden" top level window called Application. This is created automatically on application startup. Amongst other things it is the main windows message handler for VCL - hence Application.ProcessMessages.

Having the apps top level window hidden does cause some strange things, noticeably the incomplete system menu that shows in the task bar, and incorrect thumb nail windows in Vista. Later versions of Delphi correct this.

However, not all windows must have it as a parent, Windows just tends to work better if it is. However, any form created with Application.CreateForm will have it as the parent, and it will also be owned by the Application object. As they are owned, they will be freed once Application is freed. This happen behind the scenes in Forms.DoneApplication

Don Dickinson

From looking at the source in forms.pas (Delphi 2009), it appears that they create a "master" window in win32 gui apps to allow calls to

  • TApplication.Minimize
  • TApplication.Restore
  • etc

It appears that messages passed to the Application.Handle are forwarded as appropriate to the MainForm, if it exists. This would allow the app to respond to minimize, etc if the main window has not been created. By modifying the project source you can create a delphi app without a main window.

In this case, the TApplication methods will still work, even if you haven't created a main window. Not sure if I'm grasping all of the purposes, but I don't have time to go through all of the TApplication code.

Per your questions:

  • Where does it come from? It is the handle of a window created in TApplication.Create

  • What windows handle is it? a fake window that every gui delphi app requires as part of the TApplication abstraction

  • Is it the windows handle of the appliation's main form No

  • If its not the handle of application's mainform then what is it? See above

  • more importantly: why is it the ultimate parent of every form? assuming you're right that its the ultimate parent, i assume that it is so because it makes it easy to find all of forms in your application (enumerating the children of this "master" form).

  • and most important: why does everything go haywire if i try to have a form be unparented i think because the hidden "master" form is getting system messages that it should pass on to its children and/or the mainform, but can't find the unparented form.

Anyway, that's my take on it. You can probably learn more by looking at the TApplication declaration and code in forms.pas. The bottom line from what i see is it is a convenient abstraction.

Best regards,

Don

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!