ウィンドウアプリケーションで「Alt + F4」といったキー操作により
画面が閉じられるのを制御するにWndProcメソッドをオーバーライドするのが
普通だと思い込んでいたのですが、
.NET Framework 2.0以降であればCloseReasonプロパティを使用すればよりシンプルにできました。
CloseReasonプロパティについて
CloseReasonプロパティの内容については以下の通りです。
| 列挙体 | 説明 |
|---|---|
| ApplicationExitCall | Application.Exitメソッドが呼び出された。 |
| FormOwnerClosing | 呼び出し元のフォーム画面が閉じられようとしている。 |
| MdiFormClosing | 呼び出し元のMDI親フォームが閉じられようとしている。 |
| None | なんで閉じられようとしているのかわかんね┐(´ー`)┌ |
| TaskManagerClosing | タスクマネージャーにによってアプリが終了させられようとしている。 |
| UserClosing | ユーザ操作(×ボタンクリック、Alt+F4押下etc…)によって画面が閉じられようとしている。 ※注意点有 |
| WindowsShutDown | OSのシャットダウン処理によってアプリが終了させられようとしている。 |
FormOwnerClosingの注意点について
FormOwnerClosingの説明は公式リファレンスに以下のように書かれています。
ユーザーが、フォーム ウィンドウの [閉じる] ボタンを押す、ウィンドウのコントロール メニューの [閉じる] をクリックする、Alt キーと F4 キーを同時に押すなどの方法で、ユーザー インターフェイス (UI) を通じてフォームを閉じようとしています。
しかし、Form.Closeメソッドを実行した時も「UserClosing」として処理される為、
フラグ管理を行う必要がありそうです…(;´Д`)
Closeメソッド内の処理
Form.Closeメソッドのコードを見たらしっかりとUserClosingをセットしていました…
public void Close() {
if (GetState(STATE_CREATINGHANDLE))
throw new InvalidOperationException(SR.GetString(SR.ClosingWhileCreatingHandle, "Close"));
if (IsHandleCreated) {
closeReason = CloseReason.UserClosing;
SendMessage(NativeMethods.WM_CLOSE, 0, 0);
}
else{
// MSDN: When a form is closed, all resources created within the object are closed and the form is disposed.
// For MDI child: MdiChildren collection gets updated (VSWhidbey# 368642 & 93550)
Dispose();
}
}
サンプルコード
Form.Closeメソッドを呼ぶ前にフラグを操作しているだけの簡単なプログラムです。
bool userClosingFlag = true;
/// <summary>
/// フォーム閉じる際にイベント検知するやーつ
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
switch (e.CloseReason)
{
case CloseReason.ApplicationExitCall:
MessageBox.Show("ApplicationExitCall");
break;
case CloseReason.FormOwnerClosing:
MessageBox.Show("FormOwnerClosing");
break;
case CloseReason.MdiFormClosing:
MessageBox.Show("MdiFormClosing");
break;
case CloseReason.None:
MessageBox.Show("None");
break;
case CloseReason.TaskManagerClosing:
MessageBox.Show("TaskManagerClosing");
break;
case CloseReason.UserClosing:
// Form.Closeメソッドでも「UserClosing」判定となる。
if (userClosingFlag)
{
MessageBox.Show("UserClosing");
}
else
{
MessageBox.Show("Form.Close");
}
break;
case CloseReason.WindowsShutDown:
MessageBox.Show("WindowsShutDown");
break;
default:
break;
}
}
/// <summary>
/// 閉じるボタン押下時イベント
/// </summary>
/// <param name="sender">イベント送信元</param>
/// <param name="e">イベント引数</param>
private void Button1_Click(object sender, EventArgs e)
{
userClosingFlag = false;
this.Close();
}
実行結果
実行結果は以下の通りです。
Alt+F4押下時
ボタン押下時
キー制御を行うよりシンプルにコーディングできるので多少は使えるのかな…(=゚ω゚)



