Share via


How to: Create a Windows Forms Control That Shows Progress

The following code example shows a custom control called FlashTrackBar that can be used to show the user the level or the progress of an application. It uses a gradient to visually represent progress.

The FlashTrackBar control illustrates the following concepts:

  • Defining custom properties.

  • Defining custom events. (FlashTrackBar defines the ValueChanged event.)

  • Overriding the OnPaint method to provide logic to draw the control.

  • Computing the area available for drawing the control by using its ClientRectangle property. FlashTrackBar does this in its OptimizedInvalidate method.

  • Implementing serialization or persistence for a property when it is changed in the Windows Forms Designer. FlashTrackBar defines the ShouldSerializeStartColor and ShouldSerializeEndColor methods for serializing its StartColor and EndColor properties.

The following table shows the custom properties defined by FlashTrackBar.

Property

Description

AllowUserEdit

Indicates whether the user can change the value of the flash track bar by clicking and dragging it.

EndColor

Specifies the ending color of the track bar.

DarkenBy

Specifies how much to darken the background with respect to the foreground gradient.

Max

Specifies the maximum value of the track bar.

Min

Specifies the minimum value of the track bar.

StartColor

Specifies the starting color of the gradient.

ShowPercentage

Indicates whether to display a percentage over the gradient.

ShowValue

Indicates whether to display the current value over the gradient.

ShowGradient

Indicates whether the track bar should display a color gradient showing the current value.

  • Value

Specifies the current value of the track bar.

The following table shows additional members defined by FlashTrackBar: the property-changed event and the method that raises the event.

Member

Description

ValueChanged

The event that is raised when the Value property of the track bar changes.

OnValueChanged

The method that raises the ValueChanged event.

Note

FlashTrackBar uses the EventArgs class for event data and EventHandler for the event delegate.

To handle the corresponding EventName events, FlashTrackBar overrides the following methods that it inherits from System.Windows.Forms.Control:

To handle the corresponding property-changed events, FlashTrackBar overrides the following methods that it inherits from System.Windows.Forms.Control:

Example

The FlashTrackBar control defines two UI type editors, FlashTrackBarValueEditor and FlashTrackBarDarkenByEditor, which are shown in the following code listings. The HostApp class uses the FlashTrackBar control on a Windows Form.

Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Design
Imports System.Windows.Forms
Imports System.Diagnostics

Namespace Microsoft.Samples.WinForms.VB.FlashTrackBar

    <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
    Public Class FlashTrackBar
        Inherits System.Windows.Forms.Control

        Private LeftRightBorder As Integer = 10
        Private myValue As Integer = 0
        Private myMin As Integer = 0
        Private myMax As Integer = 100
        Private myShowPercentage As Boolean = False
        Private myShowValue As Boolean = False
        Private myAllowUserEdit As Boolean = True
        Private myShowGradient As Boolean = True
        Private dragValue As Integer = 0
        Private dragging As Boolean = False
        Private myStartColor As Color = Color.Red
        Private myEndColor As Color = Color.LimeGreen
        Private baseBackground As Brush
        Private backgroundDim As Brush
        Private myDarkenBy As Byte = 200

        Public Sub New()

            MyBase.New()

            'This call is required by the Windows Forms Designer.
            InitializeComponent()

            SetStyle(ControlStyles.Opaque, True)
            SetStyle(ControlStyles.ResizeRedraw, True)
            Debug.Assert(GetStyle(ControlStyles.ResizeRedraw), "Should be redraw!")
        End Sub

        'Form overrides dispose to clean up the component list.
        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


#Region " Windows Form Designer generated code "

        'Required by the Windows Form Designer
        Private components As System.ComponentModel.Container

        'NOTE: The following procedure is required by the Windows Form Designer
        'It can be modified using the Windows Form Designer.
        'Do not modify it using the code editor.
        Private Sub InitializeComponent()
            Me.components = New System.ComponentModel.Container()
            Me.ForeColor = System.Drawing.Color.White
            Me.BackColor = System.Drawing.Color.Black
            Me.Size = New System.Drawing.Size(100, 23)
            Me.Text = "FlashTrackBar"
        End Sub

