∵ なぜならば

映画とかネットとかパソコンとかコミックとか音楽とか……

Application.MainFormOnTaskbar

2021-09-11 12:24:51 | Delphi
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.}のコメントを外してください

プロジェクトソース
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」あたり使いまくってるのでキチンとテストしなくてはいけない
コメント (2)    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 1.2.4 アップしました | トップ | 正規表現ライブラリ SkRegExp »
最新の画像もっと見る

2 コメント

コメント日が  古い順  |   新しい順
ダメダメ (Terry(まも))
2021-10-17 17:51:03
まずメインフォームを最小化した時にサブウィンドウも付随する処理書かないといけないし
ちょっと気をぬくとタスクバーから消えたりスプラッシュフォームが現れたりする

またタスクトレイアイコン処理してる場合更に複雑になる
やっぱダメかも (Terry(まも))
2021-11-06 11:21:32
くろねこさんの方法を色々試したんだけど
タスクバーの問題は解決しても
Show したフォームが手前に出張るのはどうにもできないわ

コメントを投稿

Delphi」カテゴリの最新記事