C#

 

タイトルだけだと「なんのこっちゃ?」となりますが Visual Studio で C#を使いWindows フォーム アプリ (.NET Framework)を開発中での話です。

 

 

FormClosingイベントハンドラーにジャンプする問題を修正する

 

 

問題

例えば、Form1にメニューを配置し終了というメニューを作ったとします。メニューで終了をクリックするとアプリが終了するという、ごく当たり前のコードなのですが

private void 終了XToolStripMenuItem_Click(object sender, EventArgs e)
{
    DialogResult res = MessageBox.Show("終了しますか?", "終了確認", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
    if (res == DialogResult.Yes)
    { 
        Application.Exit();
    }
}

このメニュー内の終了をクリックするとメッセージボックスが現れ終了確認をするのですが、「はい」(終了)を選択してもアプリが閉じることなく、なぜか、Form1を閉じる(アプリにある×マークの事)用のイベントハンドラーである、Form1_FormClosingイベントハンドラーにジャンプしてしまう問題が発生してしまうのでした。

↓ここにジャンプしてしまう
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (MessageBox.Show(info, "終了確認", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
    {
        e.Cancel = true; // 終了をキャンセルします
    }
    Application.Exit();
}

つまり、終了確認が2回出るという問題です。

 

 

問題修整

 

//終了XToolStripMenuItem_Clickイベントハンドラー内で
//FormClosingイベントのハンドラーを解除

using System.Linq;


private void 終了XToolStripMenuItem_Click(object sender, EventArgs e)
{
    DialogResult res = MessageBox.Show("終了しますか?", "終了確認", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
    if (res == DialogResult.Yes)
    {
        // FormClosingイベントのハンドラーを解除する
        this.FormClosing -= Form1_FormClosing; 
        Application.Exit();
    }
}


//Form1_FormClosingイベントハンドラー内で
//アプリケーションが終了するように設定

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (!Application.OpenForms.Cast<Form>().Any(form => form.Visible))
    {
        Application.Exit(); // アプリケーションを終了させる
    }
}

 

終了XToolStripMenuItem_Clickイベントハンドラー内でApplication.Exit()を呼び出すと、アプリケーションが直ちに終了します。

また、Form1_FormClosingイベントハンドラー内では、アプリケーションがすでに終了されている場合は何も処理せず、それ以外の場合にアプリケーションを終了します。

これにより、終了XToolStripMenuItem_Clickイベントハンドラーからアプリケーションを終了させた場合に、Form1_FormClosingイベントハンドラーにジャンプする問題が解決されました。

 

以上。