Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2014年06月04日] [更新 2014年06月05日] Delphi サンプルプログラム集
   
712_タスクバーへの追加・削除とプログレス表示
動作確認等 Windows 7 U64(SP1) + Delphi XE(UP1) Pro
Windows 7 U64(SP1) * Delphi XE6 Pro
712_Taskbar_Progress.zip [2,616 KB] 2014年06月05日版(EXE同梱)







タスクバーへの追加・削除とプログレス表示


タスクバーへのボタン (アイコン) 表示関係のサンプルです.
ITaskbarList インターフェイスを使用します.このインターフェイスは,Delphi 2010 で実装されています.Delphi 2009 以前で使用するには,インターフェイスの実装が必要です.

もし 1 つは,タスクバーに進行状況用のプログレスを表示するサンプルです.この機能は Windows 7 で実装されました.Windows 7 では,以下の MSDN の記事のように,これ以外にもタスクバー関係のインターフェイスが実装されています.


タスクバーへのフォームのアイコン表示関係のサンプルが,以下のサンプルにもあります.
タスクバーの表示の制御は,アプリケーションウィンドウの操作が関係します.Delphi 2007 ではアプリケーションウィンドウが扱いやすくなっています.
Delphi 2007 より前で,このアプリケーションウィンドウに対応するには,[... 秘密のウインドウに対する対処] の記事が参考になります.





[備考]
Delphi 2009 以前で,本ページで使用している ITaskbarList, ITaskbarList3 インターフェイスを使用するには,ShObjidl.idl という IDL ファイルからタイプライブラリを作成し,タイプライブラリを取り込みます.タイプライブラリの取り込みで作成したユニットから,それらのインターフェイス部分だけのコードを取り出して利用することになります.ただし,修正が必要な場合もあります.

ShObjidl.idl は,Windows SDK 8.1 で提供されています.以下の記事を参考にしてください.

[注意]
上の文章で,インターフェイスのコードを追加すれば利用可能と書きましたが,Delphi 2006 以前では [秘密のウィンドウ] に対処するコードが必要です.
ただし,Delphi 2006 以前のプロジェクトを,そのまま Delphi 2007 以降で使用する場合は,やはり [秘密のウィンドウ] に対処したコードが必要です.
Delphi 2007 以降で,新規にプロジェクトを作成する場合は,秘密のウィンドウに対処したコードは必要ありません.

Delphi 2007 以降と,それより前では,プロジェクトのソースコードに違いがあります.以下の記事を参考にしてください.




01_任意のフォームをタスクバーに表示  -  ITaskbarList


複数の子フォームを持つアプリケーションで,任意のフォームのボタンをタスクバーに表示するための参考サンプルです.
本サンプルでは,3 つの子フォームを作成します.これらは,自動生成から除外して,実行時に生成します.タスクバーには,メインフォームと,現在アクティブなフォームを表示します.

ITaskbarList インターフェイスのインスタンスをメインフォームのユニットで生成し,子フォームの OnActivate イベントと OnDeactivate イベントで,タスクバーへの表示を制御します.

ITaskbarList インターフェイスのコードは,Delphi 2010 には実装されています.Delphi 2009 以前ではインターフェイスのコードを追加しないと使用できません.また,Delphi 2006 以前では [秘密のウインドウ] に対処したコードも必要です.



図1
設計時のメインフォームと子フォーム

下図が実行時の画面です.ボタンをクリックすると,子フォームを表示します.その子フォームがアクティブになると,メインフォームとは別に,子フォームのボタンがタスクバーに表示されます.
別の子フォームがアクティブなると,その子フォームがタスクバーに表示され,非アクティブになった子フォームは,タスクバーから削除されます.


図2
アプリ起動直後
  • メインフォームのアイコンがタスクバーに表示される
図3
子フォームを表示
  • 表示した子フォームのアイコンがタスクバーに表示される
図4
アクティブな子フォームを変更
  • メインフォームと,アクティブな子フォームだけがタスクバーに表示される

タスクバーのサムネイル画像は,メインフォームとアクティブな子フォームがグループ表示となっています.


図5
タスクバーのサムネイル画像

リスト1
メインフォームとは別に,子フォームのアイコンをタスクバーに表示する
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ShlObj, ComObj;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    FrmTaskBarList : ITaskbarList;
  end;

var
  Form1: TForm1;

implementation

uses Unit2, Unit3, Unit4;

{$R *.dfm}