#End Region


        <Category("Flash"), DefaultValue(True)> Public Property AllowUserEdit() As Boolean
            Get
                Return myAllowUserEdit
            End Get

            Set(ByVal Value As Boolean)
                If (Value <> myAllowUserEdit) Then
                    myAllowUserEdit = Value
                    If Not (myAllowUserEdit) Then
                        Capture = False
                        dragging = False
                    End If
                End If
            End Set

        End Property


        <Category("Flash")> Public Property EndColor() As Color
            Get
                Return myEndColor
            End Get

            Set(ByVal Value As Color)
                myEndColor = Value
                If ((baseBackground IsNot Nothing) And myShowGradient) Then
                    baseBackground.Dispose()
                    baseBackground = Nothing
                End If
                Invalidate()
            End Set
        End Property


        Public Function ShouldPersistEndColor() As Boolean
            Return Not (myEndColor.Equals(Color.LimeGreen))
        End Function


        <Category("Flash"), _
            Editor(GetType(FlashTrackBarDarkenByEditor), GetType(UITypeEditor)), _
            DefaultValue(200)> _
        Public Property DarkenBy() As Byte
            Get
                Return myDarkenBy
            End Get
            Set(ByVal Value As Byte)
                If (Value <> myDarkenBy) Then
                    myDarkenBy = Value
                    If (backgroundDim IsNot Nothing) Then
                        backgroundDim.Dispose()
                        backgroundDim = Nothing
                    End If
                    OptimizedInvalidate(Value, Max)
                End If
            End Set
        End Property

        <Category("Flash"), DefaultValue(100)> _
        Public Property Max() As Integer
            Get
                Return myMax
            End Get
            Set(ByVal Value As Integer)
                If (myMax <> Value) Then
                    myMax = Value
                    Invalidate()
                End If
            End Set
        End Property


        <Category("Flash"), DefaultValue(0)> _
        Public Property Min() As Integer
            Get
                Return myMin
            End Get
            Set(ByVal Value As Integer)
                If (Min <> Value) Then
                    Min = Value
                    Invalidate()
                End If
            End Set
        End Property


        <Category("Flash")> Public Property StartColor() As Color
            Get
                Return myStartColor
            End Get
            Set(ByVal Value As Color)
                myStartColor = Value
                If ((baseBackground IsNot Nothing) And myShowGradient) Then
                    baseBackground.Dispose()
                    baseBackground = Nothing
                End If
                Invalidate()
            End Set
        End Property

        Public Function ShouldPersistStartColor() As Boolean
            Return Not (StartColor.Equals(Color.Red))
        End Function


        <Category("Flash"), _
            RefreshProperties(RefreshProperties.Repaint), _
            DefaultValue(False)> _
        Public Property ShowPercentage() As Boolean
            Get
                Return myShowPercentage
            End Get
            Set(ByVal Value As Boolean)
                If (Value <> myShowPercentage) Then
                    myShowPercentage = Value
                    If (myShowPercentage) Then
                        myShowValue = False
                    End If
                    Invalidate()
                End If
            End Set
        End Property


        <Category("Flash"), _
            RefreshProperties(RefreshProperties.Repaint), _
            DefaultValue(False)> _
        Public Property ShowValue() As Boolean
            Get
                Return myShowValue
            End Get
            Set(ByVal Value As Boolean)
                If (Value <> myShowValue) Then
                    myShowValue = Value
                    If (myShowValue) Then
                        myShowPercentage = False
                    End If
                    Invalidate()
                End If
            End Set
        End Property



        <Category("Flash"), DefaultValue(True)> _
        Public Property ShowGradient() As Boolean
            Get
                Return myShowGradient
            End Get
            Set(ByVal Value As Boolean)
                If (Value <> myShowGradient) Then
                    myShowGradient = Value
                    If (baseBackground IsNot Nothing) Then
                        baseBackground.Dispose()
                        baseBackground = Nothing
                    End If
                    Invalidate()
                End If
            End Set
        End Property

        <Category("Flash"), _
         Editor(GetType(FlashTrackBarValueEditor), GetType(UITypeEditor)), _
         DefaultValue(0)> _
        Public Property Value() As Integer
            Get
                If (dragging) Then
                    Return dragValue
                End If
                Return myValue
            End Get
            Set(ByVal Value As Integer)
                If (Value <> myValue) Then
                    Dim old As Integer = myValue
                    myValue = Value
                    OnValueChanged(EventArgs.Empty)
                    OptimizedInvalidate(old, myValue)
                End If
            End Set
        End Property

        ' ValueChanged Event

        <Description("Raised when the Value displayed changes")> _
        Public Event ValueChanged(ByVal sender As Object, ByVal ev As EventArgs) 'As EventHandler


        Private Sub OptimizedInvalidate(ByVal oldValue As Integer, ByVal newValue As Integer)
            Dim client As Rectangle = ClientRectangle

            Dim oldPercentValue As Single = CSng(oldValue) / (CSng(Max) - CSng(Min))
            Dim oldNonDimLength As Integer = CInt(oldPercentValue * CSng(client.Width))

            Dim newPercentValue As Single = (CSng(newValue) / (CSng(Max) - CSng(Min)))
            Dim newNonDimLength As Integer = CInt(newPercentValue * CSng(client.Width))

            Dim lmin As Integer = Math.Min(oldNonDimLength, newNonDimLength)
            Dim lmax As Integer = Math.Max(oldNonDimLength, newNonDimLength)

            Dim invalid As Rectangle = New Rectangle( _
                client.X + lmin, _
                client.Y, _
                lmax - lmin, _
                client.Height)

            Invalidate(invalid)

            Dim oldToDisplay As String
            Dim newToDisplay As String

            If (ShowPercentage) Then
                oldToDisplay = Convert.ToString(CInt(oldPercentValue * 100F)) + "%"
                newToDisplay = Convert.ToString(CInt(newPercentValue * 100F)) + "%"
            ElseIf (ShowValue) Then
                oldToDisplay = Convert.ToString(oldValue)
                newToDisplay = Convert.ToString(newValue)
            Else
                oldToDisplay = Nothing
                newToDisplay = Nothing
            End If

            If (oldToDisplay <> Nothing And newToDisplay <> Nothing) Then
                Dim g As Graphics = CreateGraphics()
                Dim oldFontSize As SizeF = g.MeasureString(oldToDisplay, Font)
                Dim newFontSize As SizeF = g.MeasureString(newToDisplay, Font)
                Dim oldFontRectF As RectangleF = New RectangleF(New PointF(0, 0), oldFontSize)
                Dim newFontRectF As RectangleF = New RectangleF(New PointF(0, 0), newFontSize)
                oldFontRectF.X = (client.Width - oldFontRectF.Width) / 2
                oldFontRectF.Y = (client.Height - oldFontRectF.Height) / 2
                newFontRectF.X = (client.Width - newFontRectF.Width) / 2
                newFontRectF.Y = (client.Height - newFontRectF.Height) / 2

                Dim oldFontRect As Rectangle = New Rectangle(CInt(oldFontRectF.X), CInt(oldFontRectF.Y), CInt(oldFontRectF.Width), CInt(oldFontRectF.Height))
                Dim newFontRect As Rectangle = New Rectangle(CInt(newFontRectF.X), CInt(newFontRectF.Y), CInt(newFontRectF.Width), CInt(newFontRectF.Height))

                Invalidate(oldFontRect)
                Invalidate(newFontRect)
            End If
        End Sub


        Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
            MyBase.OnMouseDown(e)
            If Not (myAllowUserEdit) Then
                Return
            End If
            Capture = True
            dragging = True
            SetDragValue(New Point(e.X, e.Y))
        End Sub

        Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
            MyBase.OnMouseMove(e)
            If (Not myAllowUserEdit Or Not dragging) Then
                Return
            End If
            SetDragValue(New Point(e.X, e.Y))
        End Sub

        Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
            MyBase.OnMouseUp(e)
            If (Not myAllowUserEdit Or Not dragging) Then
                Return
            End If
            Capture = False
            dragging = False
            Value = dragValue
            OnValueChanged(EventArgs.Empty)
        End Sub

        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

            MyBase.OnPaint(e)

            If (baseBackground Is Nothing) Then

                If (myShowGradient) Then
                    baseBackground = New LinearGradientBrush(New Point(0, 0), _
                                                             New Point(ClientSize.Width, 0), _
                                                             StartColor, _
                                                             EndColor)
                ElseIf (BackgroundImage IsNot Nothing) Then
                    baseBackground = New TextureBrush(BackgroundImage)
                Else
                    baseBackground = New SolidBrush(BackColor)
                End If

            End If

            If (backgroundDim Is Nothing) Then
                backgroundDim = New SolidBrush(Color.FromArgb(DarkenBy, Color.Black))
            End If

            Dim toDim As Rectangle = ClientRectangle
            Dim percentValue As Single = (CSng(Value) / (CSng(Max) - CSng(Min)))
            Dim nonDimLength As Integer = CInt(percentValue * CSng(toDim.Width))
            toDim.X = toDim.X + nonDimLength
            toDim.Width = toDim.Width - nonDimLength

            Dim ltext As String = Me.Text
            Dim toDisplay As String
            Dim textRect As RectangleF = New RectangleF(0, 0, 0, 0)

            If (ShowPercentage Or ShowValue Or ltext.Length > 0) Then

                If (ShowPercentage) Then
                    toDisplay = Convert.ToString(CInt(percentValue * 100F)) + "%"
                ElseIf (ShowValue) Then
                    toDisplay = Convert.ToString(Value)
                Else
                    toDisplay = ltext
                End If

                Dim textSize As SizeF = e.Graphics.MeasureString(toDisplay, Font)
                textRect.Width = textSize.Width
                textRect.Height = textSize.Height
                textRect.X = (ClientRectangle.Width - textRect.Width) / 2
                textRect.Y = (ClientRectangle.Height - textRect.Height) / 2
            End If

            e.Graphics.FillRectangle(baseBackground, ClientRectangle)
            e.Graphics.FillRectangle(backgroundDim, toDim)
            e.Graphics.Flush()
            If (toDisplay <> Nothing And toDisplay.Length > 0) Then
                e.Graphics.DrawString(toDisplay, Font, New SolidBrush(ForeColor), textRect)
            End If
        End Sub

        Protected Overrides Sub OnTextChanged(ByVal E As EventArgs)
            MyBase.OnTextChanged(E)
            Invalidate()
        End Sub

        Protected Overrides Sub OnBackColorChanged(ByVal E As EventArgs)
            MyBase.OnBackColorChanged(E)
            If (baseBackground IsNot Nothing) And Not ShowGradient Then
                baseBackground.Dispose()
                baseBackground = Nothing
            End If
        End Sub

        Protected Overrides Sub OnBackgroundImageChanged(ByVal E As EventArgs)
            MyBase.OnTextChanged(E)
            If (baseBackground IsNot Nothing) And Not ShowGradient Then
                baseBackground.Dispose()
                baseBackground = Nothing
            End If
        End Sub

        Protected Overrides Sub OnResize(ByVal e As EventArgs)
            MyBase.OnResize(e)
            If (baseBackground IsNot Nothing) Then
                baseBackground.Dispose()
                baseBackground = Nothing
            End If
        End Sub

        Protected Overridable Sub OnValueChanged(ByVal e As EventArgs)
            RaiseEvent ValueChanged(Me, e)
        End Sub

        Private Sub SetDragValue(ByVal mouseLocation As Point)

            Dim client As Rectangle = ClientRectangle

            If (client.Contains(mouseLocation)) Then

                Dim percentage As Single = CSng(mouseLocation.X) / CSng(ClientRectangle.Width)
                Dim newDragValue As Integer = CInt(percentage * CSng(Max - Min))

                If (newDragValue <> dragValue) Then
                    Dim old As Integer = dragValue
                    dragValue = newDragValue
                    OptimizedInvalidate(old, dragValue)
                End If

            Else

                If (client.Y <= mouseLocation.Y And mouseLocation.Y <= client.Y + client.Height) Then
                    If (mouseLocation.X <= client.X And mouseLocation.X > client.X - LeftRightBorder) Then
                        Dim newDragValue As Integer = Min
                        If (newDragValue <> dragValue) Then
                            Dim old As Integer = dragValue
                            dragValue = newDragValue
                            OptimizedInvalidate(old, dragValue)
                        End If

                    ElseIf (mouseLocation.X >= client.X + client.Width And mouseLocation.X < client.X + client.Width + LeftRightBorder) Then
                        Dim newDragValue As Integer = Max
                        If (newDragValue <> dragValue) Then
                            Dim old As Integer = dragValue
                            dragValue = newDragValue
                            OptimizedInvalidate(old, dragValue)
                        End If
                    End If

                Else
                    If (dragValue <> Value) Then
                        Dim old As Integer = dragValue
                        dragValue = Value
                        OptimizedInvalidate(old, dragValue)
                    End If

                End If

            End If

        End Sub

    End Class

