とはTApplication.Handle
?
- それはどこから来たのですか?
- なぜそれが存在するのですか?
- そして最も重要なのは、なぜすべてのフォームがそれを親ウィンドウ ハンドルとして持っているのでしょうか?
Delphi のヘルプには次のように書かれています。
TApplication.ハンドル
アプリケーションのメイン フォーム (ウィンドウ) のウィンドウ ハンドルへのアクセスを提供します。
property Handle: HWND;
説明
親ウィンドウ ハンドルを必要とする Windows API 関数を呼び出す場合は、Handle を使用します。たとえば、独自のトップレベルのポップアップ ウィンドウを表示する DLL には、アプリケーションでウィンドウを表示するための親ウィンドウが必要です。Handle プロパティを使用すると、そのようなウィンドウがアプリケーションの一部になるため、アプリケーションで最小化、復元、有効化、および無効化できます。
「アプリケーションのメイン フォームのウィンドウ ハンドル」という言葉に注目し、それをアプリケーションのメイン フォームのウィンドウ ハンドルと解釈すると、次のように比較できます。
- 「アプリケーションのメイン フォームのウィンドウ ハンドル」、
MainForm
のウィンドウハンドルApplication
しかし、それらは同じではありません:
Application.MainForm.Handle: 11473728
Application.Handle: 11079574
だから何Application.Handle
ですか?
- それはどこから来たのですか?
- どの Windows® ウィンドウ ハンドルですか?
- の Windows® ウィンドウ ハンドルである場合、一致しない
Application
のMainForm
はなぜですか? - のウィンドウ ハンドルでない場合、それは何ですか?
Application
MainForm
- さらに重要なのは、なぜそれがすべてのフォームの最終的な
親所有者なのかということです。 - そして最も重要なのは、フォームを親から外して所有しないようにしようとしたり (タスクバーに表示できるようにするため)、または IProgressDialog のようなものを使用しようとすると、すべてがうまくいかない
のはなぜですか?
本当に私が求めているのは、Application.Handleを存在させる設計上の根拠は何ですか? その理由を理解できれば、その方法が明らかになるはずです。
20 の質問のゲームを通して理解を更新します。
所有者を作成することによってウィンドウをタスクバーに表示する解決策について話す際にnull
、Peter Below は 2000 年に次のように述べています。
これにより、セカンダリ フォームから表示されるモーダル フォームで問題が発生する可能性があります。
モーダル フォームが起動しているときにユーザーがアプリから切り替えて、それを表示していたフォームに戻ると、モーダル フォームがフォームの下に隠れる場合があります。モーダルフォームが親であることを確認することで、これに対処することができます [sic; 彼はそれを示したフォームに所有することを意味しました(
params.WndParent
上記のように使用)
Dialogs
しかし、これはunit およびexceptionからの標準ダイアログでは不可能であり、それらを正しく機能させるにはより多くの努力が必要です (基本的に、 を処理し、 Application viaApplication.OnActivate
を親とするモーダル フォームを検索し 、それらを Z オーダーの最上位に移動する via ) 。 .GetLastActivePopup
SetWindowPos
- モーダル フォームが他のフォームの後ろに隠れてしまうのはなぜですか?
- 通常、モーダル フォームを前面に表示するメカニズムは何ですか?ここでは機能しないのはなぜですか?
- 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;
しかし、彼は次のように警告します。
別のアプリがアクティブなときにセカンダリ フォーム タスクバー ボタンをクリックすると、すべてのアプリケーション フォームが前面に表示されます。したくない場合はオプションがあります
フォームの所有者がまだ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 はもう一度、最小化/最大化/復元メッセージを送信する必要がありますか?
おそらく、「通常の」Windows アプリケーションが実行することと、Borland が最初に Delphi アプリケーションを実行するように設計した方法を比較対照すると、このApplication
オブジェクトとメイン ループに関してです。
Application
オブジェクトはどのソリューションを解決していましたか?- これらの同じ問題が存在しないようにするために、Delphi の新しいバージョンではどのような変更が加えられましたか?
- それ以降のバージョンの Delphi での変更は、最初のアプリケーション設計が解決しようと懸命に試みた他の問題を引き起こしませんでしたか?
- これらの新しいアプリケーションは、アプリケーションがそれらに干渉することなく、どのように機能し続けることができるでしょうか?
明らかに、Borland は初期設計の欠陥に気付きました。彼らの最初の設計は何でしたか、どのような問題を解決しましたか、どのような欠陥がありましたか、どのような再設計が行われたか、どのように問題を解決しましたか?