다음을 통해 공유


방법: HelpLabel Extender 공급자 구현

extender 공급자는 다른 구성 요소에 속성을 제공하는 구성 요소입니다.예를 들어, ToolTip 컨트롤은 extender 공급자로 구현됩니다.ToolTip 컨트롤을 Form에 추가할 때, Form에 있는 다른 모든 컨트롤의 속성 목록에는 ToolTip 속성이 추가됩니다.

다음 샘플은 HelpLabel 컨트롤을 만들어 extender 공급자를 빌드하는 방법을 보여 줍니다.또한 CanExtend 메서드와 HelpText 속성의 구현을 보여 줍니다.CanExtend 메서드는 Windows Forms 디자이너에서 이 속성을 지정한 컨트롤로 확장할지 여부를 결정하기 위해 사용됩니다.HelpLabel 컨트롤은 폼의 컨트롤에 사용할 HelpText 속성을 확장합니다.컨트롤의 도움말 텍스트는 포커스가 컨트롤에 있을 때 패널에 표시됩니다.

이 샘플에는 방법: 컨트롤에 대한 디자이너 구현에 설명된 중첩 디자이너가 포함되어 있습니다.

이 샘플은 다음 항목을 보여 줍니다.

  • Extender 공급자 HelpLabel은 IExtenderProvider를 구현합니다.

  • HelpLabel 컨트롤은 ProvidePropertyAttribute를 사용하여 제동되는 속성의 이름과 속성을 수신할 수 있는 구성 요소의 형식을 지정합니다.

  • HelpLabel 자체는 Windows Forms 컨트롤이므로 Control에서 파생됩니다.

  • CanExtend 메서드는 HelpLabel을 제외한 모든 컨트롤에 대해 true를 반환합니다. 자체의 속성을 확장하는 것은 의미가 없기 때문입니다.

  • HelpLabel에는 HelpLabel에서 다른 컨트롤이 사용할 수 있도록 하는 속성을 가져오는 GetHelpText라는 메서드가 있습니다.SetHelpText 메서드는 이 속성의 값을 설정합니다.

    [!참고]

    확장 속성은 GetHelpText 및 SetHelpText 메서드에 의해 제공되고 HelpLabel은 HelpText라는 속성을 노출하지 않습니다.

예제

HostApp 클래스는 폼의 HelpLabel 컨트롤을 사용합니다.

Option Strict On
Option Explicit On 
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Windows.Forms.Design

