【VB.NET】【WPF】通知領域(タスクトレイ)を使う~ WPF NotifyIcon

MEMO

この記事は「Code Project の WPF NotifyIcon の記事」の多くの部分を参考にしています(全ては網羅してません)。詳細については「Code Project の WPF NotifyIcon の記事」を参照してください。

アプリを通知領域(旧名:タスクトレイ)に入れる機能が WPF の標準機能には無いらしい(なぬっ!?)。

で、調べてみると、Forms の NotifyIcon クラスを引っ張ってきてアレコレやる方法がヒットするけれど、Forms の力を借りるのがなんとなく気持ち悪い。

もう少しスッキリした気分で出来る方法は無いものかと探して見つけたのが WPF NotifyIcon(Hardcodet.NotifyIcon.Wpf、by Philipp Sumi)です。WPF NotifyIcon なら、WPF の特性を生かしたメッセージを表示することができます。

インストール

[ツール]>[NuGet パッケージ マネージャー]>[ソリューションの NuGet パッケージの管理]を選択。

[NuGet - ソリューション]タブで[参照]をクリックして検索ボックスに「Hardcodet.NotifyIcon.Wpf」(または「NotifyIcon」など)と入力。「Hardcodet.NotifyIcon.Wpf」が見つかったら選択して、右側のペインでインストール先のプロジェクトにチェックを入れて[インストール]ボタンをクリック。

確認ダイアログが出たら[OK]をクリック。

[出力]ウィンドウにインストール状況が表示されます。

Hello, World

プログラムコード版

Wpf NotifyIcon をインストールしたら、"Hello, World" をやってみましょう。

まず独自のアイコンファイル(.ico)を用意して、Visual Studio の[プロジェクト]>[プロジェクト名 のプロパティ]を選択。

プロパティタブで[リソース]を選択して、リソースの種類として[アイコン]を選択。

アイコンファイル(ここでは conditioner.ico とします)をドラッグ&ドロップして追加。

そして次のコードを実行すると・・・

通知エリアにアイコンが表示されました。アイコンの上にマウスカーソルを重ねるとテキストが表示されます。

XAML 版

前述のことを xaml でやるには次のようにします。

まず xaml のヘッダーに次のネームスペース宣言を追加します。

xmlns:tb="http://www.hardcodet.net/taskbar

そして <tb:TaskbarIcon IconSource="/conditioner.ico" ToolTipText="hello world" /> を追加するだけ(conditioner.ico をプロジェクトファイルと同じ場所に置いてあるという前提)。

xaml 全体は下記のような感じ。

これだけで、アプリを実行すると通知領域にアイコンが表示されます。アイコンの上にマウスカーソルを重ねるとテキストが表示されます。

アイコンを消す

コードでアイコンを消すときはこう(前述の通りインスタンス tbi を作成済みと想定)。

xaml でアイコンを消すときはこう。

 

アイコンはアプリケーションが終了すると自動的に消えるのであまり神経使う必要はないが、実行時に完全に取り除きたいときは TaskbarIcon クラスの Dispose メソッドを使用する。

ツールチップ

TaskbarIcon クラスにはツールチップに関する2つのプロパティがある。

  • TrayToolTip プロパティには任意の UIElement を指定できる。
  • ToolTipText プロパティには String を指定する。これには2通りの使い道がある。
    • TrayToolTip を使用しないとき
    • 古い OS(XP/2003)で TrayToolTip が使えないとき

アプリが古い OS で実行された場合に備えて ToolTipText プロパティは常に設定しておくのが望ましい。

ツールチップ1:インライン宣言

TaskbarIcon 宣言の中に直接、カスタムのツールチップを宣言できる。下記は TextBlock と半透明のボーダーで構成されるツールチップの例。

アプリを実行してアイコンにマウスカーソルを重ねるとこんな感じ。

ツールチップ2:ユーザーコントロールの使用

「SimpleUserControl」という名前のユーザーコントロールを作成してそれを表示してみる。

Visual Studio 上部メニューの[プロジェクト]>[ユーザー コントロールの追加]を選択。

ユーザーコントロールの名前を SimpleUserControl.xaml にして追加。

ユーザーコントロールの xaml を(たとえば)下記のようにする。

アプリのメインウィンドウの xaml のタグを下記のように変更。

そうすると、こんな感じのツールチップになる。

