- PR -

【C#】タスクトレイ表示によるFormの表示切替制御

1
投稿者投稿内容
Makoto
大ベテラン
会議室デビュー日: 2004/03/31
投稿数: 133
投稿日時: 2005-05-10 09:50
いつもお世話になっております。

C#でのタスクトレイ表示法に関して調べているのですが、行き詰ってしまいました。
ご存知の方、いらっしゃいましたらアドバイスお願い致します。

やりたいことは、下記です。
1.APを最小化時にタスクトレイに表示したい
  (APは、タスクバーには表示しない、画面を非表示にする。)

2.タスクトレイアイコンのダブルクリックで元の画面サイズに戻したい。

【手順1】
現状、タスクバーにAPを表示しないように設定する為に、Formで
this.ShowInTaskbar = false;
のようにしています。

【手順2】
しかし、最小化ボタンクリック時に、画面の右下(タスクバーの上。
詳細には『スタートボタンの上』)
にタイトルバーサイズの画面が表示されてしまいます。

【手順3】
この状態でタスクトレイアイコンのダブルクリックで元の画面に戻ります。
※ただ、どうも、このタイミングで画面サイズの変更イベントが飛んでいるっぽい?

private void notifyIcon1_DoubleClick(object sender, System.EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.WindowState = FormWindowState.Normal;
}
// Activate the form.
this.Activate();
this.Show();
}

【手順4】
 【手順2】の画面表示で非表示にするために、下記のようにFormのサイズ変更処理で、

 画面サイズを最小化された場合 →FormをHide()あるいは、Visibleをfalseにする。
 画面サイズを元に戻した場合  →FormをShow()あるいは、Visibleをtrueにする。

ようにしました。
これで、【手順2】の問題は解消されました。
が、新たに【手順3】で別の問題が発生しだしました。

【新たな問題】最小化状態でタスクトレイアイコンのダブルクリックすると、
       一度元のサイズに戻った後に、タイトルバーの幅の画面サイズに
変更されてしまいます。(デバッグで、確認)

予想するに、手順2のタイミングで、画面サイズを変更されているのではないかと
思ったのですが、...
でも、変更前は、正しく戻っていたので関係ないはずな気もするし...

おそらく、『画面サイズを最小化された場合→FormをHide()あるいは、
Visibleをfalseにする。』ことで予期しない処理が
走っているのでしょうか?

private void Form1_SizeChanged(object sender, System.EventArgs e)
{
if( this.WindowState == System.Windows.Forms.FormWindowState.Minimized )
{
this.Hide();
//this.Visible=false;
}
else if( this.WindowState == System.Windows.Forms.FormWindowState.Normal )
{
//this.Show();
//this.Visible=true;
}
}

以上、ご存知の方いらっしゃいましたらよろしくお願い致します。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-05-10 10:38
引用:

MSDN, Form.WindowState プロパティ からの引用 :

フォームを一度表示した後に非表示にすると、これらのプロパティには、 WindowState プロパティを変更したかどうかに関係なく、フォームが再度表示されるまで前の状態が反映されます。


これが原因ですね。
順番を変えて、ShowしてからWindowStateを変えれば大丈夫でしょう。
Makoto
大ベテラン
会議室デビュー日: 2004/03/31
投稿数: 133
投稿日時: 2005-05-10 13:14
回答ありがとうございました。

private void notifyIcon1_DoubleClick(object sender, System.EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.Show();
this.WindowState = FormWindowState.Normal;
}
// Activate the form.
this.Activate();
}

上記のように変更したところ、うまくいきました。
しかし、別件で問題が発生しました...

【新規問題1】
『最大化』→『最小化』→『サイズを戻す』のように操作すると、
変更前のようにサイズが正しく変更されない現象が発生しました(泣)
単純に、最大化した後にサイズを戻す場合には、発生しません...

また、従来からの別件問題なんですが、『最小化する』と、
右下(スタートボタンの方向)に入っていくように表示されます。
これって、どうにもならないんでしょうか?

もしご存知でしたら、回答お願い致します。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-05-10 19:53
アニメーションをさせずにぱっと非表示・表示をさせたいということでしょうか。
それなら、いっそ最小化される際の処理をさせないと言う手法はどうでしょう。
フォームのWndProcで、MsgがWM_SYSCOMMAND(0x112)、WParamがSC_MINIMIZE(0xF020)のときに、Hide()させた上で(base.WndProcを呼ばずに)そのままreturnさせてしまいます。
そうすれば最小化ボタンを押したときにWindowStateがMinimizedになることがなくなります。
単純にHide()されているだけですから、NotifyIconをクリックしたときにもWindowStateを考慮する必要はありません。
Makoto
大ベテラン
会議室デビュー日: 2004/03/31
投稿数: 133
投稿日時: 2005-05-10 20:24
度々の回答ありがとうございます。
下記のような関数をFormクラスに追加したところ、狙い通りの処理になりました。

はじめから、『Windowsの最小化イベントを処理前に捕捉する方法はありますか?』
と聞けば良かったですね...
C#では無理と思っていたので、聞きませんでした。
お手数お掛けしました。

ところで、下記の値(0x112や0xF020)を探すには、
やはりWinAPIのヘッダファイルの値を見ることになるんですよね。
.Netではきっと、WM_SYSCOMMANDとかが、#defineで定義されてたりしないんですよね...

//Windowイベントの捕捉処理!
protected override void WndProc(ref Message m)
{
//※下記例は、最小化ボタンクリックで、FormをHideするだけの処理にしている。
// 最小化されません!
// その他の場合には、既定の処理をさせる!→base.WndProc(ref m) ;
// Msgが、WM_SYSCOMMAND(0x112)
// WParamが、SC_MINIMIZE(0xF020)
if((m.Msg == 0x112) && (m.WParam == (IntPtr)0xF020))
{
Hide();
}
else
{
base.WndProc(ref m) ;
}
}

ありがとうございました。
また何かありましたら、よろしくお願い致します。
BabyDaemons
会議室デビュー日: 2008/04/22
投稿数: 4
投稿日時: 2008-05-07 18:00
このスレッドのおかげで、タスクトレイがらみのFormの動作を
アニメーション無しに揃えることが出来ました。助かりました。

http://d.hatena.ne.jp/babydaemons/20080507/1210150398

// cf. http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=21135&forum=7
//Windowイベントの捕捉処理!
protected override void WndProc(ref Message m)
{
//※下記例は、最小化ボタンクリックで、FormをHideするだけの処理にしている。
// 最小化されません!
// その他の場合には、既定の処理をさせる!→base.WndProc(ref m) ;
// Msgが、WM_SYSCOMMAND(0x112)
// WParamが、SC_MINIMIZE(0xF020)
if ((m.Msg == 0x112) && (m.WParam == (IntPtr)0xF020))
{
base.Hide(); // 隠す
}
else
{
base.WndProc(ref m);
}
}

private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
base.Show(); // 表示する
this.Visible = true; // フォームの表示
base.Activate(); // フォームをアクティブにする
}

private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true; // 終了処理のキャンセル
base.Hide(); // 隠す
}
}

private void 終了XToolStripMenuItem_Click(object sender, EventArgs e)
{
notifyIcon1.Visible = false; // アイコンをトレイから取り除く
Application.Exit(); // アプリケーションの終了
}

1

スキルアップ/キャリアアップ(JOB@IT)