End Namespace
namespace Microsoft.Samples.WinForms.Cs.FlashTrackBar {
    using System;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Drawing.Design;
    using System.Windows.Forms;
    using System.Diagnostics;

    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
    public class FlashTrackBar : System.Windows.Forms.Control {
        /// <summary>
        ///    Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components;

        private const int LeftRightBorder = 10;
        private int value = 0;
        private int min = 0;
        private int max = 100;
        private bool showPercentage = false;
        private bool showValue = false;
        private bool allowUserEdit = true;
        private bool showGradient = true;
        private int dragValue = 0;
        private bool dragging = false;
        private Color startColor = Color.Red;
        private Color endColor = Color.LimeGreen;
        private EventHandler onValueChanged;
        private Brush baseBackground = null;
        private Brush backgroundDim = null;
        private byte darkenBy = 200;


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

            SetStyle(ControlStyles.Opaque, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            Debug.Assert(GetStyle(ControlStyles.ResizeRedraw), "Should be redraw!");
        }

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

        /// <summary>
        ///    Required method for Designer support - do not modify
        ///    the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent () {
            this.components = new System.ComponentModel.Container ();
            this.ForeColor = System.Drawing.Color.White;
            this.BackColor = System.Drawing.Color.Black;
            this.Size = new System.Drawing.Size(100, 23);
            this.Text = "FlashTrackBar";
        }