//=============================================================================
//  任意のフォームのボタンをタスクバーに表示
//  子フォームでITaskbarListインターフェイスを使用
//  メインフォームは常にタスクバーに表示
//
//  フォーム生成時の処理
//  ITaskbarListインターフェイスの生成
//  ITaskbarListの使用には,usesにShlObjが必要
//  CreateComObjectの使用には,usesにComObjが必要
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  FrmTaskBarList := CreateComObject(CLSID_TaskbarList) as ITaskBarList;
end;

//=============================================================================
//  フォーム破棄時の処理
//  ITaskbarListインターフェイスを解放
//=============================================================================
procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(FrmTaskBarList) then FrmTaskBarList := nil;
end;

//=============================================================================
//  Form2を生成して表示
//  Form2は自動生成から除外している
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2 := TForm2.Create(Self);
  Form2.Left := Self.Left + 100;
  Form2.Top  := Self.Top  + 30;

  Form2.Show;
end;

//=============================================================================
//  Form3を生成して表示
//  Form3は自動生成から除外している
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
  Form3 := TForm3.Create(Self);
  Form3.Left := Self.Left + 130;
  Form3.Top  := Self.Top  + 80;

  Form3.Show;
end;

//=============================================================================
//  Form4を生成して表示
//  Form4は自動生成から除外している
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
begin
  Form4 := TForm4.Create(Self);
  Form4.Left := Self.Left + 160;
  Form4.Top  := Self.Top  + 130;

  Form4.Show;
end;

end.


