連載
» 2015年09月09日 05時00分 UPDATE

.NET TIPS:WPF/Windowsフォーム:タスクバーのアイコンにジャンプリストを出すには?[C#、VB]

タスクバーのアイコンに表示されるジャンプリストはアプリの使い勝手を向上させてくれる。本稿では、プログラムからジャンプリストを操作する方法を解説する。

[山本康彦,BluewaterSoft/Microsoft MVP for Windows Platform Development]
.NET TIPS
Insider.NET

 

「.NET TIPS」のインデックス

連載目次

対象:.NET 4.0以降、Windows 7以降


 Windows 7以降ではタスクバーのアイコンを右クリックするとジャンプリストが表示される。ここには、最近使ったファイルの一覧や、プログラム独自のタスクを表示できる。本稿では、.NET 4.0以降のWindowsフォームとWPFでジャンプリストのタスクを利用する方法を解説する。

ジャンプリストとは?

 タスクバー上でプログラムのアイコンをマウスで右クリックするか上へドラッグすると(タッチ操作では、長押しするか上へスライドすると)、ジャンプリストが表示される(次の画像)。ジャンプリストに表示される項目には、次のような種類がある。

  • [最近使ったもの]/[よく使うもの]: この2種類の項目は、Windowsが管理している(本稿では扱わない)*1。ファイルの拡張子と関連付けられているプログラムの場合、ファイルを開くと自動的に項目が更新されていく。
  • [タスク]/独自カテゴリのタスク: プログラムから登録したタスクが表示される。エンドユーザーがタスクを選択すると、タスクに設定された引数を伴ってプログラムが起動される。

*1 この2種類の項目をジャンプリストに表示するには、プログラムでJumpListオブジェクトのShowFrequentCategoryプロパティまたはShowRecentCategoryプロパティをTrueに設定する。また、[最近使ったもの]の一覧には、プログラムから追加することも可能である。


ジャンプリストの[最近使ったもの]の表示例(Windows 7) ジャンプリストの[最近使ったもの]の表示例(Windows 7)
この例はVisual Studio Express 2012 for Desktopである。[最近使ったもの]一覧に、プログラムで開いたファイルが新しい順に一覧されている。[最近使ったもの]の項目上にマウスをホバーさせると出てくる「ピン留め」ボタンをクリックすると、その項目は[いつも表示]という一覧に移動される(なお、[いつも表示]というカテゴリの名称はOSによって異なる。例えば、Windows 8.1では[ピン留め]、Windows 10では[固定済み]となる)。この[最近使ったもの]一覧は基本的にWindowsが管理しているもので、本稿では解説しない。
ちなみに、[最近使ったもの]一覧に表示される項目の数は変更できる。「Windows TIPS:Windows 7のジャンプ・リストに表示される項目数を増やす」を参照。

ジャンプリストの[よく使うもの]と[タスク]の表示例(Windows 10) ジャンプリストの[よく使うもの]と[タスク]の表示例(Windows 10)
この例はWindows Media Playerである。上側に[よく使うもの]一覧が、その下に[タスク]一覧([前回のプレイリストを再開]と[すべての音楽を再生]の二つ)が表示されている。[よく使うもの]一覧の項目も、[最近使ったもの]と同様にピン留めできる。
[よく使うもの]一覧はWindowsが管理しているもので、本稿では解説しない。本稿では、[タスク]一覧について解説する。

[タスク]一覧にタスクを設定するには?

 System.Windows.Shell名前空間のJumpListクラスとJumpTaskクラスを利用する。処理の流れは次のようになる。この処理は、プログラム中のどこで行ってもよい(複数個所で行うときは注意が必要、後述)。

  1. JumpListオブジェクトを生成する
  2. JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する(必要なだけ繰り返す)
  3. JumpListオブジェクトのApplyメソッドを呼び出して、Windowsに通知する

 System.Windows.Shell名前空間を使うには、プロジェクトの参照設定にPresentationFrameworkが必要である。Windowsフォームのプロジェクトでは、手動で追加しておく。

 JumpTaskオブジェクトには、Titleプロパティの設定が必須である。[タスク]一覧にタスクを設定する最小限のコードは次のようになる。

// JumpListオブジェクトを生成する
var jumpList = new System.Windows.Shell.JumpList();

// JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する
var jumpTask = new System.Windows.Shell.JumpTask()
{
  Title = "こんにちは",
};
jumpList.JumpItems.Add(jumpTask);

// Applyメソッドを呼び出して、Windowsに通知する
jumpList.Apply();

' JumpListオブジェクトを生成する
Dim jumpList = New System.Windows.Shell.JumpList()

' JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する
Dim jumpTask = New System.Windows.Shell.JumpTask() With
{
  .Title = "こんにちは"
}
jumpList.JumpItems.Add(jumpTask)

' Applyメソッドを呼び出して、Windowsに通知する
jumpList.Apply()

[タスク]一覧にタスクを設定する最小限のコード(上:C#、下:VB)
このコードを実行した後は、[タスク]一覧に「こんにちは」というタスクが表示される。ただし、それをクリックしても、プログラムが普通に起動するだけだ。
Windowsフォームのプロジェクトでは、参照設定に手動でPresentationFrameworkを追加しておく必要がある。
なお、このVBのコードは、Visual Basic 2008から利用できるようになった「ローカル型の推論」と「オブジェクト初期化子」、およびVisual Basic 2010から利用できるようになった「暗黙の行連結」を使用している。

 上の最小限のコードでは、[タスク]一覧に表示されたタスクをクリックしてもプログラムが普通に起動するだけである(なお、実際にプログラムを起動する場合には注意が必要だ。これについては本稿の最後で解説する)。タスクに応じた処理を行わせるには、JumpTaskオブジェクトのArgumentsプロパティを指定する。そうすると、タスクから起動されたときに、Argumentsプロパティに指定した文字列がプログラムへの引数として渡される。

 また、[タスク]一覧にはあまり長い文字列を表示できない(長すぎる部分は省略される)。そこで、[タスク]一覧に表示されるTitleプロパティの文字列は短めにしておいて、詳しい説明はツールチップにするとよい。それには、JumpTaskオブジェクトのDescriptionプロパティを指定する。

 以上の2点を追加したコードは次のようになる。これが一般的な形であろう。

// JumpListオブジェクトを生成する
var jumpList = new System.Windows.Shell.JumpList();

// JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する
var jumpTask = new System.Windows.Shell.JumpTask()
{
  Title = "こんにちは",
  Description = "昼の挨拶をします",
  Arguments = "/msg=こんにちは",
};
jumpList.JumpItems.Add(jumpTask);

// Applyメソッドを呼び出して、Windowsに通知する
jumpList.Apply();

' JumpListオブジェクトを生成する
Dim jumpList = New System.Windows.Shell.JumpList()

' JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する
Dim jumpTask = New System.Windows.Shell.JumpTask() With
{
  .Title = "こんにちは",
  .Description = "昼の挨拶をします",
  .Arguments = "/msg=こんにちは"
}
jumpList.JumpItems.Add(jumpTask)

' Applyメソッドを呼び出して、Windowsに通知する
jumpList.Apply()

[タスク]一覧にタスクを設定する一般的なコード(上:C#、下:VB)
先のコードに対して、太字の部分を追加した。
このコードを実行した後は、[タスク]一覧に「こんにちは」というタスクが表示される。マウスをホバーさせると、「昼の挨拶をします」というツールチップが表示される。クリックすると、引数として「/msg=こんにちは」という文字列が与えられた状態でプログラムが起動する。
なお、Argumentsプロパティに与える文字列に空白が入っていると、複数の引数として扱われる。例えば「/msg=こんにちは /color=青」という文字列をArgumentsプロパティにセットした場合、そこから起動されたときには「/msg=こんにちは」と「/color=青」という二つの引数が与えられることになる。
また、このVBのコードは、Visual Basic 2008から利用できるようになった「ローカル型の推論」と「オブジェクト初期化子」、およびVisual Basic 2010から利用できるようになった「暗黙の行連結」を使用している。

独自カテゴリのタスクを設定するには?

 「タスク」というカテゴリではなく、独自の名前を付けたカテゴリを表示するには、JumpTaskオブジェクトのCustomCategoryプロパティを指定すればよい。

 例えば、「CustomCategory01」という名前のカテゴリを作り、そこにタスクを表示するには、次のコードのようにする。

// JumpListオブジェクトを生成する
var jumpList = new System.Windows.Shell.JumpList();

// JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する
var jumpTask = new System.Windows.Shell.JumpTask()
{
  CustomCategory = "CustomCategory01",
  Title = "こんにちは",
  Description = "昼の挨拶をします",
  Arguments = "/msg=こんにちは",
};
jumpList.JumpItems.Add(jumpTask);

// Applyメソッドを呼び出して、Windowsに通知する
jumpList.Apply();

' JumpListオブジェクトを生成する
Dim jumpList = New System.Windows.Shell.JumpList()

' JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する
Dim jumpTask = New System.Windows.Shell.JumpTask() With
{
  .CustomCategory = "CustomCategory01",
  .Title = "こんにちは",
  .Description = "昼の挨拶をします",
  .Arguments = "/msg=こんにちは"
}
jumpList.JumpItems.Add(jumpTask)

' Applyメソッドを呼び出して、Windowsに通知する
jumpList.Apply()

「CustomCategory01」というカテゴリにタスクを設定するコード(上:C#、下:VB)
先のコードに対して、太字の部分を追加した。
このコードを実行した後は、ジャンプリストに「CustomCategory01」という名前のカテゴリが増える。そこに、先のコードと同様に「こんにちは」というタスクが表示される。
なお、このVBのコードは、Visual Basic 2008から利用できるようになった「ローカル型の推論」と「オブジェクト初期化子」、およびVisual Basic 2010から利用できるようになった「暗黙の行連結」を使用している。

タスクから他のプログラムを起動するには?

 JumpTaskオブジェクトのApplicationPathプロパティを設定することで、指定したプログラムを起動することもできる(次のコード)。

// JumpListオブジェクトを生成する
var jumpList = new System.Windows.Shell.JumpList();

// JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する
string currentDirectory = System.IO.Path.GetDirectoryName(
  System.Reflection.Assembly.GetExecutingAssembly().Location);
var jumpTask = new System.Windows.Shell.JumpTask()
{
  Title = "ReadMeを読む",
  Description = "ReadMeを開きます。",
  ApplicationPath = @"%SystemRoot%\System32\notepad.exe",
  IconResourcePath = @"%SystemRoot%\System32\notepad.exe",
  WorkingDirectory = currentDirectory,
  Arguments = currentDirectory + @"\ReadMe.txt",
};
jumpList.JumpItems.Add(jumpTask);

// Applyメソッドを呼び出して、Windowsに通知する
jumpList.Apply();

' JumpListオブジェクトを生成する
Dim jumpList = New System.Windows.Shell.JumpList()

' JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する
Dim currentDirectory As String = System.IO.Path.GetDirectoryName(
  System.Reflection.Assembly.GetExecutingAssembly().Location)
Dim jumpTask = New System.Windows.Shell.JumpTask() With
{
  .Title = "ReadMeを読む",
  .Description = "ReadMeを開きます。",
  .ApplicationPath = "%SystemRoot%\System32\notepad.exe",
  .IconResourcePath = "%SystemRoot%\System32\notepad.exe",
  .WorkingDirectory = currentDirectory,
  .Arguments = currentDirectory & "\ReadMe.txt"
}
jumpList.JumpItems.Add(jumpTask)

' Applyメソッドを呼び出して、Windowsに通知する
jumpList.Apply()

「メモ帳」を起動するタスクを設定するコード(上:C#、下:VB)
このコードを実行した後は、ジャンプリストに「ReadMeを読む」というタスクが表示される。それをクリックすると、「メモ帳」が起動し、プログラムと同じフォルダーにある「Readme.txt」が表示される。
なお、このVBのコードは、Visual Basic 2008から利用できるようになった「ローカル型の推論」と「オブジェクト初期化子」、およびVisual Basic 2010から利用できるようになった「暗黙の行連結」を使用している。

タスクをXAMLコードで設定するには?(WPF)

 設定する内容が固定的ならば、WPFではXAMLコードでも設定できる(次のコード)。

<Application ……省略…… >

  <JumpList.JumpList>
    <JumpList>
      <JumpTask Title="おはようございます"
                Description="朝の挨拶をします" 
                Arguments="/msg=おはようございます" />
    </JumpList>
  </JumpList.JumpList>

  ……省略……

タスクをXAMLコードで設定する例(XAML)
「App.xaml」ファイル(C#)/「Application.xaml」ファイル(VB)の「Application」開始タグのすぐ後ろに記述した。なお、以下の「タスクを追加するには?」で説明しているように、XAMLとコードの両方でジャンプリストを設定する場合には注意が必要になる(ここまでのコードを順番に試している場合、上のXAMLコードを記述しただけでは、プログラムの実行時にこの項目がジャンプリストに表示されない)。

タスクを追加するには?

 タスクを設定する処理を何カ所かに分けて行う場合(例えばWPFで、固定的なタスクはXAMLコードに、そうでないタスクはコードビハインドに書くといったとき)、2カ所目以降ではJumpListオブジェクトを新しく生成してはいけない。

 JumpListオブジェクトを新しく生成すると、それまでに設定したタスクが消えてしまうのだ。Windowsフォームでは、最初に生成したJumpListオブジェクトを保持しておいて、使い回すしかない(その都度、Applyメソッドを呼び出してよい)。

 WPFでは、2回目以降はJumpListクラスのGetJumpListメソッドを使って現在のタスク設定を取得できる(次のコード)。

// 既存のJumpListオブジェクトを取得する
var jumpList = System.Windows.Shell.JumpList.GetJumpList(App.Current);

// 以降は同じ

// JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する
var jumpTask = new System.Windows.Shell.JumpTask()
{
  Title = "こんにちは",
  Description = "昼の挨拶をします",
  Arguments = "/msg=こんにちは",
};
jumpList.JumpItems.Add(jumpTask);

// Applyメソッドを呼び出して、Windowsに通知する
jumpList.Apply();

' 既存のJumpListオブジェクトを取得する
Dim jumpList = System.Windows.Shell.JumpList.GetJumpList(Application.Current)

' 以降は同じ

' JumpTaskオブジェクトを生成し、JumpListオブジェクトに格納する
Dim jumpTask = New System.Windows.Shell.JumpTask() With
{
  .Title = "こんにちは",
  .Description = "昼の挨拶をします",
  .Arguments = "/msg=こんにちは"
}
jumpList.JumpItems.Add(jumpTask)

' Applyメソッドを呼び出して、Windowsに通知する
jumpList.Apply()

WPFでタスクを追加するコードの例(上:C#、下:VB)
JumpListオブジェクトを取得するコード(太字)以外は同じである。
なお、このVBのコードは、Visual Basic 2008から利用できるようになった「ローカル型の推論」と「オブジェクト初期化子」、およびVisual Basic 2010から利用できるようになった「暗黙の行連結」を使用している。

[タスク]一覧からの起動に対応するには?

 タスクを設定したときのArgumentsプロパティが、起動時の引数として渡される。従って、起動時の引数によって動作を変更すればよい。

 例えば、「/msg=」で始まる引数を取り出すには、次のコードのようにする。

string msgArgment 
  = Environment
      .GetCommandLineArgs()
      .Where(arg => arg.ToUpperInvariant().StartsWith("/MSG="))
      .FirstOrDefault();

Dim msgArgment As String _
  = Environment _
      .GetCommandLineArgs() _
      .Where(Function(arg) arg.ToUpperInvariant().StartsWith("/MSG=")) _
      .FirstOrDefault()

「/msg=」で始まる引数を取り出すコードの例(上:C#、下:VB)
まず、Environmentクラス(System名前空間)のGetCommandLineArgsメソッドで、引数を文字列の配列として取り出している。
続けてLINQを使って、引数の中から「/msg」で始まっているものを選び出し(Whereメソッド)、その最初のもの(なかったときはNull)を「msgArgment」変数に格納している(FirstOrDefaultメソッド)。
なお、Whereメソッドの引数はラムダ式*2である。

*2 ラムダ式について詳しくは、次のMSDNのドキュメントを参照していただきたい。


実行結果

 以上で紹介したコードを組み合わせたサンプルコードを作成した(「Windows desktop code samples:.NET Tips #1115」からダウンロードできる)。

 ジャンプリストのテストをするときは、そのままVisual Studioから実行してはいけない。ビルドされた実行ファイルを直接実行するか、Visual Studioホスティングプロセスを無効にした上でVisual Studioから実行する*3

*3 Visual Studioホスティングプロセスについては、「.NET TIPS:VSホスト・プロセス(*.vshost.exe)とは何か?」を参照していただきたい。


 実行結果は次の画像のようになる。ジャンプリストと、ジャンプリストから起動したウィンドウが見えている。

ジャンプリストの実行例(Windows 7)
ジャンプリストの実行例(Windows 10) ジャンプリストの実行例(上:Windows 7/下:Windows 10)
上はWindowsフォーム、下はWPFである。
画像には写っていないが、ジャンプリストのタスク[おはようございます]のところにマウスカーソルがある。そこにツールチップも表示されているのがお分かりいただけるだろうか。

まとめ

 ジャンプリストをWindowsフォーム/WPFから利用するのは意外と簡単である。ぜひ活用していただきたい。

利用可能バージョン:.NET Framework 4.0以降
カテゴリ:Windowsフォーム 処理対象:ウィンドウ
カテゴリ:WPF/XAML 処理対象:タスクバー
使用ライブラリ:JumpListクラス(System.Windows.Shell名前空間)
使用ライブラリ:JumpTaskクラス(System.Windows.Shell名前空間)
関連TIPS:WPF/Windowsフォーム:タスクバーのアイコンに進捗表示を出すには?[C#、VB]
関連TIPS:タスクバー上のボタンやウィンドウのタイトルバーを点滅させるには?[C#、VB]
関連TIPS:タスクバーにアイコンを表示させないようにするには?


「.NET TIPS」のインデックス

.NET TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。