Help us understand the problem. What is going on with this article?

タスクトレイ(通知領域)に寄せてフォームを表示する

More than 1 year has passed since last update.

はじめに

Windows用の常駐型アプリを標ぼうするため、タスクトレイ(通知領域)にアイコンを表示させ

  1. 「起動時には自フォームを非表示」
  2. 「タスクトレイ(通知領域)アイコンをダブルクリックしたら、タスクトレイの近くに自フォームを表示」

を実装してみます。

うまくいかない例

「起動時には非表示」のため、フォームの Visible プロパティ初期値を False に設定する。

これは残念ながら最初からフォームが表示されてしまいます。

「起動時には非表示」のため、フォームの WindowState プロパティ初期値を Minimized にしてかつ ShowInTaskbar プロパティを False に設定し、タスクトレイアイコンをダブルクリックしたら WindowState プロパティを Normal にすればよい。

起動時の非表示化は成功しますが、ダブルクリックイベントで表示させるときに、変な場所からとび出てきて表示されて、格好悪いです。

コードと説明

課題を実現してみたコードです。Visual Studio 2017 (15.8.1)から、SampleAppという名前のプロジェクトを「Windowsフォームアプリケーション(.NET Framework : C#)」(.NET Framework 4.5.2) で作成しました。初期作成される Form1 に、NotifyIcon(notifyIcon1:タスクトレイアイコン)と、Button(buttonExit:アプリを終了させるボタン)を、それぞれ配置しています。

Form1.cs
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace SampleApp
{
    public partial class Form1 : Form
    {
        private bool _initialized = false;

        public Form1()
        {
            InitializeComponent();

            //  デザイナで初期設定してもOK
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.StartPosition = FormStartPosition.Manual;
        }

        protected override void SetVisibleCore(bool value)
        {
            //  コントロールの表示状態を強制:初回は非表示にする
            base.SetVisibleCore(_initialized && value);
            _initialized = true;
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            //  フォームを閉じる操作をされた
            //base.OnClosing(e);
            this.Visible = false;
            e.Cancel = true;
        }

        private void buttonExit_Click(object sender, EventArgs e)
        {
            //  終了ボタン押下
            Application.Exit();
        }

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            //  タスクトレイ(通知領域)のアイコンダブルクリック
            SetFormLocation();
            this.Visible = true;
        }

        //  ここが今回のキモ!!
        private void SetFormLocation()
        {
            var wa = Screen.PrimaryScreen.WorkingArea;

            if (0 < wa.Left)
            {
                //  タスクバーは左
                this.Location = new System.Drawing.Point(wa.Left, wa.Bottom - this.Height);
            }
            else if (0 < wa.Top)
            {
                //  タスクバーは上
                this.Location = new System.Drawing.Point(wa.Right - this.Width, wa.Top);
            }
            else
            {
                //  タスクバーは右か下
                this.Location = new System.Drawing.Point(wa.Right - this.Width, wa.Bottom - this.Height);
            }
        }
    }
}

初期表示を非表示にする

フォームの SetVisibleCore 仮想メソッドをオーバーライドして、コントロールの表示状態を強制させることができます。Visible (Visibility) の Setter メソッドのさらに中核ということで SetVisibleCore というメソッド名なのかしら...
このプログラムでは、初回の呼び出し時のみ Visible = False を強制して、初期表示を非表示にさせています。

タスクトレイアイコンダブルクリック時に、通知領域に寄せて(通知領域に近いデスクトップ内のエッジの位置に)フォームを表示する

通知領域(タスクトレイ)の座標やタスクバーの位置を得る方法があればズバリかもしれませんが、当方残念ながら存じません(ご存知の方、ぜひ教えてください!)
そこで代替手段、プライマリスクリーンの作業領域座標からタスクバーの位置、ひいては通知領域の位置を推測します。Form.Screen プロパティのPrimaryScreen.WorkingArea プロパティには、プライマリスクリーンの作業領域座標(タスクバーなどを除いたデスクトップ座標)が入っています。
作業領域座標の上端が0ではない場合は、上側に作業領域ではない領域(タスクバーなど)があると考えます(左端の場合も同様)
タスクバーを自動で隠す設定にされていてタスクバーが隠れている状態だと、このスクリーン座標と作業領域座標とは一致してしまって検出できなくなるのですが、「通知領域アイコンがダブルクリック」されるときにはタスクバーは必ず表示されているので、そこのところは気にしなくて済みそうです。

おわりに

もっとエレガントな方法がありましたら、ぜひ教えてください!

otagaisama-1
自社の開発・運用で、皆様からの情報にとてもお世話になっています。ほぼ1人情SYSの身で、他のネット情報には少ないレアめなシステムを自社で使っている点でも、今めいたシステム情報入手面でも、Qiita のみなさまはとても貴重です。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした