« 10.23 時間の問題だとは | ココ | 10.25 VSライクなTabView »

2006年10月24日

サブクラス化 with .NET  このエントリーを含むはてなブックマーク 

VB.NETになってようやく継承でWndProc()が使えるようになるまで、ウィンドウメッセージを補足しようとするなら、メッセージフックやサブクラス化といった手法が必須でした。わがPinMarchでも、VB5のときにサブクラス化をするクラス(コントロール)を作っていました(今もそれは残ってますが)。

WndProc()がサポートされたことにより、ある程度のメッセージ処理が可能にはなりましたが、わざわざ継承をするほどでもない場合など、どうしても他のウィンドウのメッセージを補足したいときがあります。

子ウィンドウ(コントロール)から、親ウィンドウ(フォーム)のメッセージを補足したいときなんかはまさにそれに当たります。


子ウィンドウでタイトルバーを付けることができるんですが、普通にウィンドウスタイルを変えただけだと、子ウィンドウのタイトルバーの色が常に非アクティブなんですね。これじゃあ格好悪いです。

原因は、WM_NCACTIVATEがやって来ないことです。WM_NCPAINTなら来るっぽいですが。ここで、親ウィンドウ(親フォーム)のメッセージフックをやらねばなぁとなるわけですわ。

そこで、ちょうど参考になったのが、NativeWindowクラスを用いたサブクラス化(スナップウィンドウの作成)。こちらをご覧いただくことを強くお奨めします。

' NativeWindowクラスから継承したサブクラス化?ウィンドウ

Private Class _OwnerNativeWindow
  Inherits NativeWindow

  Private _target As Control

  Public Property Target() As Control
    Get
      Return _target
    End Get
    Set(ByVal Value As Control)
      _target = Value
    End Set
  End Property

  <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    'Debug.WriteLine(Hex(m.Msg))
    ' WM_NCPAINTとWM_NCACTIVATEを子ウィンドウ(_target)に転送
    Select Case m.Msg
      Case WM_NCPAINT
        Dim m2 As Message = Message.Create(_target.Handle, m.Msg, m.WParam, m.LParam)
        MyBase.WndProc(m2)
      Case WM_NCACTIVATE
        Dim m2 As Message = Message.Create(_target.Handle, m.Msg, m.WParam, m.LParam)
        MyBase.WndProc(m2)
    End Select

    MyBase.WndProc(m)
  End Sub
End Class

子ウィンドウのハンドル作成時に先ほどの_OwnerNativeWindowクラスを生成して、親ウィンドウのハンドルを割り当てれば、親ウィンドウのメッセージがそっちに流れ込みます。子ウィンドウが破棄されるときには、割り当てを解除することをお忘れなく。

' 子ウィンドウの各関数をオーバーライド

  Protected Overrides Sub OnHandleCreated(ByVal e As System.EventArgs)
    _owner = New _OwnerNativeWindow
    _owner.Target = Me
    _owner.AssignHandle(Me.TopLevelControl.Handle)

    MyBase.OnHandleCreated(e)

  End Sub

  Protected Overrides Sub OnHandleDestroyed(ByVal e As System.EventArgs)
    _owner.ReleaseHandle()
    _owner = Nothing

    MyBase.OnHandleDestroyed(e)

  End Sub

NativeWindowクラスを使えば、SendMessage()APIの代わりにもなりそうですね。

By ただ at 22:03 カテゴリー ; さんぷるライブラリー , PinMarch Samples , VB, VB .net , プログラミング単語帳 , mein Erbe , 仕事関係

« 10.23 時間の問題だとは | 10月の記事 | 10.25 VSライクなTabView »




トラックバック

このエントリーのトラックバックURL:
http://pinmarch.sakura.ne.jp/mt/mt-tb.cgi/684