MEMO

エイリアスの local のところでエラーが出る場合は後述の「はまりやすい点」を参照してみてください。

ツールチップ3:リソースにリンク

ツールチップコントロールをリソースに宣言している場合はこんな感じらしい(当サイトの管理人は未検証)。

ポップアップ

ツールチップと違って、ポップアップはユーザーが NotifyIcon をクリックしたときだけ表示され、ユーザーがトレイエリアからマウスを離しても開いたままになる。

ただし、ユーザーがどこか違う場所をクリックすると、閉じる。

というわけで、ポップアップにはインタラクティブなコンテンツを含めることができる。

詳細は「Code Project の WPF NotifyIcon の記事」を参照してください(当サイトの管理人は未検証)。

コンテキストメニュー

NotifyIcon をクリックしたときに表示されるコンテキストメニュー。これは FrameworkElement のベースクラスから直接派生した WPF 標準の ContextMenu である。

xaml でコンテキストメニューを定義した例。

メニューの項目がクリックされたときの動作をコードで記述した例。

 

コンテキストメニューはデフォルトでは右クリックで開くが、その挙動は MenuActivation プロパティで変えることができる(左クリックやダブルクリックで開くようにもできる)。

ちなみに PopupActivation と MenuActivation で干渉しあう値を設定した場合、MenuActivation が優先される。

バルーンチップ(通知バナー)

標準のバルーンチップ(通知バナー)

コード

表示例(組み込みのアイコンを使用)

表示例(カスタムのアイコンを使用)

注意

カスタムのアイコンを使うメソッドの第4引数(True)は本来は省略できるオプションのはずですが、省略したり False にしたりするとバルーンが表示されませんでした。

バグかな?

カスタムのバルーンチップ(通知バナー)

カスタムのバルーンを表示するには TaskbarIcon クラスの ShowCustomBalloon メソッドを使う。ShowCustomBalloon は任意の UIElement のインスタンスを表示できるだけでなく、第2引数でバルーンの表示方法(アニメーション)を指定したり、第3引数でバルーンのタイムアウトの時間を指定することもできる。

下図は、私(当サイトの管理人)が UserControl で作ったカスタムのバルーンを表示したところ。

MEMO

アニメーションの選択肢は Fade、Scroll、Slide の3種類ありますが、表示速度が速いせいか、あまり違いを感じませんでした。

コマンド(ICommand)

TaskbarIcon では現在のところ次の2つのプロパティにコマンドを割り当てることができる(割り当てる必要がある)。

  • LeftClickCommand
  • DoubleClickCommand

コマンド定義

まずコマンドを定義します。

割り当て方法1:XAML でバインド

xaml でバインドするときはこんな感じ(下記のハイライト個所については後述の「はまりやすい点」で解説)。

アプリを実行して、通知領域のアイコンを左クリックまたはダブルクリックすると下図のメッセージボックスが表示される。

はまりやすい点

上記のコードを試してみて「あれ? 動かないよ。エラーになるよ!」ということがあるかもしれないので、ポイントを解説します。

最初のポイントは、上の xaml の6行目に xmlns:local="clr-namespace:WpfApp1" という記述がある点です。プロジェクトのルート名前空間(WpfApp1。デフォルトはプロジェクト名と同じ)を local というエイリアスに割り当てています。

2番目のポイントですが、今回、コマンドパラメータを記述したのは、下図の場所です。メインウィンドウのクラスの外に定義しました。

で、xaml に戻って3番目のポイントです。下図のところ(前述の xaml の13行目)で正しいコマンドパラメータの名前を記述しても最初はエラーが出るかもしれません。

xaml のエラーって、現在の状態をリアルタイムに反映してないんですよね。。。記述が正しければ、リビルドしたり「デバッグの開始(F5)」を実行すると、エラーが消えます。

割り当て方法2:コードビハインド

コードでコマンドを割り当てる場合は下記のようにします。

Window.ShowInTaskbar

基本的すぎて書くのを忘れるとこでしたけど、念のため書いておきます。

WPF のウィンドウには .ShowInTaskbar プロパティ(タスクバーにアイコンを表示するかどうか)があるので、通知領域(タスクトレイ)を使うときは、きっとこのプロパティも活用することになりますね。

コメントの投稿

avatar
  購読する  
通知を受け取る対象