Namespace Microsoft.Samples.WinForms.Vb.HelpLabel
    '
    ' <doc>
    ' <desc>
    ' Help Label offers an extender property called
    ' HelpText.  It monitors the active control
    ' and displays the help text for the active control.
    ' </desc>
    ' </doc>
    '

    <ProvideProperty("HelpText", GetType(Control)), Designer(GetType(HelpLabel.HelpLabelDesigner))> _
    Public Class HelpLabel
        Inherits Control
        Implements System.ComponentModel.IExtenderProvider
        ' <summary>
        '    Required designer variable.
        ' </summary>
        Private components As System.ComponentModel.Container
        Private helpTexts As Hashtable
        Private activeControl As System.Windows.Forms.Control

        '
        ' <doc>
        ' <desc>
        '      Creates a new help label object.
        ' </desc>
        ' </doc>
        '
        Public Sub New()
            '
            ' Required for Windows Form designer support.
            '
            InitializeComponent()
            helpTexts = New Hashtable
        End Sub

        ' <summary>
        '    Clean up any resources being used.
        ' </summary>
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                If components IsNot Nothing Then
                    components.Dispose()
                End If
            End If
            MyBase.Dispose(disposing)
        End Sub

        ' <summary>
        '    Required method for designer support. Do not modify
        '    the contents of this method with the code editor.
        ' </summary>
        Private Sub InitializeComponent()
            Me.components = New System.ComponentModel.Container
            Me.BackColor = System.Drawing.SystemColors.Info
            Me.ForeColor = System.Drawing.SystemColors.InfoText
            Me.TabStop = False
        End Sub
        '
        ' <doc>
        ' <desc>
        '      Overrides the text property of Control.  This label ignores
        '      the text property, so we add additional attributes here so the
        '      property does not show up in the Properties window and is not
        '      persisted.
        ' </desc>
        ' </doc>
        '
        <Browsable(False), _
        EditorBrowsable(EditorBrowsableState.Never), _
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public Overrides Property [Text]() As String
            Get
                Return MyBase.Text
            End Get
            Set(ByVal Value As String)
                MyBase.Text = Value
            End Set
        End Property


        '
        ' <doc>
        ' <desc>
        '      This implements the IExtenderProvider.CanExtend method.  The
        '      help label provides an extender property, and the design-time
        '      framework will call this method once for each component to determine
        '      if we are interested in providing our extended properties for the
        '      component.  We return true here if the object is a control and is
        '      not a HelpLabel (because it would not be meaningful to add this property to
        '      ourselves).
        ' </desc>
        ' </doc>
        '
        Function CanExtend(ByVal target As Object) As Boolean Implements IExtenderProvider.CanExtend
            If TypeOf target Is Control And Not TypeOf target Is HelpLabel Then

                Return True
            End If
            Return False
        End Function

        '
        ' <doc>
        ' <desc>
        '      This is the extended property for the HelpText property.  Extended
        '      properties are actual methods because they take an additional parameter
        '      that is the object or control to provide the property for.
        ' </desc>
        ' </doc>
        '
        <DefaultValue("")> _
        Public Function GetHelpText(ByVal ctrl As Control) As String
            Dim myText As String = CStr(helpTexts(ctrl))
            If myText Is Nothing Then
                myText = String.Empty
            End If
            Return myText
        End Function

        '
        ' <doc>
        ' <desc>
        '      This is the extended property for the HelpText property.
        ' </desc>
        ' </doc>
        '
        Public Sub SetHelpText(ByVal ctrl As Control, ByVal value As String)
            If value Is Nothing Then
                value = String.Empty
            End If

            If value.Length = 0 Then
                helpTexts.Remove(ctrl)

                RemoveHandler ctrl.Enter, AddressOf OnControlEnter
                RemoveHandler ctrl.Leave, AddressOf OnControlLeave
            Else
                helpTexts(ctrl) = value
                AddHandler ctrl.Enter, AddressOf OnControlEnter
                AddHandler ctrl.Leave, AddressOf OnControlLeave
            End If

            If ctrl Is activeControl Then
                Invalidate()
            End If
        End Sub

        '
        ' <doc>
        ' <desc>
        '      This is an event handler that responds to the OnControlEnter
        '      event.  We attach this to each control we are providing help
        '      text for.
        ' </desc>
        ' </doc>
        '
        Private Sub OnControlEnter(ByVal sender As Object, ByVal e As EventArgs)
            activeControl = CType(sender, Control)
            Invalidate()
        End Sub

        '
        ' <doc>
        ' <desc>
        '      This is an event handler that responds to the OnControlLeave
        '      event.  We attach this to each control we are providing help
        '      text for.
        ' </desc>
        ' </doc>
        '
        Private Sub OnControlLeave(ByVal sender As Object, ByVal e As EventArgs)
            If sender Is activeControl Then
                activeControl = Nothing
                Invalidate()
            End If
        End Sub

        '
        ' <doc>
        ' <desc>
        '      Overrides Control.OnPaint.  Here we draw our
        '      label.
        ' </desc>
        ' </doc>
        '
        Protected Overrides Sub OnPaint(ByVal pe As PaintEventArgs)
            ' Let the base draw.  This will cover our back
            ' color and set any image that the user has
            ' provided.
            '
            MyBase.OnPaint(pe)

            ' Draw a rectangle around the control.
            '
            Dim rect As Rectangle = ClientRectangle

            Dim borderPen As New Pen(ForeColor)
            pe.Graphics.DrawRectangle(borderPen, rect)
            borderPen.Dispose()

            ' Finally, draw the text over the top of the
            ' rectangle.
            '
            If (activeControl IsNot Nothing) Then
                Dim myText As String = CStr(helpTexts(activeControl))
                If (myText IsNot Nothing) And myText.Length > 0 Then
                    rect.Inflate(-2, -2)
                    Dim brush As New SolidBrush(ForeColor)
                    pe.Graphics.DrawString(myText, Font, brush, RectangleF.op_Implicit(rect))
                    brush.Dispose()
                End If
            End If
        End Sub


        ' <doc>
        ' <desc>
        '     Returns true if backColor should be persisted in code gen.  We
        '      override this because we change the default back color.
        ' </desc>
        ' <retvalue>
        '     true if the backColor should be persisted.
        ' </retvalue>
        ' </doc>
        '
        Public Function ShouldSerializeBackColor() As Boolean
            Return Not BackColor.Equals(SystemColors.Info)
        End Function


        ' <doc>
        ' <desc>
        '     Returns true if foreColor should be persisted in code gen.  We
        '      override this because we change the default foreground color.
        ' </desc>
        ' <retvalue>
        '     true if foreColor should be persisted.
        ' </retvalue>
        ' </doc>
        '
        Public Function ShouldSerializeForeColor() As Boolean
            Return Not ForeColor.Equals(SystemColors.InfoText)
        End Function

        '
        ' <doc>
        ' <desc>
        '      This is a designer for the HelpLabel.  This designer provides
        '      design time feedback for the label.  The help label responds
        '      to changes in the active control, but these events do not
        '      occur at design time.  In order to provide some usable feedback
        '      that the control is working the right way, this designer listens
        '      to selection change events and uses those events to trigger active
        '      control changes.
        ' </desc>
        ' </doc>
        '
        <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
        Public Class HelpLabelDesigner
            Inherits System.Windows.Forms.Design.ControlDesigner

            Private _trackSelection As Boolean = True

            ' <summary>
            ' This property is added to the control's set of properties in the method
            ' PreFilterProperties below.  Note that on designers, properties that are
            ' explictly declared by TypeDescriptor.CreateProperty can be declared as
            ' private on the designer.  This helps to keep the designer's public
            ' object model clean.
            ' </summary>
            <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
            Private Property TrackSelection() As Boolean
                Get
                    Return _trackSelection
                End Get
                Set(ByVal Value As Boolean)
                    _trackSelection = Value
                    If _trackSelection Then
                        Dim ss As ISelectionService = CType(GetService(GetType(ISelectionService)), ISelectionService)
                        If (ss IsNot Nothing) Then
                            UpdateHelpLabelSelection(ss)
                        End If
                    Else
                        Dim helpLabel As HelpLabel = CType(Control, HelpLabel)
                        If (helpLabel.activeControl IsNot Nothing) Then
                            helpLabel.activeControl = Nothing
                            helpLabel.Invalidate()
                        End If
                    End If
                End Set
            End Property

            Public Overrides ReadOnly Property Verbs() As DesignerVerbCollection
                Get
                    Dim myVerbs() As DesignerVerb = {New DesignerVerb("Sample Verb", AddressOf OnSampleVerb)}
                    Return New DesignerVerbCollection(myVerbs)
                End Get
            End Property

            '
            ' <doc>
            ' <desc>
            '      Overrides Dispose.  Here we remove our handler for the selection changed
            '      event.  With designers, it is critical that they clean up any events they
            '      have attached.  Otherwise, during the course of an editing session many
            '      designers might get created and never destroyed.
            ' </desc>
            ' </doc>
            '
            Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
                If disposing Then
                    Dim ss As ISelectionService = CType(GetService(GetType(ISelectionService)), ISelectionService)
                    If (ss IsNot Nothing) Then
                        RemoveHandler ss.SelectionChanged, AddressOf OnSelectionChanged
                    End If
                End If
                MyBase.Dispose(disposing)
            End Sub

            '
            ' <doc>
            ' <desc>
            '       Overrides initialize.  Here we add an event handler to the selection service.
            '      Notice that we are very careful not to assume that the selection service is
            '      available.  It is entirely optional that a service is available and you should
            '      always degrade gracefully if a service cannot be found.
            ' </desc>
            ' </doc>
            '
            Public Overrides Sub Initialize(ByVal component As IComponent)
                MyBase.Initialize(component)

                Dim ss As ISelectionService = CType(GetService(GetType(ISelectionService)), ISelectionService)
                If (ss IsNot Nothing) Then
                    AddHandler ss.SelectionChanged, AddressOf OnSelectionChanged
                End If
            End Sub

            Private Sub OnSampleVerb(ByVal sender As Object, ByVal e As EventArgs)
                MessageBox.Show("You have just invoked a sample verb.  Normally, this would do something interesting.")
            End Sub

            '
            ' <doc>
            ' <desc>
            '      The handler for the selection change event.  Here we update the active control within
            '      the help label.
            ' </desc>
            ' </doc>
            '
            Private Sub OnSelectionChanged(ByVal sender As Object, ByVal e As EventArgs)
                If _trackSelection Then
                    Dim ss As ISelectionService = CType(sender, ISelectionService)
                    UpdateHelpLabelSelection(ss)
                End If
            End Sub

            Protected Overrides Sub PreFilterProperties(ByVal properties As IDictionary)
                ' Always call base first in PreFilter* methods, and last in PostFilter*
                ' methods.
                MyBase.PreFilterProperties(properties)

                ' We add a design-time property called TrackSelection that is used to track
                ' the active selection.  If the user sets this to true (the default), then
                ' we will listen to selection change events and update the control's active
                ' control to point to the current primary selection.
                properties("TrackSelection") = TypeDescriptor.CreateProperty( _
                   Me.GetType(), _
                   "TrackSelection", _
                   GetType(Boolean), _
                   New Attribute() {CategoryAttribute.Design})
            End Sub

            ' <summary>
            ' This is a helper method that, given a selection service, will update the active control
            ' of the help label with the currently active selection.
            ' </summary>
            ' <param name="ss"></param>
            Private Sub UpdateHelpLabelSelection(ByVal ss As ISelectionService)
                Dim c As Control = CType(ss.PrimarySelection, Control)
                Dim helpLabel As HelpLabel = CType(Control, HelpLabel)
                If (c IsNot Nothing) Then
                    helpLabel.activeControl = c
                    helpLabel.Invalidate()
                Else
                    If (helpLabel.activeControl IsNot Nothing) Then
                        helpLabel.activeControl = Nothing
                        helpLabel.Invalidate()
                    End If
                End If
            End Sub

            Public Sub New()

            End Sub
        End Class

    End Class