        [
            Category("Flash"),
            DefaultValue(true)
        ]
        public bool AllowUserEdit {
            get {
                return allowUserEdit;
            }
            set {
                if (value != allowUserEdit) {
                    allowUserEdit = value;
                    if (!allowUserEdit) {
                        Capture = false;
                        dragging = false;
                    }
                }
            }
        }

        [
            Category("Flash")
        ]
        public Color EndColor {
            get {
                return endColor;
            }
            set {
                endColor = value;
                if (baseBackground != null && showGradient) {
                    baseBackground.Dispose();
                    baseBackground = null;
                }
                Invalidate();
            }
        }

        public bool ShouldSerializeEndColor() {
            return !(endColor == Color.LimeGreen);
        }


        [
            Category("Flash"),
            Editor(typeof(FlashTrackBarDarkenByEditor), typeof(UITypeEditor)),
            DefaultValue((byte)200)
        ]
        public byte DarkenBy {
            get {
                return darkenBy;
            }
            set {
                if (value != darkenBy) {
                    darkenBy = value;
                    if (backgroundDim != null) {
                        backgroundDim.Dispose();
                        backgroundDim = null;
                    }
                    OptimizedInvalidate(Value, max);
                }
            }
        }

        [
            Category("Flash"),
            DefaultValue(100)
        ]
        public int Max {
            get {
                return max;
            }
            set {
                if (max != value) {
                    max = value;
                    Invalidate();
                }
            }
        }

