C# WPF で タスクトレイ 常駐アプリ の 開発

4 件のコメント

C# の WPF を利用して、タスクトレイに常駐するアプリケーションのひな形を開発してみます。 チュートリアルに近い形で順を追って作成できるようにしてみました。

概要

ここでは、タスクトレイ常駐アプリとして最低限と思われる以下の機能を実装します。

実装機能

  • タスクトレイに「常駐アプリのアイコン」を表示する
  • 「常駐アプリアイコン」を右クリックでコンテキストメニューを表示する
  • コンテキストメニューには以下の項目が表示される
    • 表示
    • 終了
  • コンテキストメニュー「表示」をクリックでウィンドウが立ち上がる
  • コンテキストメニュー「終了」で常駐アプリを終了する

実行イメージ

プロジェクト の 作成

プロジェクト自体は特に気にすることはなく、ウィザードに従って "WPFアプリケーション" のプロジェクトを作成します。

  1. [ファイル]-[新規作成]-[プロジェクト] を選択

  2. 「新しいプロジェクト」ウィンドウにて、「WPF アプリケーション」を選択し、 名前、場所、ソリューション名を設定して、「OK」ボタンを押下

常駐アプリ の 実装

  1. プロジェクトを右クリック、 [プロパティ] を選択

  2. [アプリケーション] タブ にある [アセンブリ情報] ボタンを選択

  3. 「アセンブリ情報」にて、 タイトル を変更

    ※ ここで設定する タイトル は 「通知領域アイコン」にて表示される アプリケーション名 になります

NotifyIcon クラス は WPF で直接使えないので、ラッパーを作成して利用します。 ここでは、そのひな形を作るだけで、中身の実装はあとで行います。

  1. プロジェクトを右クリック、[追加]-[新しい項目] を選択

  2. 「新しい項目の追加」ウィンドウにて、「コンポーネント クラス」を選択し、名前を入力して、[追加]ボタンを押下
    ここでは名前を NotifyIconWrapper としました。