リスト2
子フォームのコード.他の子フォームのコードも同じ
このコード内でタスクバーへの表示を制御する
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm2 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormActivate(Sender: TObject);
    procedure FormDeactivate(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form2: TForm2;

implementation

uses Unit1;

{$R *.dfm}

//=============================================================================
//  フォームを閉じる時の処理
//  このフォームは,自動生成から除外しているので自身を解放
//=============================================================================
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

//=============================================================================
//  OnActivateイベント処理
//  タスクバーに追加して,そのタスクバーのボタンをアクティブに
//=============================================================================
procedure TForm2.FormActivate(Sender: TObject);
begin
  if Form1.FrmTaskBarList <> nil then begin
    Form1.FrmTaskBarList.AddTab(Self.Handle);
    Form1.FrmTaskBarList.ActivateTab(Self.Handle);
  end;
end;

//=============================================================================
//  OnDeactivateイベント処理
//  タスクバーから消去
//=============================================================================
procedure TForm2.FormDeactivate(Sender: TObject);
begin
  if Form1.FrmTaskBarList <> nil then begin
    Form1.FrmTaskBarList.DeleteTab(Self.Handle);
  end;
end;

end.




02_アクティブなフォームだけをタスクバーに表示  -  ITaskbarList


前項のサンプルと同じように,複数の子フォームを持つアプリケーションの例です.
本サンプルでは,メインフォームと子フォームも含めて,現在アクティブなフォームだけをタスクバーに表示します.
前項のサンプルと違うのは,子フォームに書いてある,タスクバーへの表示制御のコードを,メインフォームにも追加しただけです.

ITaskbarList インターフェイスのコードは,Delphi 2010 には実装されています.Delphi 2009 以前ではインターフェイスのコードを追加しないと使用できません.また,Delphi 2006 以前では [秘密のウインドウ] に対処したコードも必要です.



図6
設計時のメインフォームと子フォーム

その前に,複数のフォームがあるアプリケーションの動作を確認しておくことにします.
下図がその結果です.
複数のフォームを持つアプリケーションは,子フォームを表示しても,タスクバーに表示されるのはメインフォームだけです.もちろん,タスクバーのサムネイル画像はメインフォームです.


図7
実行して,子フォームを表示
  • タスクバーには,メインフォームのボタンだけが表示される
図8
タスクバーのサムネイル
  • 子フォームがアクティブでも,メインフォームのサムネイル

下図が,本サンプルでの実行結果です.
現在アクティブなフォームだけしか,タスクバーに表示しません.また,サムネイルも,現在アクティブなフォームの画像となります.


図9
子フォームを表示
  • 表示した子フォームがタスクバーに表示される
  • ここでは,Form3
  • メインフォームはタスクバーに表示されない
図10
タスクバーのサムネイル画像
  • アクティブな子フォームのものとなっている

リスト3
現在アクティブなフォームだけをタスクバーに表示するサンプル
子フォームのコードは,前項のサンプルと同じ
implementation

uses Unit2, Unit3, Unit4;

{$R *.dfm}

//=============================================================================
//  アクティブなフォームだけをタスクバーに表示
//  子フォームでもITaskbarListインターフェイスを使用
//
//  フォーム生成時の処理
//  ITaskbarListインターフェイスの生成
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  FrmTaskBarList := CreateComObject(CLSID_TaskbarList) as ITaskBarList;
end;

//=============================================================================
//  フォーム破棄時の処理
//  ITaskbarListインターフェイスを解放
//=============================================================================
procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(FrmTaskBarList) then FrmTaskBarList := nil;
end;

//=============================================================================
//  OnActivateイベント処理
//  タスクバーに追加して,そのタスクバーのボタンをアクティブに
//=============================================================================
procedure TForm1.FormActivate(Sender: TObject);
begin
  if FrmTaskBarList <> nil then begin
    FrmTaskBarList.AddTab(Self.Handle);
    FrmTaskBarList.ActivateTab(Self.Handle);
  end;
end;

//=============================================================================
//  OnDeactivateイベント処理
//  タスクバーから消去
//=============================================================================
procedure TForm1.FormDeactivate(Sender: TObject);
begin
  if FrmTaskBarList <> nil then begin
    FrmTaskBarList.DeleteTab(Self.Handle);
  end;
end;

//=============================================================================
//  Form2を生成して表示
//  Form2は自動生成から除外している
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2 := TForm2.Create(Self);
  Form2.Left := Self.Left + 100;
  Form2.Top  := Self.Top  + 30;

  Form2.Show;
end;

//=============================================================================
//  Form3を生成して表示
//  Form3は自動生成から除外している
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
  Form3 := TForm3.Create(Self);
  Form3.Left := Self.Left + 130;
  Form3.Top  := Self.Top  + 80;

  Form3.Show;
end;

//=============================================================================
//  Form4を生成して表示
//  Form4は自動生成から除外している
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
begin
  Form4 := TForm4.Create(Self);
  Form4.Left := Self.Left + 160;
  Form4.Top  := Self.Top  + 130;

  Form4.Show;
end;




03_タスクバーでプログレス表示  -  ITaskbarList3


タスクバーにプログレス表示するサンプルです.この機能は Windows 7 以降で有効となります.
ITaskbarList3 インターフェイスの機能を使用します.

ITaskbarList3 インターフェイスのコードは,Delphi 2010 には実装されています.Delphi 2009 以前ではインターフェイスのコードを追加しないと使用できません.また,Delphi 2006 以前では [秘密のウインドウ] に対処したコードも必要です.



図11
設計時画面

実行画面です.
SetProgressState 関数の引数の値によって,プログレスの色等が変わります.


図12
タスクバーに進行状況を表示

リスト4
タスクバーにプログレス表示するサンプル
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ShlObj, ComObj;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    TaskBarList3 : ITaskbarList3;
  end;

var
  Form1: TForm1;

implementation

uses MMSystem;

{$R *.dfm}

//=============================================================================
//  フォーム生成時の処理
//  ITaskbarListインターフェイスの生成して,それからITaskbarList3を生成
//  ITaskbarList3はDelphi2010で実装されている
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
  TaskBarList : ITaskbarList;
begin
  //ローカル変数は不定なので念のため初期化
  TaskBarList := nil;
  //Windows 7以上なら実行
  if not CheckWin32Version(6, 1) then exit;

  TaskBarList := CreateComObject(CLSID_TaskbarList) as ITaskBarList;
  if TaskBarList = nil then exit;

  //IUnknownインターフェイスの派生インターフェイスはQueryInterfaceが使用可能
  if TaskBarList.QueryInterface(IID_ITaskbarList3, TaskBarList3) =S_OK then begin
    //ITaskBarList3のインターフェイスのインスタンス(TaskBarList3)取得成功
  end else begin
    //ITaskBarList3のインターフェイスのインスタンス(TaskBarList3)取得失敗
  end;
  TaskBarList := nil;
end;

//=============================================================================
//  フォーム破棄時の処理
//  ITaskbarList3インターフェイスを解放
//=============================================================================
procedure TForm1.FormDestroy(Sender: TObject);
begin
  if TaskBarList3 <> nil then TaskBarList3 := nil;
end;

//=============================================================================
//  タスクバーにプログレスを表示
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  MaxTime   : UInt64;
  aTime     : UInt64;
  StartTime : Cardinal;
begin
  if TaskBarList3 = nil then exit;

  MaxTime   := 5000;
  StartTime := TimeGetTime;

  TaskBarList3.SetProgressState(Handle, TBPF_NORMAL);

  //何かの処理の代わりとしてのループ
  while True do begin
    aTime := timeGetTime - StartTime;
    if aTime > MaxTime then break;

    TaskBarList3.SetProgressValue(Handle, aTime, MaxTime);

    Application.ProcessMessages;
    Sleep(1);
  end;
  TaskBarList3.SetProgressState(Handle, TBPF_NOPROGRESS);
end;

end.


ITaskbarList3 インターフェイスの継承関係は次のようになっています.
前項のサンプルで使用した ITaskbarList を継承したインターフェイスとなっています.


CLSID_ITaskbarList: TGUID...
    .... 
ITaskbarList = interface(IUnknown)
ITaskbarList2 = interface(ITaskbarList)
ITaskbarList3 = interface(ITaskbarList2)
ITaskbarList4 = interface(ITaskbarList3)


したがって,上のコードでは,QueryInterface 関数を使用しましたが,次のように,Supports 関数を使用してもインターフェイスのインスタンスを取得することができます.
Supports 関数は,内部で QueryInterface 関数を実行しています.


procedure TForm1.FormCreate(Sender: TObject);
var
  TaskBarList : ITaskbarList;
begin
  //ローカル変数は不定なので念のため初期化
  TaskBarList := nil;
  //Windows 7以上なら実行
  if not CheckWin32Version(6, 1) then exit;

  TaskBarList := CreateComObject(CLSID_TaskbarList) as ITaskBarList;
  if TaskBarList = nil then exit;

  if Supports(TaskbarList, IID_ITaskbarList3, TaskbarList3) then begin
    //ITaskBarList3のインターフェイスのインスタンス(TaskBarList3)取得成功
  end else begin
    //ITaskBarList3のインターフェイスのインスタンス(TaskBarList3)取得失敗
  end;
  TaskBarList := nil;
end;


また,ITaskbarList インターフェイスのインスタンスを生成しなくても,CoCreateInstance 関数を使用して次のように ITaskbarList3 のインスタンスを取得することもできます.


procedure TForm1.FormCreate(Sender: TObject);
begin
  //Windows 7以上なら実行
  if not CheckWin32Version(6, 1) then exit;

  //CoCreateInstanceとCLSCTX_ALLの使用には,usesにActiveXが必要
  if Succeeded(CoCreateInstance(CLSID_TaskbarList,
                                nil,
                                CLSCTX_ALL,
                                IID_ITaskbarList3,
                                TaskBarList3)) then begin
    //ITaskBarList3のインターフェイスのインスタンス(TaskBarList3)取得成功
  end else begin
    //ITaskBarList3のインターフェイスのインスタンス(TaskBarList3)取得失敗
  end;
end;




04_タスクバーでプログレス表示  -  TTaskbar コンポーネント


前項と同じく,タスクバーにプログレス表示するサンプルです.この機能は Windows 7 以降で有効となります.
Delphi XE6 では,タスクバーを操作するための TTaskbar コンポーネントが追加されました.このコンポーネントを使用した例です.



図13
設計時画面
図14
実行画面

リスト5
タスクバーにプログレス表示するサンプル
Delphi XE6 で実装された TTaskbar コンポーネントを使用する例
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  System.Win.TaskbarCore, Vcl.Taskbar, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Taskbar1: TTaskbar;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses MMSystem;

{$R *.dfm}

//=============================================================================
//  タスクバーにプログレス表示
//  Delphi XE6で実装されたTTaskBarコンポーネントを使用
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  MaxTime   : UInt64;
  aTime     : Cardinal;
  StartTime : Cardinal;
begin
  //Windows 7以上なら実行
  if not CheckWin32Version(6, 1) then exit;

  MaxTime   := 7000;
  StartTime := TimeGetTime;

  Taskbar1.ProgressMaxValue := MaxTime;
  Taskbar1.ProgressState    := TTaskBarProgressState.Normal;

  //何かの処理の代わりとしてのループ
  while True do begin
    aTime := timeGetTime - StartTime;
    if aTime > MaxTime then break;

    Taskbar1.ProgressValue := aTime;

    Application.ProcessMessages;
    Sleep(1);
  end;
  Taskbar1.ProgressValue := 0;
end;

end.


Delphi XE6 に,TTaskbar コンポーネントのサンプルがあります.
場所は,下図のように,[Samples] フォルダの [VCL] の [Taskbar] フォルダ内です.


図15
[スタート] から,サンプルのフォルダを開く
図16
TTaskbar コンポーネントのサンプルがある場所