        [
            Category("Flash"),
            DefaultValue(0)
        ]
        public int Min {
            get {
                return min;
            }
            set {
                if (min != value) {
                    min = value;
                    Invalidate();
                }
            }
        }

        [
            Category("Flash")
        ]
        public Color StartColor {
            get {
                return startColor;
            }
            set {
                startColor = value;
                if (baseBackground != null && showGradient) {
                    baseBackground.Dispose();
                    baseBackground = null;
                }
                Invalidate();
            }
        }

        public bool ShouldSerializeStartColor() {
            return !(startColor == Color.Red);
        }



        [
            Category("Flash"),
            RefreshProperties(RefreshProperties.Repaint),
            DefaultValue(false)
        ]
        public bool ShowPercentage {
            get {
                return showPercentage;
            }
            set {
                if (value != showPercentage) {
                    showPercentage = value;
                    if (showPercentage) {
                        showValue = false;
                    }
                    Invalidate();
                }
            }
        }

        [
            Category("Flash"),
            RefreshProperties(RefreshProperties.Repaint),
            DefaultValue(false)
        ]
        public bool ShowValue {
            get {
                return showValue;
            }
            set {
                if (value != showValue) {
                    showValue = value;
                    if (showValue) {
                        showPercentage = false;
                    }
                    Invalidate();
                }
            }
        }

        [
            Category("Flash"),
            DefaultValue(true)
        ]
        public bool ShowGradient {
            get {
                return showGradient;
            }
            set {
                if (value != showGradient) {
                    showGradient = value;
                    if (baseBackground != null) {
                        baseBackground.Dispose();
                        baseBackground = null;
                    }
                    Invalidate();
                }
            }
        }

        [
            Category("Flash"),
            Editor(typeof(FlashTrackBarValueEditor), typeof(UITypeEditor)),
            DefaultValue(0)
        ]
        public int Value {
            get {
                if (dragging) {
                    return dragValue;
                }
                return value;
            }
            set {
                if (value != this.value) {
                    int old = this.value;
                    this.value = value;
                    OnValueChanged(EventArgs.Empty);
                    OptimizedInvalidate(old, this.value);
                }
            }
        }

        // ValueChanged Event
        [Description("Raised when the Value displayed changes")]
        public event EventHandler ValueChanged {
            add {
                onValueChanged += value;
            }
            remove {
                onValueChanged -= value;
            }
        }

        private void OptimizedInvalidate(int oldValue, int newValue) {
            Rectangle client = ClientRectangle;

            float oldPercentValue = ((float)oldValue / ((float)Max - (float)Min));
            int oldNonDimLength = (int)(oldPercentValue * (float)client.Width);

            float newPercentValue = ((float)newValue / ((float)Max - (float)Min));
            int newNonDimLength = (int)(newPercentValue * (float)client.Width);

            int min = Math.Min(oldNonDimLength, newNonDimLength);
            int max = Math.Max(oldNonDimLength, newNonDimLength);

            Rectangle invalid = new Rectangle(
                client.X + min, 
                client.Y, 
                max - min, 
                client.Height);

            Invalidate(invalid);

            string oldToDisplay;
            string newToDisplay;

            if (ShowPercentage) {
                oldToDisplay = Convert.ToString((int)(oldPercentValue * 100f)) + "%";
                newToDisplay = Convert.ToString((int)(newPercentValue * 100f)) + "%";
            }
            else if (ShowValue) {
                oldToDisplay = Convert.ToString(oldValue);
                newToDisplay = Convert.ToString(newValue);
            }
            else {
                oldToDisplay = null;
                newToDisplay = null;
            }

            if (oldToDisplay != null && newToDisplay != null) {
                Graphics g = CreateGraphics();
                SizeF oldFontSize = g.MeasureString(oldToDisplay, Font);
                SizeF newFontSize = g.MeasureString(newToDisplay, Font);
                RectangleF oldFontRect = new RectangleF(new PointF(0, 0), oldFontSize);
                RectangleF newFontRect = new RectangleF(new PointF(0, 0), newFontSize);
                oldFontRect.X = (client.Width - oldFontRect.Width) / 2;
                oldFontRect.Y = (client.Height - oldFontRect.Height) / 2;
                newFontRect.X = (client.Width - newFontRect.Width) / 2;
                newFontRect.Y = (client.Height - newFontRect.Height) / 2;

                Invalidate(new Rectangle((int)oldFontRect.X, (int)oldFontRect.Y, (int)oldFontRect.Width, (int)oldFontRect.Height));
                Invalidate(new Rectangle((int)newFontRect.X, (int)newFontRect.Y, (int)newFontRect.Width, (int)newFontRect.Height));
            }
        }

