Delphi2007 以降に搭載されたプロジェクトファイル内の
Application.MainFormOnTaskbar := True;
(新しいプロジェクトには、この行が自動的に追加)
特殊な構造をしていた Delphiを Windows のエアロ対応にするために歪な方法?で実現した(と私は受け取った)
しかしその副作用のため「Show」したサブフォームがメインフォームより前面に出てしまい見た目が「ShowModal」状態になってしまう問題は現在でも解消されていない(らしい)
https://docwiki.embarcadero.com/Libraries/Sydney/ja/Vcl.Forms.TApplication.MainFormOnTaskBar
『このプロパティに依存するアプリケーションでは、このプロパティが MainForm の Z 順序に影響を与える点に注意してください。』
わざとわかりにくく書いているのか?
要するにこう
「メインフォームから表示したフォームが常にメインフォームの上に表示されてしまう」
こちら↓でも「MainFormOnTaskbar はコメントアウトしようぜ」になってる(記事は古いけど)
フォームの重なり順序を変更する方法は?
おわかりいただけただろうか……
Form1 のタイトルバーがアクティブ色なことに……
![](https://blogimg.goo.ne.jp/user_image/0b/53/604339f234d5458ea8472cc6550ee9d9.png)
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」あたり使いまくってるのでキチンとテストしなくてはいけない