.NETのちょっとマイナーな機能 その2(後半)

遅くなりましたが、前半のつづきです。


拡張プロバイダコンポーネントを作るのに重要なポイントは下記の3つです。



ProvideProperty属性を使って、プロパティの名前と型を指定します。
提供するプロパティは、プロパティとして実装するわけではなくメソッドとして実装する必要があります。メソッドの名前は、Get+プロパティ名、Set+プロパティ名にする必要があります。これはそのようなルールのようです。こうしないとうまく動きませんのでご注意を。


IExtenderProviderインターフェイスは、CanExtendというメソッドを持っています。このメソッドにより、どのオブジェクトに対してプロパティの提供を許可するのかを指定します。


では、実際の作成のほうに移りましょう。


ここでは、フォーカスを受け取ったら背景色を変更するOnFocusBackColorというプロパティを提供する拡張プロバイダコンポーネントを作成します。
まず、Visual Studioのプロジェクトの新規作成にて、クラスライブラリを選択します。ここでは、言語はVisual Basicを選択します。


次に、参照設定にSystem.DrawingとSystem.Windows.Formsを追加してください。
その後、下記のコードを貼り付けます。このコードはデブサミのセッションで使ったものと同じものです。


07/08/17:コメントにてご指摘いただいた点を修正


Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
 
' OnFocusBackColorプロパティを提供する拡張プロバイダコンポーネント
<ProvideProperty("OnFocusBackColor", GetType(Windows.Forms.Control))> _
Public Class MyExtendrProvider
    Inherits System.ComponentModel.Component
    Implements System.ComponentModel.IExtenderProvider
 
    ' Windowsフォームコントロールへのプロパティ提供を許可します
    Public Function CanExtend(ByVal extendee As Object) As Boolean Implements System.ComponentModel.IExtenderProvider.CanExtend
        If TypeOf extendee Is Windows.Forms.Control Then
            addPropertyValue(CType(extendee, Windows.Forms.Control))
            Return True
        Else
            Return False
        End If
    End Function
 
    Friend htCtrlProperties As New Hashtable
 
    ' ハッシュテーブルに各コントロールごとのプロパティの値を保存します
    Private Function addPropertyValue(ByVal ctrl As Windows.Forms.Control) As MyExtendedProperties
        If htCtrlProperties.Contains(ctrl) Then
            Return CType(htCtrlProperties(ctrl), MyExtendedProperties)
        Else
            Dim props As New MyExtendedProperties
            props.myDefaultColor = ctrl.BackColor
            htCtrlProperties.Add(ctrl, props)
 
            AddHandler ctrl.GotFocus, AddressOf GotFocusHandler
            AddHandler ctrl.LostFocus, AddressOf LostFocusHandler
 
            Return props
        End If
    End Function
 
    ' フォーカスを受け取ったときに背景色をOnFocusBackColorプロパティの値に変更します
    Private Sub GotFocusHandler(ByVal sender As Object, ByVal e As EventArgs)
        CType(sender, Control).BackColor = CType(htCtrlProperties(CType(sender, Control)), MyExtendedProperties).OnFocusBackColor
    End Sub
 
    ' フォーカスを失ったときにデフォルトの背景色へと戻します
    Private Sub LostFocusHandler(ByVal sender As Object, ByVal e As EventArgs)
        CType(sender, Control).BackColor = CType(htCtrlProperties(CType(sender, Control)), MyExtendedProperties).myDefaultColor
    End Sub
 
    <Description("コントロールがフォーカスを受け取ったときに表示する背景色を設定します。"), _
        Category("MyExtenderProvider")> _
    Public Function GetOnFocusBackColor(ByVal ctrl As Windows.Forms.Control) As Color
        If Not htCtrlProperties.Contains(ctrl) Then
            addPropertyValue(ctrl).OnFocusBackColor = addPropertyValue(ctrl).myDefaultColor
        End If
        Return CType(htCtrlProperties(ctrl), MyExtendedProperties).OnFocusBackColor
    End Function
 
    Public Sub SetOnFocusBackColor(ByVal ctrl As Windows.Forms.Control, ByVal value As Color)
        addPropertyValue(ctrl).OnFocusBackColor = value
    End Sub
 
    Public Class MyExtendedProperties
        Public OnFocusBackColor As Color
        Public myDefaultColor As Color
    End Class
 
End Class


上記のコードでは各コントロール毎のプロパティ値を格納するのにHashtableを使っています。
そうしましたら、ビルドしてアセンブリを作成します。これで拡張プロバイダコンポーネントの完成です。


さっそく、使ってみましょう。Windowsアプリケーションから作成したアセンブリでもプロジェクトでも構いませんが、参照設定を追加してください。
フォームに適当なコントロールを貼り付けて、作成した拡張プロバイダコンポーネントを貼り付けると、下記の画像のようにプロパティが拡張されているはずです。



適当な色を設定し、実行してみましょう。フォーカスをあてると指定した色に変更されるはずです(フォーカスがあたらないWindowsフォームコントロールもありますのでご注意を)。


前半と後半で拡張プロバイダを説明してきましたが、拡張プロバイダの便利さは感じていただけたでしょうか。グレープシティの入力コンポーネントInputMan for .NET 4.0Jでは、3D効果やキャプションなどを提供するコンテナ(Container)コントロール、ふりがな取得や変換モードといった機能を提供するIMEImeコンポーネントなど、いくつかのコンポーネントを拡張プロバイダとして実装しています。是非、この便利さをご体感ください。


最後に、実際に試されて分からない部分、うまくいかないなどの問題がありましたら、どんな些細なことでも構いませんのでコメントに書いていただければと思います。