        protected override void OnMouseDown(MouseEventArgs e) {
            base.OnMouseDown(e);
            if (!allowUserEdit) {
                return;
            }
            Capture = true;
            dragging = true;
            SetDragValue(new Point(e.X, e.Y));
        }

        protected override void OnMouseMove(MouseEventArgs e) {
            base.OnMouseMove(e);
            if (!allowUserEdit || !dragging) {
                return;
            }
            SetDragValue(new Point(e.X, e.Y));
        }

        protected override void OnMouseUp(MouseEventArgs e) {
            base.OnMouseUp(e);
            if (!allowUserEdit || !dragging) {
                return;
            }
            Capture = false;
            dragging = false;
            value = dragValue;
            OnValueChanged(EventArgs.Empty);
        }

        protected override void OnPaint(PaintEventArgs e) {

            base.OnPaint(e);
            if (baseBackground == null) {
                if (showGradient) {
                    baseBackground = new LinearGradientBrush(new Point(0, 0),
                                                             new Point(ClientSize.Width, 0),
                                                             StartColor,
                                                             EndColor);
                }
                else if (BackgroundImage != null) {
                    baseBackground = new TextureBrush(BackgroundImage);
                }
                else {
                    baseBackground = new SolidBrush(BackColor);
                }
            }

            if (backgroundDim == null) {
                backgroundDim = new SolidBrush(Color.FromArgb(DarkenBy, Color.Black));
            }

            Rectangle toDim = ClientRectangle;
            float percentValue = ((float)Value / ((float)Max - (float)Min));
            int nonDimLength = (int)(percentValue * (float)toDim.Width);
            toDim.X += nonDimLength;
            toDim.Width -= nonDimLength;


            string text = Text;
            string toDisplay = null;
            RectangleF textRect = new RectangleF();

            if (ShowPercentage || ShowValue || text.Length > 0) {

                if (ShowPercentage) {
                    toDisplay = Convert.ToString((int)(percentValue * 100f)) + "%";
                }
                else if (ShowValue) {
                    toDisplay = Convert.ToString(Value);
                }
                else {
                    toDisplay = text;
                }

                SizeF textSize = e.Graphics.MeasureString(toDisplay, Font);
                textRect.Width = textSize.Width;
                textRect.Height = textSize.Height;
                textRect.X = (ClientRectangle.Width - textRect.Width) / 2;
                textRect.Y = (ClientRectangle.Height - textRect.Height) / 2;
            }

            e.Graphics.FillRectangle(baseBackground, ClientRectangle);
            e.Graphics.FillRectangle(backgroundDim, toDim);
            e.Graphics.Flush();
            if (toDisplay != null && toDisplay.Length > 0) {
                e.Graphics.DrawString(toDisplay, Font, new SolidBrush(ForeColor), textRect);
            }
        }

        protected override void OnTextChanged(EventArgs e) {
            base.OnTextChanged(e);
            Invalidate();
        }

        protected override void OnBackColorChanged(EventArgs e) {
            base.OnBackColorChanged(e);
            if ((baseBackground != null) && (!showGradient)) {
                        baseBackground.Dispose();
                        baseBackground = null;
            }
        }

        protected override void OnBackgroundImageChanged(EventArgs e) {
            base.OnTextChanged(e);
            if ((baseBackground != null) && (!showGradient)) {
                        baseBackground.Dispose();
                        baseBackground = null;
            }
        }

        protected override void OnResize(EventArgs e) {
            base.OnResize(e);
            if (baseBackground != null) {
                baseBackground.Dispose();
                baseBackground = null;
            }
        }

        protected virtual void OnValueChanged(EventArgs e) {
            if (onValueChanged != null) {
                onValueChanged.Invoke(this, e);
            }
        }

