/ .NET

image
何だか格好良さげなタイトルですが、Windowsフォームアプリの例外関連の話。
上のような画面を見たことのある開発者の方もいるかと思いますが、フォームやコントロールの描画処理で何らかの例外が発生すると描画が中止されて赤い×マーク(バツマーク、バッテン)が表示されます。
通常はユーザコントロールなどの内部処理で落ちた場合などに発生するケースが多いと思うのですが、この×マーク、一旦表示されると元の表示状態に戻すのがなかなか難しく、普通は画面を開き直したり、アプリ再起動くらいしか手段がありません。
この問題を解決すべく、海外のWebサイトを徘徊した結果、見つけた回避策が以下の方法。

Public Class Form1

	Dim isError As Boolean = False

	Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
		If isError Then
			Throw New Exception()
		End If
	End Sub

	Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
		isError = Not isError

		If isError Then
			Button1.Text = "reset"
		Else
			Me.GetType().InvokeMember("SetState", _
			 System.Reflection.BindingFlags.NonPublic _
			 Or System.Reflection.BindingFlags.InvokeMethod _
			 Or System.Reflection.BindingFlags.Instance, Nothing, _
			 Me, New Object() {&H400000, False})
			Me.Invalidate()

			Button1.Text = "throw exception"
		End If
	End Sub

End Class

OnPaintイベントでわざとエラーを発生させて×マークを表示した後、ボタンクリックで再描画を行うサンプルです。
実際のアプリではOnThreadExceptionで×マークの原因となったスレッド例外を捕捉したら再描画、といった感じになるでしょうか。
ハイライト表示した箇所が強制再描画のくだりですが、リフレクションでSetStateなる内部メソッドを呼び出してエラー状態を解消するという、なかなかの荒業。
SetStateや0x400000の意味などはソースを直接覗くしか知るすべがないようです。
とりあえずVBで書いていますが、参考にさせていただいたこちらのサイトにC#で書かれたサンプルも掲載されています。
もちろん、根本的な描画時エラーを取り除いて×マーク自体を出現させないようにすることが先決ですので、どうしても解決できない場合の参考ということで…



コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です