Compartilhar via


Como implementar um provedor de extensor HelpLabel

Um provedor do extensor é um componente que fornece propriedades para outros componentes. Por exemplo, o ToolTip o controle é implementado como um provedor extender. Quando você adiciona um ToolTip o controle para um Form, todos os outros controles do Form ter um ToolTip propriedade adicionada à sua lista de propriedades.

O exemplo a seguir demonstra como criar um provedor extender, criando o HelpLabel controle. Ele mostra a implementação da CanExtend método e a HelpText propriedade. O CanExtend método é usado pelo Windows Forms Designer para determinar se deve estender essa propriedade para um determinado controle. O HelpLabel controle estende o HelpText propriedade para uso com os controles em um formulário. O texto de ajuda para um controle é exibido em um painel, quando o controle tem foco.

O exemplo inclui um designer aninhado que é descrito em Como implementar um designer para um controle.

O exemplo demonstra os seguintes itens:

  • O provedor do extensor HelpLabel implementa IExtenderProvider.

  • O HelpLabel controle usa o ProvidePropertyAttribute para especificar o nome da propriedade fornecida, bem como o tipo de componentes que pode receber a propriedade.

  • HelpLabelé um controle Windows Forms em si e, portanto, deriva de Control.

  • O CanExtend método retorna true para qualquer controle, exceto HelpLabel, porque não é significativo para estender uma propriedade em si.

  • HelpLabeltem um método denominado GetHelpText que obtém a propriedade que HelpLabel disponibiliza para outros controles. O SetHelpText método define o valor da propriedade.

    Dica

    A propriedade estendida é fornecida pelo GetHelpText e SetHelpText métodos, e HelpLabel não expõe uma propriedade chamada HelpText.

Exemplo

O HostApp classe usa a HelpLabel controle em um formulário.

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());
        }

    }
}

Consulte também

Tarefas

Como implementar um provedor de extensor

Referência

IExtenderProvider

Conceitos

Como implementar um designer para um controle