        private void SetDragValue(Point mouseLocation) {

            Rectangle client = ClientRectangle;

            if (client.Contains(mouseLocation)) {
                float percentage = (float)mouseLocation.X / (float)ClientRectangle.Width;
                int newDragValue = (int)(percentage * (float)(max - min));
                if (newDragValue != dragValue) {
                    int old = dragValue;
                    dragValue = newDragValue;
                    OptimizedInvalidate(old, dragValue);
                }
            }
            else {
                if (client.Y <= mouseLocation.Y && mouseLocation.Y <= client.Y + client.Height) {
                    if (mouseLocation.X <= client.X && mouseLocation.X > client.X - LeftRightBorder) {
                        int newDragValue = min;
                        if (newDragValue != dragValue) {
                            int old = dragValue;
                            dragValue = newDragValue;
                            OptimizedInvalidate(old, dragValue);
                        }
                    }
                    else if (mouseLocation.X >= client.X + client.Width && mouseLocation.X < client.X + client.Width + LeftRightBorder) {
                        int newDragValue = max;
                        if (newDragValue != dragValue) {
                            int old = dragValue;
                            dragValue = newDragValue;
                            OptimizedInvalidate(old, dragValue);
                        }
                    }
                }
                else {
                    if (dragValue != value) {
                        int old = dragValue;
                        dragValue = value;
                        OptimizedInvalidate(old, dragValue);
                    }
                }
            }
        }
    }
}
Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Design
Imports System.Windows.Forms
Imports System.Diagnostics

Namespace Microsoft.Samples.WinForms.VB.FlashTrackBar 

   Public Class FlashTrackBarDarkenByEditor 
        Inherits FlashTrackBarValueEditor 

       Overrides Protected Sub SetEditorProps(editingInstance As FlashTrackBar, editor As FlashTrackBar) 
           MyBase.SetEditorProps(editingInstance, editor)
           editor.Min = 0
           editor.Max = System.Byte.MaxValue
       End Sub

   End Class

End Namespace
namespace Microsoft.Samples.WinForms.Cs.FlashTrackBar {
   using System;
   using System.ComponentModel;
   using System.ComponentModel.Design;
   using System.Diagnostics;
   using System.Drawing;
   using System.Drawing.Drawing2D;
   using System.Drawing.Design;
   using System.Windows.Forms;
   using System.Windows.Forms.ComponentModel;
   using System.Windows.Forms.Design;

   public class FlashTrackBarDarkenByEditor : FlashTrackBarValueEditor {
       protected override void SetEditorProps(FlashTrackBar editingInstance, FlashTrackBar editor) {
           base.SetEditorProps(editingInstance, editor);
           editor.Min = 0;
           editor.Max = byte.MaxValue;
       }
   }
}

Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Design
Imports System.Windows.Forms
Imports System.Diagnostics
Imports System.Windows.Forms.ComponentModel
Imports System.Windows.Forms.Design

Namespace Microsoft.Samples.WinForms.VB.FlashTrackBar

    <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
    Public Class FlashTrackBarValueEditor
        Inherits UITypeEditor

        Private edSvc As IWindowsFormsEditorService


        Overridable Protected Sub SetEditorProps(editingInstance As FlashTrackBar, editor As FlashTrackBar)
            editor.ShowValue = true
            editor.StartColor = Color.Navy
            editor.EndColor = Color.White
            editor.ForeColor = Color.White
            editor.Min = editingInstance.Min
            editor.Max = editingInstance.Max
        End Sub

        Overrides OverLoads Public Function EditValue(context As ITypeDescriptorContext, provider As IServiceProvider, value As object) As Object

            If ((context IsNot Nothing) And (context.Instance IsNot Nothing) And (provider IsNot Nothing)) Then

                edSvc = CType(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)

                If (edSvc IsNot Nothing) Then

                    Dim trackBar As FlashTrackBar = New FlashTrackBar()
                    AddHandler trackBar.ValueChanged, AddressOf Me.ValueChanged
                    SetEditorProps(CType(context.Instance, FlashTrackBar), TrackBar)

                    Dim asInt As Boolean = True

                    If (TypeOf value Is Integer) Then
                        trackBar.Value = CInt(value)
                    ElseIf (TypeOf value Is System.Byte) Then
                        asInt = False
                        trackBar.Value = CType(value, Byte)
                    End If

                    edSvc.DropDownControl(trackBar)

                    If (asInt) Then
                        value = trackBar.Value
                    Else
                        value = CType(trackBar.Value, Byte)
                    End If

                End If

            End If

            Return value

         End Function

        Overrides OverLoads Public Function GetEditStyle(context As ITypeDescriptorContext) As UITypeEditorEditStyle
            If ((context IsNot Nothing) And (context.Instance IsNot Nothing)) Then
                Return UITypeEditorEditStyle.DropDown
            End If
            Return MyBase.GetEditStyle(context)
        End Function

        private Sub ValueChanged(sender As object, e As EventArgs)
            If (edSvc IsNot Nothing) Then
                edSvc.CloseDropDown()
            End If
        End Sub

    End Class

End Namespace
namespace Microsoft.Samples.WinForms.Cs.FlashTrackBar {
    using System;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Drawing.Design;
    using System.Windows.Forms;
    using System.Windows.Forms.ComponentModel;
    using System.Windows.Forms.Design;

    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
    public class FlashTrackBarValueEditor : System.Drawing.Design.UITypeEditor {

