記事カテゴリ

ユーザー機能


 2024年4月20日(土) 01:53 JST

[Delphi] MainFormOnTaskBarとタスクバーボタン

  • 投稿者:
  • 表示回数
    10,427

Delphi2007 以降からでしょうか?MainFormOnTaskBar と言うプロパティが追加されています。

embarcadero のサイトでは下記のように説明されています。

MainFormOnTaskBar プロパティは、Windows タスクバー ボタンを VCL で扱う方法を制御します。

このプロパティが true の場合、タスクバー ボタンはアプリケーションのメイン フォームを表し、そのキャプションが表示されます。false の場合、タスクバー ボタンは、アプリケーションの(非表示の)メイン ウィンドウを表し、アプリケーションのタイトルが表示されます。
 
Windows Vista Aero 効果を使用するには、MainFormOnTaskBar が true であることが必要です。効果には、ライブ タスクバー サムネイル、動的ウィンドウ、Windows フリップ、Windows フリップ 3D があります。

このプロパティの登場というか、Windows Vista Aero 対応のために Delphi が行った修正によっていろいろとフォームの挙動が変更されました。

以前だと、フォームからフォームを表示しても、タスクバーにはアプリケーションのウィンドウのボタンが表示されていたため、何の変化もありませんでした。
しかし、今はメインフォームのボタンが表示されます。
これがどういうことかもう少しブレイクダウンします。

Form1 から Form2 を表示するアプリケーションを作ります。
Form1 のボタンをクリックすると Form2 を表示することとします。
このコードは下記のようになります。

procedure TForm1.Button1Click(Sender: TObject);
begin
  TForm2.Create(Self).Show;
end;

このアプリケーションを実行すると、タスクバーにはメインフォームである Form1 のボタンが表示されます。
Form2を表示しても同じです。

今度は、Form1 のボタンをクリックすると Form2 を表示し、Form1 はハイドすることとします。
以下のようなコードになります。

procedure TForm1.Button1Click(Sender: TObject);
begin
  TForm2.Create(Self).Show;
  Hide;
end;

このアプリケーションを実行して確認してみると、Form1 の表示時は先ほどと変わりないですが、Form2 を表示するとタスクバーから表示が消えてしまいます。メインフォームが消えてしまったからだと思われます。

これはちょっとまずいと思いました。くろねこ的には、現在アクティブなフォームのアイコンとキャプションを持ったタスクバーアイコンにしたいわけです。とりあえず、この内容を ActiveFormOnTaskBar と名づけます。Delphi で標準対応してほしいところですが、出来ないのでやり方を考えて見ます。

SetWindowLong と SetParent を使用します。

procedure TForm2.ShowTaskbarButton;
begin
  Windows.SetWindowLong(Handle, GWL_EXSTYLE, 
    Windows.GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_APPWINDOW);
  Windows.SetParent(Handle, GetDesktopWindow);
end;

Form1を非表示にしない場合のタスクバーボタンのみ非表示にする関数

procedure TForm1.HideTaskBarButton;
begin
  ShowWindow(Handle, SW_HIDE);
  SetWindowLong(Handle, GWL_EXSTYLE,
    GetWindowLong(Handle, GWL_EXSTYLE) and not WS_EX_APPWINDOW or WS_EX_TOOLWINDOW);
  ShowWindow(Handle, SW_SHOW);
end;

Form2を閉じたときにForm1のタスクバーボタンを元に戻す関数

// Form1側 ---
procedure TForm1.RestoreTaskBarButton;
begin
  Windows.SetWindowLong(Handle, GWL_EXSTYLE, FExStyle);
  Windows.SetParent(Handle, GetDesktopWindow);
end;
// FExStyle は、FormCreate で退避
procedure TForm1.FormCreate(Sender: TObject);
begin
  FExStyle := GetWindowLong(Handle, GWL_EXSTYLE);
end;

// Form2側 ---
procedure TForm2.FormDestroy(Sender: TObject);
begin
  if (Owner is TForm1) then
    with TForm1(Owner) do
    begin
      if not Visible then
        Show;
      RestoreTaskBarButton;
      Refresh;
    end;
end;

現在、だいたいいけるようになりましたが、Form2を表示している際のForm1のタイトルバーが変更されてしまっているのが気になります。外観の変更を伴わずに何とかならないですかね?

■参考:

トラックバック

このエントリのトラックバックURL:
https://www.blackcat.xyz/trackback.php/ProgramingFAQ_del0081

[Delphi] MainFormOnTaskBarとタスクバーボタンで完成できていなかったActiveFormOnTaskBarの動きがようやく完成です。 M社のサポートセンターの方にもご協力いただいて... 実現しました。 ウィンドウスタイルを変更すると概観にも変化が起きてしまうので、今度はタスクバーそのものを直接いじってます。 このため、今回はComObjectを利用することになりました。 よって、uses にComObj, ShlObjを追加しておいてください。 タスクバーにタス... 続きを読む

以下のコメントは、その投稿者が所有するものでサイト管理者はコメントに関する責任を負いません。