業務アプリに限らず、いろいろなプログラム作成を経験していると、
タスクトレイ(通常画面右下の時計が表示される場所)へアプリケーションを
常駐させて(タスクバーに出さずに他の作業の邪魔にならないように)動かしたい
事は必ず1度や2度はあるのではないかと思う。
C#(.Net Framework)では、タスクトレイへアプリケーションを格納するための
クラスが標準で備わっている。それが、タイトルにもある、NotifyIconである。
使い方はいたって簡単であり、タスクトレイへの常駐だけでなく、アイコンの設定、
バルーン表示機能(吹き出しのようなメッセージが一定時間表示される機能)や、
ヒントメッセージ、コンテキストメニューの設定がとても簡単にできるが、
細かい動きを気にすると、少しテクニックが必要になるので書いておきます。
※細かい動きと言っても、常駐アプリケーションを使用する場合には大抵必要になる
だろう動きだと思うので、調べると結構同様の対応策が検索できる。
まずは、NotifyIconの使い方も含め、
1.NotifyIconをフォームに張り付ける。
2.NotifyIconのVisibleプロパティをtrueにし、Iconプロパティに表示したいアイコンを
指定すると、これだけでアプリケーション実行時にタスクトレイにアイコンが表示
される。また、タスクバーにアプリケーションのタスクを表示させないためには、
ShowInTaskbarプロパティをflaseに設定します。
3.Titleプロパティの内容が、ヒントメッセージになり、BalloonTip?プロパティを設定
し、ShowBalloonTipメソッドでバルーンを一定時間表示できます。
4.ここまでは、簡単な設定だけでうまくいくのですが、アプリケーションのウィンドウは
最小化するとタスクバーには表示されないのですが、デスクトップ領域に表示されて
しまいます。また、閉じるボタンを押した際にアプリケーションが終了するのではなく、
画面は消えるが、タスクトレイには常駐されたままにしたいというのが一般的な機能
でしょう。
5.結論から言うと、WndProc というメッセージの処理をつかさどるメソッドをオーバ
ライドすると自由にアプリケーションの動作を制御することが可能なので、
この方法がベストでしょう。ただ今回は、極力簡単で分かりやすい方法で
できないかを探しており、少し動作的に微妙な点はあるが、メッセージを使用せず、
WindowStateプロパティを制御するだけでもうまく動かすことはできた。
6.WndProcの制御も覚えれば簡単なので、ハードルは高くないと思われるが、今回は
せっかくなので両方の方法のサンプルを書いておきます。
コードサンプル
前提条件
・フォームにNotifyIcoonコントロールを張り付ける
・NotifiIconのVisibleをtrue、ShowInTaskbarプロパティをfalse、Iconプロパティを設定
a)WndProcを使用する方法
public partial class Form1 : Form
{
private int WM_SYSCOMMAND = 0x112;
private IntPtr SC_MINIMIZE = (IntPtr)0xF020;
public Form1()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
//最小化されたときにフォームを非表示にする
if ((m.Msg == WM_SYSCOMMAND) && (m.WParam == SC_MINIMIZE))
{
this.Hide();
}
//上記以外はデフォルトの処理をおこなう
else
{
base.WndProc(ref m);
}
}
private void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
//タスクトレイのアイコンダブルクリックでフォームを表示、アクティブ化
this.Show();
this.Activate();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//フォームを閉じる時、タスクトレイに表示されている場合は閉じずに非表示
if (notifyIcon1.Visible)
{
e.Cancel = true;
this.Hide();
}
}
//NotifyIconのコンテキストメニューに追加した「閉じる」メニュークリックイベント
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
//NotifyIconのコンテキストメニューで閉じるメニューを実行した場合
//NotifyIconを非表示にしてアプリケーションを終了する
notifyIcon1.Visible = false;
Application.Exit();
}
}
b)WindowStateプロパティを使用する方法
→この方法の場合は、あくまで最小化の処理が発生していることになるので、
最小化のアニメーションが表示されてしまう、再表示する場合に、フォームの状態を
再設定するため、画面がちらつく場合があるなど微妙に動作が気になる部分も残る。
public partial class Form1 : Form
{
//ウィンドウの状態を保存するためのフィールド
private FormWindowState windowState;
public Form1()
{
InitializeComponent();
windowState = WindowState;
}
private void MainForm_ClientSizeChanged(object sender, EventArgs e)
{
//ウィンドウが最小化された場合はフォームを非表示
if (this.WindowState == FormWindowState.Minimized)
{
this.Hide();
}
//最小化以外の場合はウィンドウの状態を保存しておく
else
{
windowState = WindowState;
}
}
private void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
//ウィンドウを表示、保存しておいた状態に戻し、アクティブ化する
this.Show();
this.WindowState = windowState;
this.Activate();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//フォームを閉じる時、タスクトレイに表示されている場合は閉じずに非表示
if (notifyIcon1.Visible)
{
e.Cancel = true;
this.Hide();
}
}
//NotifyIconのコンテキストメニューに追加した「閉じる」メニュークリックイベント
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
//NotifyIconのコンテキストメニューで閉じるメニューを実行した場合
//NotifyIconを非表示にしてアプリケーションを終了する
notifyIcon1.Visible = false;
Application.Exit();
}
}