        private IWindowsFormsEditorService edSvc = null;

        protected virtual void SetEditorProps(FlashTrackBar editingInstance, FlashTrackBar editor) {
            editor.ShowValue = true;
            editor.StartColor = Color.Navy;
            editor.EndColor = Color.White;
            editor.ForeColor = Color.White;
            editor.Min = editingInstance.Min;
            editor.Max = editingInstance.Max;
        }

        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {

            if (context != null
                && context.Instance != null
                && provider != null) {

                edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

                if (edSvc != null) {
                    FlashTrackBar trackBar = new FlashTrackBar();
                    trackBar.ValueChanged += new EventHandler(this.ValueChanged);
                    SetEditorProps((FlashTrackBar)context.Instance, trackBar);
                    bool asInt = true;
                    if (value is int) {
                        trackBar.Value = (int)value;
                    }
                    else if (value is byte) {
                        asInt = false;
                        trackBar.Value = (byte)value;
                    }
                    edSvc.DropDownControl(trackBar);
                    if (asInt) {
                        value = trackBar.Value;
                    }
                    else {
                        value = (byte)trackBar.Value;
                    }
                }
            }

            return value;
        }

        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
            if (context != null && context.Instance != null) {
                return UITypeEditorEditStyle.DropDown;
            }
            return base.GetEditStyle(context);
        }

        private void ValueChanged(object sender, EventArgs e) {
            if (edSvc != null) {
                edSvc.CloseDropDown();
            }
        }
    }
}

Imports System
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
Imports Microsoft.Samples.WinForms.VB.FlashTrackBar


Namespace Microsoft.Samples.WinForms.VB.HostApp

    Public Class HostApp
        Inherits System.Windows.Forms.Form

        Public Sub New()

            MyBase.New()

            HostApp = Me

            'This call is required by the Windows Forms Designer.
            InitializeComponent()

        End Sub

        'Form overrides dispose to clean up the component list.
        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



#Region " Windows Form Designer generated code "

        'Required by the Windows Form Designer
        Private components As System.ComponentModel.Container
        Private WithEvents flashTrackBar1 As Microsoft.Samples.WinForms.VB.FlashTrackBar.FlashTrackBar

        Private WithEvents HostApp As System.Windows.Forms.Form

        'NOTE: The following procedure is required by the Windows Form Designer
        'It can be modified using the Windows Form Designer.
        'Do not modify it using the code editor.
        Private Sub InitializeComponent()
            Me.components = New System.ComponentModel.Container()
            Me.flashTrackBar1 = New Microsoft.Samples.WinForms.VB.FlashTrackBar.FlashTrackBar()

            flashTrackBar1.Dock = System.Windows.Forms.DockStyle.Fill
            flashTrackBar1.ForeColor = System.Drawing.Color.White
            flashTrackBar1.BackColor = System.Drawing.Color.Black
            flashTrackBar1.Size = New System.Drawing.Size(600, 450)
            flashTrackBar1.TabIndex = 0
            flashTrackBar1.Value = 73
            flashTrackBar1.Text = "Drag the Mouse and say Wow!"

            Me.Text = "Control Example"
            Me.ClientSize = New System.Drawing.Size(528, 325)

            Me.Controls.Add(flashTrackBar1)

        End Sub

#End Region

        'The main entry point for the application
        <STAThread()> Shared Sub Main()
            System.Windows.Forms.Application.Run(New HostApp())
        End Sub

    End Class

End Namespace

namespace Microsoft.Samples.WinForms.Cs.HostApp {
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Windows.Forms;
    using Microsoft.Samples.WinForms.Cs.FlashTrackBar;

    public class HostApp : System.Windows.Forms.Form {
        /// <summary>
        ///    Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components;
        protected internal Microsoft.Samples.WinForms.Cs.FlashTrackBar.FlashTrackBar flashTrackBar1;

        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) {
                if (components != null) {
                    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.flashTrackBar1 = new Microsoft.Samples.WinForms.Cs.FlashTrackBar.FlashTrackBar ();
            this.Text = "Control Example";
            this.ClientSize = new System.Drawing.Size (600, 450);
            flashTrackBar1.BackColor = System.Drawing.Color.Black;
            flashTrackBar1.Dock = System.Windows.Forms.DockStyle.Fill;
            flashTrackBar1.TabIndex = 0;
            flashTrackBar1.ForeColor = System.Drawing.Color.White;
            flashTrackBar1.Text = "Drag the Mouse and say Wow!";
            flashTrackBar1.Value = 73;
            flashTrackBar1.Size = new System.Drawing.Size (600, 450);
            this.Controls.Add (this.flashTrackBar1);
        }

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

    }
}

See Also

Concepts

Windows Forms Control Development Basics

Other Resources

Extending Design-Time Support