やりたいこと
.NET6とC#で、タスクトレイに常駐しているアプリを作りたい。
タスクトレイからコンテキストメニューを開いて、また別のアプリを起動したりしたい。
使うもの
やりかた
実験アプリ仕様
今回は実験として、そのバックグラウンドアプリの中で下記のようなことをするものを作ってみる。
- 起動すると、タスクトレイの中にアイコンを表示する。
- アイコンにマウスオーバーすると、文言を表示する。
- アイコンを右クリックすると、コンテキストメニューを表示する。
- コンテキストメニューの「電卓を起動します」を押すと、電卓を起動する。
- コンテキストメニューの「アプリを終了します」を押すと、アプリ終了し、タスクトレイの常駐も終了する。
- それ以外のときは、なにもしない。(exeはずっと動き続け、その間タスクトレイにアイコン表示する)
やり方
まず、以前書いた「バックグラウンドプロセスを作ってみる」の記事のやり方で、バックグラウンドアプリを作成する。
WinFormsのクラス System.Windows.Forms.NotifyIcon
と System.Windows.Forms.ContextMenuStrip
を使うので、
プロジェクトファイル(.csproj)に、下記を追記する。(こちらの記事も参照)
<UseWindowsForms>true</UseWindowsForms>
App
クラスの中のOnStartup(StartupEventArgs e)
で、下記のようにする。
using System.Diagnostics; using System.Windows; namespace TaskTrayJikken { public partial class App : Application { private System.Windows.Forms.ContextMenuStrip menu = new(); System.Windows.Forms.NotifyIcon notifyIcon = new(); protected override void OnStartup(StartupEventArgs e) { // 右クリックに出すのコンテキストメニューを作成 menu.Items.Add("アプリを終了します", null, (obj, e) => { Shutdown(); }); menu.Items.Add("電卓を起動します", null, (obj, e) => { Process.Start(@"C:\Windows\System32\calc.exe"); }); // タスクトレイ上のアイコンを作成 notifyIcon.Visible = true; notifyIcon.Icon = new System.Drawing.Icon(@"MyIcon.ico"); // 今回は、icoファイルを「常にコピー」にしておいて、exeと同じ階層にicoができるようにして使用 notifyIcon.Text = "マウスポインタを当てたときに表示する文言"; notifyIcon.ContextMenuStrip = menu; // アイコンを押したときの処理 notifyIcon.Click += (obj, e) => { Debug.WriteLine("クリックされました"); }; // プロセス通常起動 base.OnStartup(e); } protected override void OnExit(ExitEventArgs e) { menu.Dispose(); notifyIcon.Dispose(); base.OnExit(e); } } }
コード中にも書いているが、今回はアイコンの.icoファイルを、
ファイルのプロパティの「出力ディレクトリにコピー」を「常にコピー」にしておいて、exeと同じ階層にicoがある(コピーされてる)前提で上記コードで呼ぶことにした。
2022年07月 追記
OnExit
のオーバーライドを追加し、その中でmenuとnotifyIconのDisposeを追加。
これをしていないと、このアプリが終了してもタスクトレイの中のアイコンが消えない。
正確に言うと、
- アイコンが消えずに残る。
- 複数回、アプリを起動→終了、とすると、その回数だけアイコンがタスクトレイの中に増えていく
- なぜかそのアイコンにマウスオーバーすると消えていく
という現象になった。Disposeしてあげると、アプリ終了すると、アイコンも一緒に消えてくれるようになった。