Window は表示せず、 NotifyIcon のみを起動するように処理を変更します。

  1. App.xaml から /Application/@StartupUri を削除

    修正前

    修正後 App.xaml

    <Application x:Class="ResidentApplication.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Application.Resources>
             
        </Application.Resources>
    </Application>
    
  2. App.xaml.cs に プロパティ、起動処理、終了処理を追加

    修正前

    修正後 App.xaml.cs

    namespace ResidentApplication
    {
        using System.Windows;
    
        /// <summary>
        /// App.xaml の相互作用ロジック
        /// </summary>
        public partial class App : Application
        {
            /// <summary>
            /// タスクトレイに表示するアイコン
            /// </summary>
            private NotifyIconWrapper notifyIcon;
    
            /// <summary>
            /// System.Windows.Application.Startup イベント を発生させます。
            /// </summary>
            /// <param name="e">イベントデータ を格納している StartupEventArgs</param>
            protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);
                this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
                this.notifyIcon = new NotifyIconWrapper();
            }
    
            /// <summary>
            /// System.Windows.Application.Exit イベント を発生させます。
            /// </summary>
            /// <param name="e">イベントデータ を格納している ExitEventArgs</param>
            protected override void OnExit(ExitEventArgs e)
            {
                base.OnExit(e);
                this.notifyIcon.Dispose();
            }
        }
    }
    

  1. 「ソリューション エクスプローラー」にて、「NotifyIconWrapper.cs」をダブルクリック

  2. 「ツールボックス」にある「NotifyIcon」と「ContextMenuStrip」を、「NotifyIconWrapper.cs [デザイン]」へ ドラッグ&ドロップ
    NotifyIcon は [コモンコントロール]-[NotifyIcon] にあります。
    ContextMenuStrip は [メニューとツールバー]-[ContextMenuStrip] にあります。

  3. 「ソリューション エクスプローラー」にて、「参照設定」を右クリック、[参照の追加] を選択

  4. 「参照マネージャー」にて、 System.Drawing を追加

    System.Drawing は アイコン を表示させるために必要な参照になります。

  5. 「NotifyIconWrapper.cs [デザイン]」に追加した notifyIcon1 を選択し、「プロパティ」ウィンドウにて、以下の項目を設定

    「通知アイコン」プロパティ

    ContextMenuStrip
    タスクトレイに表示するアイコンを右クリックした時表示するコンテキストメニュー
    前項で追加した contextMenuStrip1 を設定
    Icon
    タスクトレイに表示したいアイコン
    Text
    タスクトレイ上のアイコンにマウスオーバーした時表示されるツールチップメッセージ

    ※ ここで設定する Text は「通知領域アイコン」にて表示される コメント、タスクトレイ上で アイコン に マウスオーバー したときの ツールチップ になります

  6. 「NotifyIconWrapper.cs [デザイン]」に追加した contextMenuStrip1 を右クリック、[項目の編集] を選択

  7. 「項目コレクション エディター」にて、以下のような MenuItem を2項目追加

    「"表示" メニュー項目」プロパティ

    (Name)
    toolStripMenuItem_Open
    Text
    表示

    「"終了" メニュー項目」プロパティ

    (Name)
    toolStripMenuItem_Exit
    Text
    終了

  8. NotifyIconWrapper クラス に コンテキストメニュー 選択時 の 処理を実装

    修正前

    修正後 NotifyIconWrapper.cs

    namespace ResidentApplication
    {
        using System;
        using System.ComponentModel;
        using System.Windows;
    
        /// <summary>
        /// タスクトレイ通知アイコン
        /// </summary>
        public partial class NotifyIconWrapper : Component
        {
            /// <summary>
            /// NotifyIconWrapper クラス を生成、初期化します。
            /// </summary>
            public NotifyIconWrapper()
            {
                // コンポーネントの初期化
                this.InitializeComponent();
    
                // コンテキストメニューのイベントを設定
                this.toolStripMenuItem_Open.Click += this.toolStripMenuItem_Open_Click;
                this.toolStripMenuItem_Exit.Click += this.toolStripMenuItem_Exit_Click;
            }
    
            /// <summary>
            /// コンテナ を指定して NotifyIconWrapper クラス を生成、初期化します。
            /// </summary>
            /// <param name="container">コンテナ</param>
            public NotifyIconWrapper(IContainer container)
            {
                container.Add(this);
    
                this.InitializeComponent();
            }
    
            /// <summary>
            /// コンテキストメニュー "表示" を選択したとき呼ばれます。
            /// </summary>
            /// <param name="sender">呼び出し元オブジェクト</param>
            /// <param name="e">イベントデータ</param>
            private void toolStripMenuItem_Open_Click(object sender, EventArgs e)
            {
                // MainWindow を生成、表示
                var wnd = new MainWindow();
                wnd.Show();
            }
    
            /// <summary>
            /// コンテキストメニュー "終了" を選択したとき呼ばれます。
            /// </summary>
            /// <param name="sender">呼び出し元オブジェクト</param>
            /// <param name="e">イベントデータ</param>
            private void toolStripMenuItem_Exit_Click(object sender, EventArgs e)
            {
                // 現在のアプリケーションを終了
                Application.Current.Shutdown();
            }
        }
    }
    

実装は以上になります。 この後は、実際にアプリを実行して正常に動作するか検証を行います。

常駐アプリ の 実行/テスト

特に変わったことはせず、普通にデバッグ実行するとテストができます。

  1. Visual Studio でデバッグ実行

  2. タスクトレイに常駐して起動していることを確認

参考記事

最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!

 

  1. このままですと同じフォームを複数個起動可能となってしまいます。

    返信削除
    返信
    1. ご指摘ありがとうございます。
      この記事ではシングルトンにするまでは記述していませんので、
      必要に応じて開発されているアプリケーションにシングルトンパターンを適用いただければと思います。
      (static プロパティにインスタンスを保存して static メソッドで インスタンス取得するようなパターン)

      ※参考
       TECHSCORE - 5. Singleton パターン
       https://www.techscore.com/tech/DesignPattern/Singleton.html/

      よろしくお願いいたします。

      削除
  2. >タスクトレイに常駐して起動していることを確認

    私の環境下だと右下に時刻がでていますが、galifeの画像を見ると時刻がでてきません。
    この記事は間違っていませんか?

    返信削除
    返信
    1. ご指摘ありがとうございます。
      わかりにくい画像になっていたようで申し訳ございません。
      右下の時計はいつのキャプチャかわからないよう「ぼかし」をいれたので「消えたよう」に見えているだけです。
      よく見ると文字列があるような形跡が確認できるかと思います。
      よろしくお願いいたします。

      削除