はい、これは可能です。Application.Exit()メソッドは、Application.OpenFormsコレクション内のフォームを反復処理して、OnFormClosing()メソッドを呼び出します。Winformsにはバグがあり、そのコレクションは開いているフォームを追跡できなくなります。このコードはそれを示しています:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
protected override void OnHandleCreated(EventArgs e) {
// Set breakpoint here:
base.OnHandleCreated(e);
}
protected override void OnMouseDown(MouseEventArgs e) {
this.ShowInTaskbar = !this.ShowInTaskbar;
MessageBox.Show(string.Format("There are {0} open forms", Application.OpenForms.Count));
Application.Exit();
}
protected override void OnFormClosing(FormClosingEventArgs e) {
MessageBox.Show("you won't see this");
base.OnFormClosing(e);
}
}
フォームをクリックしてバグをトリガーします。0の開いているフォームがどのように報告され、OnFormClosingにメッセージボックスが表示されなかったかに注意してください。
それを引き起こすのは、ShowInTaskbarプロパティへの割り当てです。そのようなプロパティはいくつかありますが、NotifyIconがある場合に使用する可能性が高いため、ShowInTaskbarを選択しました。RightToLeftはもう1つです。これらのプロパティは、ウィンドウがネイティブのCreateWindowEx()API関数で作成された場合にのみ指定できるため、特別です。それらを変更するには、Winformsがかなり英雄的なことをする必要があります。ウィンドウを破壊して再作成します。残念ながら、これもバグの引き金となります。ウィンドウを破棄すると、OpenFormsコレクションからフォームが削除され、追加し直すのを忘れてしまいます。
このスニペットからOnHandleCreated()メソッドをコピーしてフォームに貼り付け、ブレークポイントを設定します。ウィンドウが最初に作成されたときに、一度トリガーする必要があります。再度トリガーされてバグシナリオが呼び出されると、呼び出しスタックを調べて、クラス内のどのコードがトリガーしたかを確認できます。そのコードを無効にして、別の方法を見つける必要があります。コンストラクターでShowInTaskbarプロパティを設定することは問題ありませんが、Loadイベントハンドラーのように、ウィンドウの作成後に割り当てた場合にのみ問題が発生します。