End Namespace
namespace Microsoft.Samples.WinForms.Cs.HelpLabel 
{
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;

    //
    // <doc>
    // <desc>
    // Help Label offers an extender property called
    // "HelpText".  It monitors the active control
    // and displays the help text for the active control.
    // </desc>
    // </doc>
    //
    [
    ProvideProperty("HelpText",typeof(Control)),
    Designer(typeof(HelpLabel.HelpLabelDesigner))
    ]
    public class HelpLabel : Control, System.ComponentModel.IExtenderProvider 
    {
        /// <summary>
        ///    Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components;
        private Hashtable helpTexts;
        private System.Windows.Forms.Control activeControl;

        //
        // <doc>
        // <desc>
        //      Creates a new help label object.
        // </desc>
        // </doc>
        //
        public HelpLabel() 
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            helpTexts = new Hashtable();
        }

        /// <summary>
        ///    Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing) 
        {
            if (disposing) 
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        /// <summary>
        ///    Required method for Designer support - do not modify
        ///    the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent() 
        {
            this.components = new System.ComponentModel.Container ();
            this.BackColor = System.Drawing.SystemColors.Info;
            this.ForeColor = System.Drawing.SystemColors.InfoText;
            this.TabStop = false;
        }

        //
        // <doc>
        // <desc>
        //      Overrides the text property of Control.  This label ignores
        //      the text property, so we add additional attributes here so the
        //      property does not show up in the properties window and is not
        //      persisted.
        // </desc>
        // </doc>
        //
        [
        Browsable(false),
        EditorBrowsable(EditorBrowsableState.Never),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
        ]
        public override string Text 
        {
            get 
            {
                return base.Text;
            }
            set 
            {
                base.Text = value;
            }
        }

        //
        // <doc>
        // <desc>
        //      This implements the IExtenderProvider.CanExtend method.  The
        //      help label provides an extender property, and the design time
        //      framework will call this method once for each component to determine
        //      if we are interested in providing our extended properties for the
        //      component.  We return true here if the object is a control and is
        //      not a HelpLabel (since it would be silly to add this property to
        //      ourselves).
        // </desc>
        // </doc>
        //
        bool IExtenderProvider.CanExtend(object target) 
        {
            if (target is Control &&
                !(target is HelpLabel)) 
            {

                return true;
            }
            return false;
        }

        //
        // <doc>
        // <desc>
        //      This is the extended property for the HelpText property.  Extended
        //      properties are actual methods because they take an additional parameter
        //      that is the object or control to provide the property for.
        // </desc>
        // </doc>
        //
        [
        DefaultValue(""),
        ]
        public string GetHelpText(Control control) 
        {
            string text = (string)helpTexts[control];
            if (text == null) 
            {
                text = string.Empty;
            }
            return text;
        }

        //
        // <doc>
        // <desc>
        //      This is an event handler that responds to the OnControlEnter
        //      event.  We attach this to each control we are providing help
        //      text for.
        // </desc>
        // </doc>
        //
        private void OnControlEnter(object sender, EventArgs e) 
        {
            activeControl = (Control)sender;
            Invalidate();
        }

        //
        // <doc>
        // <desc>
        //      This is an event handler that responds to the OnControlLeave
        //      event.  We attach this to each control we are providing help
        //      text for.
        // </desc>
        // </doc>
        //
        private void OnControlLeave(object sender, EventArgs e) 
        {
            if (sender == activeControl) 
            {
                activeControl = null;
                Invalidate();
            }
        }

        //
        // <doc>
        // <desc>
        //      This is the extended property for the HelpText property.
        // </desc>
        // </doc>
        //
        public void SetHelpText(Control control, string value) 
        {
            if (value == null) 
            {
                value = string.Empty;
            }

            if (value.Length == 0) 
            {
                helpTexts.Remove(control);

                control.Enter -= new EventHandler(OnControlEnter);
                control.Leave -= new EventHandler(OnControlLeave);
            }
            else 
            {
                helpTexts[control] = value;

                control.Enter += new EventHandler(OnControlEnter);
                control.Leave += new EventHandler(OnControlLeave);
            }

            if (control == activeControl) 
            {
                Invalidate();
            }
        }

        //
        // <doc>
        // <desc>
        //      Overrides Control.OnPaint.  Here we draw our
        //      label.
        // </desc>
        // </doc>
        //
        protected override void OnPaint(PaintEventArgs pe) 
        {

            // Let the base draw.  This will cover our back
            // color and set any image that the user may have
            // provided.
            //
            base.OnPaint(pe);

            // Draw a rectangle around our control.
            //
            Rectangle rect = ClientRectangle;

            Pen borderPen = new Pen(ForeColor);
            pe.Graphics.DrawRectangle(borderPen, rect);
            borderPen.Dispose();

            // Finally, draw the text over the top of the
            // rectangle.
            //
            if (activeControl != null) 
            {
                string text = (string)helpTexts[activeControl];
                if (text != null && text.Length > 0) 
                {
                    rect.Inflate(-2, -2);
                    Brush brush = new SolidBrush(ForeColor);
                    pe.Graphics.DrawString(text, Font, brush, rect);
                    brush.Dispose();
                }
            }
        }

        // <doc>
        // <desc>
        //     Returns true if the backColor should be persisted in code gen.  We
        //      override this because we change the default back color.
        // </desc>
        // <retvalue>
        //     true if the backColor should be persisted.
        // </retvalue>
        // </doc>
        //
        public bool ShouldSerializeBackColor() 
        {
            return(!BackColor.Equals(SystemColors.Info));
        }

        // <doc>
        // <desc>
        //     Returns true if the foreColor should be persisted in code gen.  We
        //      override this because we change the default foreground color.
        // </desc>
        // <retvalue>
        //     true if the foreColor should be persisted.
        // </retvalue>
        // </doc>
        //
        public bool ShouldSerializeForeColor() 
        {
            return(!ForeColor.Equals(SystemColors.InfoText));
        }

        //
        // <doc>
        // <desc>
        //      This is a designer for the HelpLabel.  This designer provides
        //      design time feedback for the label.  The help label responds
        //      to changes in the active control, but these events do not
        //      occur at design time.  In order to provide some usable feedback
        //      that the control is working the right way, this designer listens
        //      to selection change events and uses those events to trigger active
        //      control changes.
        // </desc>
        // </doc>
        //
        [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
        public class HelpLabelDesigner : System.Windows.Forms.Design.ControlDesigner 
        {

            private bool trackSelection = true;

            /// <summary>
            /// This property is added to the control's set of properties in the method
            /// PreFilterProperties below.  Note that on designers, properties that are
            /// explictly declared by TypeDescriptor.CreateProperty can be declared as
            /// private on the designer.  This helps to keep the designer's publi
            /// object model clean.
            /// </summary>
            [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
            private bool TrackSelection
            {
                get
                {
                    return trackSelection;
                }
                set
                {
                    trackSelection = value;
                    if (trackSelection)
                    {
                        ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
                        if (ss != null)
                        {
                            UpdateHelpLabelSelection(ss);
                        }
                    }
                    else
                    {
                        HelpLabel helpLabel = (HelpLabel)Control;
                        if (helpLabel.activeControl != null)
                        {
                            helpLabel.activeControl = null;
                            helpLabel.Invalidate();
                        }
                    }
                }
            }

            public override DesignerVerbCollection Verbs
            {
                get
                {
                    DesignerVerb[] verbs = new DesignerVerb[] {
                                                                  new DesignerVerb("Sample Verb", new EventHandler(OnSampleVerb))
                                                              };
                    return new DesignerVerbCollection(verbs);
                }
            }

            //
            // <doc>
            // <desc>
            //      Overrides Dispose.  Here we remove our handler for the selection changed
            //      event.  With designers, it is critical that they clean up any events they
            //      have attached.  Otherwise, during the course of an editing session many
            //      designers may get created and never destroyed.
            // </desc>
            // </doc>
            //
            protected override void Dispose(bool disposing) 
            {
                if (disposing) 
                {
                    ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
                    if (ss != null) 
                    {
                        ss.SelectionChanged -= new EventHandler(OnSelectionChanged);
                    }
                }

                base.Dispose(disposing);
            }

            //
            // <doc>
            // <desc>
            //       Overrides initialize.  Here we add an event handler to the selection service.
            //      Notice that we are very careful not to assume that the selection service is
            //      available.  It is entirely optional that a service is available and you should
            //      always degrade gracefully if a service could not be found.
            // </desc>
            // </doc>
            //
            public override void Initialize(IComponent component) 
            {
                base.Initialize(component);

                ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
                if (ss != null) 
                {
                    ss.SelectionChanged += new EventHandler(OnSelectionChanged);
                }
            }

            private void OnSampleVerb(object sender, EventArgs e)
            {
                MessageBox.Show("You have just invoked a sample verb.  Normally, this would do something interesting.");
            }

            //
            // <doc>
            // <desc>
            //      Our handler for the selection change event.  Here we update the active control within
            //      the help label.
            // </desc>
            // </doc>
            //
            private void OnSelectionChanged(object sender, EventArgs e) 
            {
                if (trackSelection)
                {
                    ISelectionService ss = (ISelectionService)sender;
                    UpdateHelpLabelSelection(ss);
                }
            }

            protected override void PreFilterProperties(IDictionary properties)
            {
                // Always call base first in PreFilter* methods, and last in PostFilter*
                // methods.
                base.PreFilterProperties(properties);

                // We add a design-time property called "TrackSelection" that is used to track
                // the active selection.  If the user sets this to true (the default), then
                // we will listen to selection change events and update the control's active
                // control to point to the current primary selection.
                properties["TrackSelection"] = TypeDescriptor.CreateProperty(
                    this.GetType(),        // the type this property is defined on
                    "TrackSelection",    // the name of the property
                    typeof(bool),        // the type of the property
                    new Attribute[] {CategoryAttribute.Design});    // attributes
            }

            /// <summary>
            /// This is a helper method that, given a selection service, will update the active control
            /// of our help label with the currently active selection.
            /// </summary>
            /// <param name="ss"></param>
            private void UpdateHelpLabelSelection(ISelectionService ss)
            {
                Control c = ss.PrimarySelection as Control;
                HelpLabel helpLabel = (HelpLabel)Control;
                if (c != null)
                {
                    helpLabel.activeControl = c;
                    helpLabel.Invalidate();
                }
                else
                {
                    if (helpLabel.activeControl != null)
                    {
                        helpLabel.activeControl = null;
                        helpLabel.Invalidate();
                    }
                }
            }
        }
    }
}

Imports System
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms


Public Class HostApp
   Inherits System.Windows.Forms.Form
    ' <summary>
    '    Required designer variable.
    ' </summary>
   Private components As System.ComponentModel.Container
   Private label1 As System.Windows.Forms.Label
   Private textBox1 As System.Windows.Forms.TextBox
   Private button1 As System.Windows.Forms.Button
    Private helpLabel1 As Microsoft.Samples.WinForms.Vb.HelpLabel.HelpLabel


   Public Sub New()
      '
      ' Required for Windows Form Designer support
      '
      InitializeComponent()
    End Sub


    ' <summary>
    '    Required method for Designer support - do not modify
    '    the contents of this method with the code editor.
    ' </summary>
    Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container
        Me.label1 = New System.Windows.Forms.Label
        Me.button1 = New System.Windows.Forms.Button
        Me.textBox1 = New System.Windows.Forms.TextBox
        Me.helpLabel1 = New Microsoft.Samples.WinForms.Vb.HelpLabel.HelpLabel

        label1.Location = New System.Drawing.Point(16, 16)
        label1.Text = "Name:"
        label1.Size = New System.Drawing.Size(56, 24)
        label1.TabIndex = 3

        helpLabel1.Dock = System.Windows.Forms.DockStyle.Bottom
        helpLabel1.Size = New System.Drawing.Size(448, 40)
        helpLabel1.TabIndex = 0
        helpLabel1.Location = New System.Drawing.Point(0, 117)

        button1.Anchor = AnchorStyles.Right Or AnchorStyles.Bottom
        button1.Size = New System.Drawing.Size(104, 40)
        button1.TabIndex = 1
        helpLabel1.SetHelpText(button1, "This is the Save Button. Press the Save Button to save your work.")
        button1.Text = "&Save"
        button1.Location = New System.Drawing.Point(336, 56)

        Me.Text = "Control Example"
        Me.ClientSize = New System.Drawing.Size(448, 157)

        textBox1.Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top
        textBox1.Location = New System.Drawing.Point(80, 16)
        textBox1.Text = "<Name>"
        helpLabel1.SetHelpText(textBox1, "This is the name field. Please enter your name here.")
        textBox1.TabIndex = 2
        textBox1.Size = New System.Drawing.Size(360, 20)

        Me.Controls.Add(label1)
        Me.Controls.Add(textBox1)
        Me.Controls.Add(button1)
        Me.Controls.Add(helpLabel1)
    End Sub



    ' <summary>
    ' The main entry point for the application.
    ' </summary>
    <STAThread()> _
              Public Shared Sub Main(ByVal args() As String)
        Application.Run(New HostApp)
    End Sub
End Class
namespace Microsoft.Samples.WinForms.Cs.HostApp 
{
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Windows.Forms;
    using Microsoft.Samples.WinForms.Cs.HelpLabel;

    public class HostApp : System.Windows.Forms.Form 
    {
        /// <summary>
        ///    Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Button button1;
        private Microsoft.Samples.WinForms.Cs.HelpLabel.HelpLabel helpLabel1;

        public HostApp() 
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

        }

        /// <summary>
        ///    Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing) 
        {
            if (disposing) 
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        /// <summary>
        ///    Required method for Designer support - do not modify
        ///    the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent() 
        {
            this.components = new System.ComponentModel.Container();
            this.label1 = new System.Windows.Forms.Label();
            this.button1 = new System.Windows.Forms.Button();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.helpLabel1 = new Microsoft.Samples.WinForms.Cs.HelpLabel.HelpLabel();

            label1.Location = new System.Drawing.Point(16, 16);
            label1.Text = "Name:";
            label1.Size = new System.Drawing.Size(56, 24);
            label1.TabIndex = 3;

            helpLabel1.Dock = System.Windows.Forms.DockStyle.Bottom;
            helpLabel1.Size = new System.Drawing.Size(448, 40);
            helpLabel1.TabIndex = 0;
            helpLabel1.Location = new System.Drawing.Point(0, 117);

            button1.Anchor = AnchorStyles.Right | AnchorStyles.Bottom;
            button1.Size = new System.Drawing.Size(104, 40);
            button1.TabIndex = 1;
            helpLabel1.SetHelpText(button1, "This is the Save Button. Press the Save Button to save your work.");
            button1.Text = "&Save";
            button1.Location = new System.Drawing.Point(336, 56);

            this.Text = "Control Example";
            this.ClientSize = new System.Drawing.Size(448, 157);

            textBox1.Anchor = AnchorStyles.Left| AnchorStyles.Right | AnchorStyles.Top;
            textBox1.Location = new System.Drawing.Point(80, 16);
            textBox1.Text = "<Name>";
            helpLabel1.SetHelpText(textBox1, "This is the name field. Please enter your name here.");
            textBox1.TabIndex = 2;
            textBox1.Size = new System.Drawing.Size(360, 20);

            this.Controls.Add(label1);
            this.Controls.Add(textBox1);
            this.Controls.Add(button1);
            this.Controls.Add(helpLabel1);
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        public static void Main(string[] args) 
        {
            Application.Run(new HostApp());
        }

    }
}

참고 항목

작업

방법: Extender 공급자 구현

참조

IExtenderProvider

개념

방법: 컨트롤에 대한 디자이너 구현