びったんびったん

ユーザビリティ・プログラミングについて。

ShowWindow(hWnd, SW_RESTORE) は Visible プロパティを更新しない

やりたいこと

最小化されていてかつ非表示なフォームがある。これを表示し元のサイズに戻したい。

バグ

状況を再現する最小のコードを書いた。元のサイズに戻すことは .NET ではできないので Win32 の ShowWindow(hWnd, SW_RESTORE) 関数を使う。

class C {

    [DllImport("user32")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    private const int SW_RESTORE = 9;

    private void F() {
        var f = new Form {
            WindowState = FormWindowState.Minimized
        };
        ShowWindow(f.Handle, SW_RESTORE);

        Console.WriteLine(f.Visible); // フォームは表示されているのになぜか Visible は false
    }
}

フォームは表示されているのになぜか Visible は false になる。イミワカンナイ

なにがまずいのか

.NET がフォームをごにょごにょするときに Visible を参照して表示か非表示かを判断していることがありそこがバグる

具体的にはフォームに関連付けられたコンテキストメニューは、フォームが表示されているときにしか表示できないらしい。先のバグでフォームが表示されているにもかかわらずコンテキストメニューが表示できなかった。

じゃあどうすんの

ShowWindow(f.Handle, SW_RESTORE);
f.Show();
// f.Visible = true;

ShowWindow 関数の直後に Show メソッドを呼ぶか Visible プロパティに true をセットする。かなり気持ち悪いが、今のところ不具合は起きていない。もっとよい方法があれば教えてください。

まとめ

.NET と Win32 が混在するときには最新の注意を払いましょう。