Delphi2007 以降に搭載されたプロジェクトファイル内の
Application.MainFormOnTaskbar := True;
(新しいプロジェクトには、この行が自動的に追加)
特殊な構造をしていた Delphiを Windows のエアロ対応にするために歪な方法?で実現した(と私は受け取った)
しかしその副作用のため「Show」したサブフォームがメインフォームより前面に出てしまい見た目が「ShowModal」状態になってしまう問題は現在でも解消されていない(らしい)
https://docwiki.embarcadero.com/Libraries/Sydney/ja/Vcl.Forms.TApplication.MainFormOnTaskBar
『このプロパティに依存するアプリケーションでは、このプロパティが MainForm の Z 順序に影響を与える点に注意してください。』
わざとわかりにくく書いているのか?
要するにこう
「メインフォームから表示したフォームが常にメインフォームの上に表示されてしまう」
こちら↓でも「MainFormOnTaskbar はコメントアウトしようぜ」になってる(記事は古いけど)
フォームの重なり順序を変更する方法は?
おわかりいただけただろうか……
Form1 のタイトルバーがアクティブ色なことに……
Application.MainFormOnTaskbar を False にするとこれは解消されるが Aero が機能せずタスクバーにマウスを持って行った時サブフォームがプレビュー(サムネイル)として表示されたりする
ググった結果くろねこさんがファイナルアンサーを出しているっぽいんだけど
[Delphi] MainFormOnTaskBarとタスクバーボタン
[Delphi] MainFormOnTaskBarとタスクバーボタン2
「ITaskbarList インターフェイス」が Delphi 2010 で実装でそれ以前の Delphi ではタイプライブラリを作成
712_タスクバーへの追加・削除とプログレス表示
というのが邪魔くさかったのともっとわかりやすくて安易な方法を求めて彷徨った結果こちらにたどり着く
「How to allow Delphi secondary forms behind the main form」
つまり姿を隠したスプラッシュフォームをメインフォームに設定してサブフォームの親はすべてこいつにする
本来のメインフォームを閉じる( = アプリケーションの終了)時にスプラッシュフォームを閉じるようにすればユーザーにはわからない
『町娘を嫁にしたいからいったん他の武家の養女にする』みたいな感じ
このままではエアロ対応にはならず
・Application.MainFormOnTaskbar は True のまま
更にはタスクバーに登録されないので
・タスクバーへの登録は自分でやる
※最近の Delphi なら{Winapi.}のコメントを外してください
プロジェクトソース
スプラッシュフォームユニット
【リアル】メインフォームユニット
サブフォームユニット
これでいけると思うが NanaTerry では多重起動処理で「Application.MainForm」あたり使いまくってるのでキチンとテストしなくてはいけない
Application.MainFormOnTaskbar := True;
(新しいプロジェクトには、この行が自動的に追加)
特殊な構造をしていた Delphiを Windows のエアロ対応にするために歪な方法?で実現した(と私は受け取った)
しかしその副作用のため「Show」したサブフォームがメインフォームより前面に出てしまい見た目が「ShowModal」状態になってしまう問題は現在でも解消されていない(らしい)
https://docwiki.embarcadero.com/Libraries/Sydney/ja/Vcl.Forms.TApplication.MainFormOnTaskBar
『このプロパティに依存するアプリケーションでは、このプロパティが MainForm の Z 順序に影響を与える点に注意してください。』
わざとわかりにくく書いているのか?
要するにこう
「メインフォームから表示したフォームが常にメインフォームの上に表示されてしまう」
こちら↓でも「MainFormOnTaskbar はコメントアウトしようぜ」になってる(記事は古いけど)
フォームの重なり順序を変更する方法は?
おわかりいただけただろうか……
Form1 のタイトルバーがアクティブ色なことに……
Application.MainFormOnTaskbar を False にするとこれは解消されるが Aero が機能せずタスクバーにマウスを持って行った時サブフォームがプレビュー(サムネイル)として表示されたりする
ググった結果くろねこさんがファイナルアンサーを出しているっぽいんだけど
[Delphi] MainFormOnTaskBarとタスクバーボタン
[Delphi] MainFormOnTaskBarとタスクバーボタン2
「ITaskbarList インターフェイス」が Delphi 2010 で実装でそれ以前の Delphi ではタイプライブラリを作成
712_タスクバーへの追加・削除とプログレス表示
というのが邪魔くさかったのともっとわかりやすくて安易な方法を求めて彷徨った結果こちらにたどり着く
「How to allow Delphi secondary forms behind the main form」
つまり姿を隠したスプラッシュフォームをメインフォームに設定してサブフォームの親はすべてこいつにする
本来のメインフォームを閉じる( = アプリケーションの終了)時にスプラッシュフォームを閉じるようにすればユーザーにはわからない
『町娘を嫁にしたいからいったん他の武家の養女にする』みたいな感じ
このままではエアロ対応にはならず
・Application.MainFormOnTaskbar は True のまま
更にはタスクバーに登録されないので
・タスクバーへの登録は自分でやる
※最近の Delphi なら{Winapi.}のコメントを外してください
プロジェクトソース
program TestMainFormOnTaskbar; uses Forms, TestMainFormOnTaskbarMainFormUnit in 'TestMainFormOnTaskbarMainFormUnit.pas' {RealMainForm}, Form2Unit in 'Form2Unit.pas' {SubForm}, SplashFormUnit in 'SplashFormUnit.pas' {SplashForm}; {$R *.res} begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TSplashForm, SplashForm); Application.CreateForm(TRealMainForm, RealMainForm); Application.Run; end.
スプラッシュフォームユニット
unit SplashFormUnit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls; type TSplashForm = class(TForm) Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private { Private 宣言 } public { Public 宣言 } procedure CloseApplication; end; var SplashForm: TSplashForm; implementation uses TestMainFormOnTaskbarMainFormUnit;//本来のメインフォーム {$R *.dfm} procedure TSplashForm.CloseApplication; begin Close; end; procedure TSplashForm.FormCreate(Sender: TObject); begin BorderStyle:=bsNone; Height:=1;//見せない方向で…… // Show; // BringToFront; end; procedure TSplashForm.Timer1Timer(Sender: TObject); begin if Assigned(RealMainForm) then begin Visible:=False; //この部分がないとタスクバーに登録されない {Winapi.}Windows.SetWindowLong(RealMainForm.Handle, GWL_EXSTYLE, {Winapi.}Windows.GetWindowLong(RealMainForm.Handle, GWL_EXSTYLE) or WS_EX_APPWINDOW); {Winapi.}Windows.SetParent(RealMainForm.Handle, GetDesktopWindow); RealMainForm.Show; Timer1.Enabled:=False; end else Timer1.Interval:=10;//スプラッシュ画面を見せるならここを長くする end; end.
【リアル】メインフォームユニット
unit TestMainFormOnTaskbarMainFormUnit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TRealMainForm = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private 宣言 } public { Public 宣言 } end; var RealMainForm: TRealMainForm; implementation uses Form2Unit, //SubForm SplashFormUnit;//Close 手続き {$R *.dfm} procedure TRealMainForm.Button1Click(Sender: TObject); begin TSubForm.Create(Self).Show; end; procedure TRealMainForm.FormClose(Sender: TObject; var Action: TCloseAction); begin SplashForm.CloseApplication; end; end.
サブフォームユニット
unit Form2Unit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; type TSubForm = class(TForm) procedure FormCreate(Sender: TObject); private { Private 宣言 } protected procedure CreateParams(var Params:TCreateParams); override; public { Public 宣言 } end; var SubForm: TSubForm; implementation {$R *.dfm} procedure TSubForm.CreateParams(var Params: TCreateParams); begin //Show されるフォーム inherited; Params.WndParent:=Application.MainForm.Handle; end; procedure TSubForm.FormCreate(Sender: TObject); begin Color:=clRed;//わかりやすいように色つける end; end.
これでいけると思うが NanaTerry では多重起動処理で「Application.MainForm」あたり使いまくってるのでキチンとテストしなくてはいけない
ちょっと気をぬくとタスクバーから消えたりスプラッシュフォームが現れたりする
またタスクトレイアイコン処理してる場合更に複雑になる
タスクバーの問題は解決しても
Show したフォームが手前に出張るのはどうにもできないわ