WPF ではフォームのことをウィンドウ(Window)と呼びます。Window と Form では、どのような違いがあるのでしょうか。

Windows OS との相互運用

 WPF の Window には Windows OS とやり取りする部分が隠されています。なにかというと、ウィンドウメッセージを処理する WndProc メソッドがありません。ウィンドウスタイルを作成する CreateParams プロパティもありません。Windows OS とやり取りするために一番必要なウィンドウハンドルもありません。このように WPF の Window は Windows OS とは独立して WPF の中で動作するように作成されています。

 それでも WPF が Windows OS 上で動作する以上は、Windows OS とやり取りする必要があります。次のようにすれば、その部分を処理することができるようになります。

WPF でウィンドウプロシージャを処理する例
Imports System.Windows.Interop

Private Class Window1
    Private Sub Window1_SourceInitialized(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.SourceInitialized
        Dim wih As New WindowInteropHelper(Me)
        Dim hs As HwndSource = HwndSource.FromHwnd(wih.Handle)
        hs.AddHook(AddressOf WndProc)
    End Sub
    Private Function WndProc(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByRef handled As Boolean) As IntPtr
        ' WndProc と同じように処理できます。
        Return IntPtr.Zero
    End Function
End Class

 Windows OS とやり取りするためのライブラリが System.Windows.Interop 名前空間にあります。その中の WindowInteropHelper クラスを使用することで、Window の ウィンドウハンドル を取得することができます。そのウィンドウハンドルから HwndSource クラスを生成し、AddHook メソッドでウィンドウプロシージャをフックできるようになります。また、ウィンドウハンドルさえ取得できれば、SendMessage などの Win32 API を呼び出す P/Invoke ができます。

Window のコントロールボックス

 P/Invoke しなくても Window に対するあらゆることができるだろうと思いましたが、できないこともあるようです。その代表的といえるのがコントロールボックスの表示可否についてです。

 Window にはコントロールボックス自体とその部品を非表示にするプロパティがありません。アイコンの表示可否のプロパティがないため、独自のダイアログなどを作成しようとした場合、必ずアイコンが表示されてしまいます。通常ダイアログなどのサブウィンドウは、メインウィンドウと区別するためにアイコンを表示しません。

 最小化、最大化ボタンの表示可否のプロパティもありません。一応 ResizeMode プロパティである程度は設定できますが、最小化ボタンを無効にして最大化ボタンを有効にするといった、細かいことができません。

Window の Dispose メソッド

 Window は Dispose メソッドを実装していません。Finalize メソッドも定義されてありません。ということはマネージリソースとアンマネージリソースの両方を持っていないということでしょうか? 詳しくはわかりませんが、Dispose メソッドを実装しているクラスを内部に持ったときに実装すればいいのだと思います。

まとめ

  • Window は Windows OS とのやり取りする部分を隠蔽している。
  • System.Windows.Interop 名前空間に存在するライブラリを使用することで、その部分を処理することができる。
  • コントロールボックスは P/Invoke で表示可否を制御する必要がある。
  • Dispose メソッドを実装していない。
  • Finalize メソッドも定義されていない。

 Window では Windows OS とやり取りする部分が隠蔽されているため、なんだかクリーンになった気がします。これで P/Invoke する必要がないと思っても、コントロールボックスの表示可否が Window では制御できないなど、必要なものが抜けているように思います。