Note that there are some explanatory texts on larger screens.

plurals
  1. PODelphi: What is Application.Handle?
    primarykey
    data
    text
    <p>What is <code>TApplication.Handle</code>? </p> <ul> <li>Where does it come from? </li> <li>Why does it exist? </li> <li>And most importantly: why do all forms have it as their parent window handle?</li> </ul> <p>The Delphi help says:</p> <blockquote> <p><strong>TApplication.Handle</strong></p> <p>Provides access to the window handle of the main form (window) of the application.</p> <pre><code>property Handle: HWND; </code></pre> <p><strong>Description</strong></p> <p>Use Handle when calling Windows API functions that require a parent window handle. For example, a DLL that displays its own top-level pop-up windows needs a parent window to display its windows in the application. Using the Handle property makes such windows part of the application, so that they are minimized, restored, enabled and disabled with the application.</p> </blockquote> <p>If i focus on the words "<em>the window handle of the main form of the application</em>", and i take that to mean <em>the window handle of the main form of the application</em>, then i can compare: </p> <ul> <li>"the window handle of the main form of the application", with</li> <li>the window handle of the <code>MainForm</code> of the <code>Application</code></li> </ul> <p>but they are not the same:</p> <pre><code>Application.MainForm.Handle: 11473728 Application.Handle: 11079574 </code></pre> <p>So what is <code>Application.Handle</code>? </p> <ul> <li>Where does it come from? </li> <li>What Windows&reg; window handle is it?</li> <li>If it <strong>is</strong> the Windows&reg; window handle of the <code>Application</code>'s <code>MainForm</code>, then why don't they match?</li> <li>If it's <strong>not</strong> the window handle of the <code>Application</code>'s <code>MainForm</code>, then what is it?</li> <li>More importantly: Why is it the ultimate <strike>parent</strike> owner of every form?</li> <li>And most important: Why does everything go haywire if i try to have a form be <strike>unparented</strike> unowned (so i it can appear on the TaskBar), or try to use something like <strong>IProgressDialog</strong>?</li> </ul> <p>Really what i'm asking is: What is the design rationale that makes <strong>Application.Handle</strong> exist? If i can understand the why, the how should become obvious.</p> <hr> <p><strong>Update</strong> Understanding through a game of twenty questions:</p> <p>In talking about the solution of making a window appear on the taskbar by making its owner <code>null</code>, <a href="http://groups.google.com/group/borland.public.delphi.objectpascal/msg/1754081cc34d3576" rel="nofollow noreferrer">Peter Below in 2000 said</a>:</p> <blockquote> <p>This can cause some problems with modal forms shown from secondary forms. </p> <p>If the user switches away from the app while a modal form is up, and then back to the form that showed it, the modal form may hide beneath the form. It is possible to deal with this by making sure the modal form is parented [sic; he meant owned] to the form that showed it (using <code>params.WndParent</code> as above) </p> <p>But this is not possible with the standard dialogs from the <code>Dialogs</code> unit and <strong>exceptions</strong>, which need more effort to get them to work right (basically handling <code>Application.OnActivate</code>, looking for modal forms parented to <strong>Application</strong> via <code>GetLastActivePopup</code> and bringing them to the top of the Z-order via <code>SetWindowPos</code>). </p> </blockquote> <ul> <li>Why does a modal form end up stuck behind other forms?</li> <li>What mechanism normally brings a modal form to the front, and why is it not functional here?</li> <li>Windows&reg; is responsible for showing windows stacked. What has gone wrong that Windows&reg; isn't showing the right windows?</li> </ul> <p>He also talked about using the new Windows extended style that forces a window to appear on the taskbar (when the normal rules of making it un-owned is insufficient, impractical, or undesirable), by adding the <code>WS_EX_APPWINDOW</code> extended style:</p> <pre><code>procedure TForm2.CreateParams(var Params: TCreateParams); begin inherited CreateParams( params ); Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW; end; </code></pre> <p>But then he cautions: </p> <blockquote> <p>If you click on a secondary forms taskbar button while another app is active this will still bring all the applications forms to front. If you do not want that there is option </p> </blockquote> <p>Who is bringing all the forms to the front when the form's owner is still <code>Application.Handle</code>. Is <strong>Application</strong> doing this? Why is it doing this? Rather than doing this, shouldn't it <strong>not</strong> be doing this? What is the downside of <strong>not</strong> doing this; i see the downside of <strong>doing</strong> it (system menu's don't work propertly, taskbar button thumbnails are inaccurate, Windows&reg; shell cannot minimize windows.</p> <hr> <p>In another post dealing with the <code>Application</code>, <a href="http://www.delphi3000.com/articles/article_723.asp?SK=" rel="nofollow noreferrer">Mike Edenfield says that the parent window sends other window's their minimize, maximize and restore messages</a>:</p> <blockquote> <p>This will add the taskbar button for your form, but there are a few other minor details to handle. Most obviously, your form still receives minimize/maximize that get sent to the parent form (the main form of the application). In order to avoid this, you can install a message handler for WM_SYSCOMMAND by adding a line such as: </p> <pre><code>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; </code></pre> <p>Note that this handler goes in the <strong>PARENT</strong> form of the one you want to behave independantly of > the rest of the application, so as to avoid passing on the minimize message. You can add similar > code for SC_MAXIMIZE, SC_RESTORE, etc.</p> </blockquote> <p>How is it that minimize/maximize/restore messages for my Windows&reg; windows are not going to my window? Is this because messages destined for a window are sent, by Windows&reg; to the window's owner? And in this case all the forms in a Delphi application are "owned" by <code>Application</code>? Does that not mean that making the owner null:</p> <pre><code>procedure TForm2.CreateParams(var Params: TCreateParams); begin inherited; Params.WndParent := 0; //NULL end; </code></pre> <p>will remove <code>Application</code> and it's window Handle from interfering with my form, and Windows should once again send <em>me</em> my mimimize/maximize/restore messages?</p> <hr> <p>Perhaps if we compared and contrasted now a "normal" Windows application does things, with how Borland initially designed Delphi applications to do things - with respect to this <code>Application</code> object and it's main loop. </p> <ul> <li>what solution was the <code>Application</code> object solving?</li> <li>What change was made with later versions of Delphi so that these same issues don't exist? </li> <li>Did the change in later versions of Delphi not introduce other problems, that the inital Application design tried so hard to solve?</li> <li>How can those newer applications still function without Application interfering with them?</li> </ul> <p>Obviously Borland realized the flaw in their initial design. What was their initial design, what problem was it solving, what is the flaw, what was the re-design, and how does it solve the problem?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload