|

Introduction
This article presents owner-drawn trackbar control. Component is written entirely from scratch. All painting events are done by code.
It’s got cool, modern look. The best thing is, however, the capability of changing slider’s thumb shape. It is done simply by providing appropriate graphics path.
Background (optional)
I always wanted to have cool slider for my audio player application. The best I could find here was Guinness4Strength's article. Unfortunately, I didn’t find it pretty enough, so I decided to write my own trackbar. Hopefully you like it.
Properties
Appearance:
ThumbSize - Gets or sets the size of the thumb
ThumbCustomShape - Gets or sets the thumb custom shape. Use ThumbRect property to determine bounding rectangle.
ThumbRoundRectSize - Gets or sets the size of the thumb round rectangle edges.
BorderRoundRectSize - Gets or sets the size of the border round rect.
Values:
Orientation - Gets or sets the orientation of Slider.
Value - Gets or sets the value of Slider.
Minimum - Gets or sets the minimum value.
Maximum - Gets or sets the maximum value.
SmallChange - Gets or sets trackbar's small change. It affects how to behave when directional keys are pressed
LargeChange - Gets or sets trackbar's large change. It affects how to behave when PageUp/PageDown keys are pressed
Behavior:
DrawFocusRectangle - Gets or sets a value indicating whether to draw focus rectangle.
DrawSemitransparentThumb - Gets or sets a value indicating whether to draw semitransparent thumb.
MouseEffects - Gets or sets whether mouse entry and exit actions have impact on how control look.
MouseWheelBarPartitions - Gets or sets the mouse wheel bar partitions.
Colors:
ThumbOuterColor - Gets or sets the thumb outer color.
ThumbInnerColor - Gets or sets the inner color of the thumb.
ThumbPenColor - Gets or sets the color of the thumb pen.
BarOuterColor - Gets or sets the outer color of the bar.
BarInnerColor - Gets or sets the inner color of the bar.
BarPenColor - Gets or sets the color of the bar pen.
ElapsedOuterColor - Gets or sets the outer color of the elapsed.
ElapsedInnerColor - Gets or sets the inner color of the elapsed.
Points of Interest
This control will provide design-time support. Next version should contain custom properties editors.
History
30.01.2007 - first version.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 18 of 18 (Total in Forum: 18) (Refresh) | FirstPrevNext |
|
 |
|
|
Hi Michal, this is absolutely brilliant and exactly what I was looking for!! Well done! My application is in VB. Could I just place the dll in my solution and reference it or would I need a VB version of the component class?
I tried converting but there are numerous errors!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
hi,
you only need to extract control source to separate C# library and then add reference to it in your VB project
Regards
Michal Brylka
Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why. Programmers combine theory and practice: Nothing works and they don't know why.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Good job ! In order to use it in my application i made 2 small modifs: - I fired the Scroll event after the OnMouse_Wheel - I added the support for Image Thumb
Here is the changed code of ColorSlider.cs:
using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms;
namespace MB.Controls { /// <summary> /// Encapsulates control that visualy displays certain integer value and allows user to change it within desired range. It imitates <see cref="System.Windows.Forms.TrackBar"/> as far as mouse usage is concerned. /// </summary> [ToolboxBitmap(typeof(TrackBar))] [DefaultEvent("Scroll"), DefaultProperty("BarInnerColor")] public partial class ColorSlider : Control { #region Events
/// <summary> /// Fires when Slider position has changed /// </summary> [Description("Event fires when the Value property changes")] [Category("Action")] public event EventHandler ValueChanged;
/// <summary> /// Fires when user scrolls the Slider /// </summary> [Description("Event fires when the Slider position is changed")] [Category("Behavior")] public event ScrollEventHandler Scroll;
#endregion
#region Properties
private Rectangle thumbRect; //bounding rectangle of thumb area /// <summary> /// Gets the thumb rect. Usefull to determine bounding rectangle when creating custom thumb shape. /// </summary> /// <value>The thumb rect.</value> [Browsable(false)] public Rectangle ThumbRect { get { return thumbRect; } }
private Rectangle barRect; //bounding rectangle of bar area private Rectangle barHalfRect; private Rectangle thumbHalfRect; private Rectangle elapsedRect; //bounding rectangle of elapsed area
private int thumbSize = 15; /// <summary> /// Gets or sets the size of the thumb. /// </summary> /// <value>The size of the thumb.</value> /// <exception cref="T:System.ArgumentOutOfRangeException">exception thrown when value is lower than zero or grather than half of appropiate dimension</exception> [Description("Set Slider thumb size")] [Category("ColorSlider")] [DefaultValue(15)] public int ThumbSize { get { return thumbSize; } set { if (value > 0 & value < (barOrientation == Orientation.Horizontal ? ClientRectangle.Width : ClientRectangle.Height)) thumbSize = value; else throw new ArgumentOutOfRangeException( "TrackSize has to be greather than zero and lower than half of Slider width"); Invalidate(); } }
private GraphicsPath thumbCustomShape = null; /// <summary> /// Gets or sets the thumb custom shape. Use ThumbRect property to determine bounding rectangle. /// </summary> /// <value>The thumb custom shape. null means default shape</value> [Description("Set Slider's thumb's custom shape")] [Category("ColorSlider")] [Browsable(false)] [DefaultValue(typeof(GraphicsPath), "null")] public GraphicsPath ThumbCustomShape { get { return thumbCustomShape; } set { thumbCustomShape = value; thumbSize = (int) (barOrientation == Orientation.Horizontal ? value.GetBounds().Width : value.GetBounds().Height) + 1; Invalidate(); } }
private Size thumbRoundRectSize = new Size(8, 8); /// <summary> /// Gets or sets the size of the thumb round rectangle edges. /// </summary> /// <value>The size of the thumb round rectangle edges.</value> [Description("Set Slider's thumb round rect size")] [Category("ColorSlider")] [DefaultValue(typeof(Size), "8; 8")] public Size ThumbRoundRectSize { get { return thumbRoundRectSize; } set { int h = value.Height, w = value.Width; if (h <= 0) h = 1; if (w <= 0) w = 1; thumbRoundRectSize = new Size(w, h); Invalidate(); } }
private Size borderRoundRectSize = new Size(8, 8); /// <summary> /// Gets or sets the size of the border round rect. /// </summary> /// <value>The size of the border round rect.</value> [Description("Set Slider's border round rect size")] [Category("ColorSlider")] [DefaultValue(typeof(Size), "8; 8")] public Size BorderRoundRectSize { get { return borderRoundRectSize; } set { int h = value.Height, w = value.Width; if (h <= 0) h = 1; if (w <= 0) w = 1; borderRoundRectSize = new Size(w, h); Invalidate(); } }
private Orientation barOrientation = Orientation.Horizontal; /// <summary> /// Gets or sets the orientation of Slider. /// </summary> /// <value>The orientation.</value> [Description("Set Slider orientation")] [Category("ColorSlider")] [DefaultValue(Orientation.Horizontal)] public Orientation Orientation { get { return barOrientation; } set { if (barOrientation != value) { barOrientation = value; int temp = Width; Width = Height; Height = temp; if (thumbCustomShape != null) thumbSize = (int) (barOrientation == Orientation.Horizontal ? thumbCustomShape.GetBounds().Width : thumbCustomShape.GetBounds().Height) + 1; Invalidate(); } } }
private int trackerValue = 50; /// <summary> /// Gets or sets the value of Slider. /// </summary> /// <value>The value.</value> /// <exception cref="T:System.ArgumentOutOfRangeException">exception thrown when value is outside appropriate range (min, max)</exception> [Description("Set Slider value")] [Category("ColorSlider")] [DefaultValue(50)] public int Value { get { return trackerValue; } set { if (value >= barMinimum & value <= barMaximum) { trackerValue = value; if (ValueChanged != null) ValueChanged(this, new EventArgs()); Invalidate(); } else throw new ArgumentOutOfRangeException("Value is outside appropriate range (min, max)"); } }
private int barMinimum = 0; /// <summary> /// Gets or sets the minimum value. /// </summary> /// <value>The minimum value.</value> /// <exception cref="T:System.ArgumentOutOfRangeException">exception thrown when minimal value is greather than maximal one</exception> [Description("Set Slider minimal point")] [Category("ColorSlider")] [DefaultValue(0)] public int Minimum { get { return barMinimum; } set { if (value < barMaximum) { barMinimum = value; if (trackerValue < barMinimum) { trackerValue = barMinimum; if (ValueChanged != null) ValueChanged(this, new EventArgs()); } Invalidate(); } else throw new ArgumentOutOfRangeException("Minimal value is greather than maximal one"); } }
private int barMaximum = 100; /// <summary> /// Gets or sets the maximum value. /// </summary> /// <value>The maximum value.</value> /// <exception cref="T:System.ArgumentOutOfRangeException">exception thrown when maximal value is lower than minimal one</exception> [Description("Set Slider maximal point")] [Category("ColorSlider")] [DefaultValue(100)] public int Maximum { get { return barMaximum; } set { if (value > barMinimum) { barMaximum = value; if (trackerValue > barMaximum) { trackerValue = barMaximum; if (ValueChanged != null) ValueChanged(this, new EventArgs()); } Invalidate(); } else throw new ArgumentOutOfRangeException("Maximal value is lower than minimal one"); } }
private uint smallChange = 1; /// <summary> /// Gets or sets trackbar's small change. It affects how to behave when directional keys are pressed /// </summary> /// <value>The small change value.</value> [Description("Set trackbar's small change")] [Category("ColorSlider")] [DefaultValue(1)] public uint SmallChange { get { return smallChange; } set { smallChange = value; } }
private uint largeChange = 5;
/// <summary> /// Gets or sets trackbar's large change. It affects how to behave when PageUp/PageDown keys are pressed /// </summary> /// <value>The large change value.</value> [Description("Set trackbar's large change")] [Category("ColorSlider")] [DefaultValue(5)] public uint LargeChange { get { return largeChange; } set { largeChange = value; } }
private bool drawFocusRectangle = true; /// <summary> /// Gets or sets a value indicating whether to draw focus rectangle. /// </summary> /// <value><c>true</c> if focus rectangle should be drawn; otherwise, <c>false</c>.</value> [Description("Set whether to draw focus rectangle")] [Category("ColorSlider")] [DefaultValue(true)] public bool DrawFocusRectangle { get { return drawFocusRectangle; } set { drawFocusRectangle = value; Invalidate(); } }
private bool drawSemitransparentThumb = true; /// <summary> /// Gets or sets a value indicating whether to draw semitransparent thumb. /// </summary> /// <value><c>true</c> if semitransparent thumb should be drawn; otherwise, <c>false</c>.</value> [Description("Set whether to draw semitransparent thumb")] [Category("ColorSlider")] [DefaultValue(true)] public bool DrawSemitransparentThumb { get { return drawSemitransparentThumb; } set { drawSemitransparentThumb = value; Invalidate(); } }
private bool mouseEffects = true; /// <summary> /// Gets or sets whether mouse entry and exit actions have impact on how control look. /// </summary> /// <value><c>true</c> if mouse entry and exit actions have impact on how control look; otherwise, <c>false</c>.</value> [Description("Set whether mouse entry and exit actions have impact on how control look")] [Category("ColorSlider")] [DefaultValue(true)] public bool MouseEffects { get { return mouseEffects; } set { mouseEffects = value; Invalidate(); } }
private int mouseWheelBarPartitions = 10; /// <summary> /// Gets or sets the mouse wheel bar partitions. /// </summary> /// <value>The mouse wheel bar partitions.</value> /// <exception cref="T:System.ArgumentOutOfRangeException">exception thrown when value isn't greather than zero</exception> [Description("Set to how many parts is bar divided when using mouse wheel")] [Category("ColorSlider")] [DefaultValue(10)] public int MouseWheelBarPartitions { get { return mouseWheelBarPartitions; } set { if (value > 0) mouseWheelBarPartitions = value; else throw new ArgumentOutOfRangeException("MouseWheelBarPartitions has to be greather than zero"); } }
private Image thumbImage = null; /// <summary> /// Gets or sets the Image use to render the thumb. /// </summary> /// <value>the thumb Image</value> [Description("Set to use a specific Image for the thumb")] [Category("ColorSlider")] [DefaultValue(null)] public Image ThumbImage { get { return thumbImage; } set { if (value !=null ) { thumbImage = value; } } } private Color thumbOuterColor = Color.White; /// <summary> /// Gets or sets the thumb outer color . /// </summary> /// <value>The thumb outer color.</value> [Description("Set Slider thumb outer color")] [Category("ColorSlider")] [DefaultValue(typeof(Color), "White")] public Color ThumbOuterColor { get { return thumbOuterColor; } set { thumbOuterColor = value; Invalidate(); } }
private Color thumbInnerColor = Color.Gainsboro; /// <summary> /// Gets or sets the inner color of the thumb. /// </summary> /// <value>The inner color of the thumb.</value> [Description("Set Slider thumb inner color")] [Category("ColorSlider")] [DefaultValue(typeof(Color), "Gainsboro")] public Color ThumbInnerColor { get { return thumbInnerColor; } set { thumbInnerColor = value; Invalidate(); } }
private Color thumbPenColor = Color.Silver; /// <summary> /// Gets or sets the color of the thumb pen. /// </summary> /// <value>The color of the thumb pen.</value> [Description("Set Slider thumb pen color")] [Category("ColorSlider")] [DefaultValue(typeof(Color), "Silver")] public Color ThumbPenColor { get { return thumbPenColor; } set { thumbPenColor = value; Invalidate(); } }
private Color barOuterColor = Color.SkyBlue; /// <summary> /// Gets or sets the outer color of the bar. /// </summary> /// <value>The outer color of the bar.</value> [Description("Set Slider bar outer color")] [Category("ColorSlider")] [DefaultValue(typeof(Color), "SkyBlue")] public Color BarOuterColor { get { return barOuterColor; } set { barOuterColor = value; Invalidate(); } }
private Color barInnerColor = Color.DarkSlateBlue; /// <summary> /// Gets or sets the inner color of the bar. /// </summary> /// <value>The inner color of the bar.</value> [Description("Set Slider bar inner color")] [Category("ColorSlider")] [DefaultValue(typeof(Color), "DarkSlateBlue")] public Color BarInnerColor { get { return barInnerColor; } set { barInnerColor = value; Invalidate(); } }
private Color barPenColor = Color.Gainsboro; /// <summary> /// Gets or sets the color of the bar pen. /// </summary> /// <value>The color of the bar pen.</value> [Description("Set Slider bar pen color")] [Category("ColorSlider")] [DefaultValue(typeof(Color), "Gainsboro")] public Color BarPenColor { get { return barPenColor; } set { barPenColor = value; Invalidate(); } }
private Color elapsedOuterColor = Color.DarkGreen; /// <summary> /// Gets or sets the outer color of the elapsed. /// </summary> /// <value>The outer color of the elapsed.</value> [Description("Set Slider's elapsed part outer color")] [Category("ColorSlider")] [DefaultValue(typeof(Color), "DarkGreen")] public Color ElapsedOuterColor { get { return elapsedOuterColor; } set { elapsedOuterColor = value; Invalidate(); } }
private Color elapsedInnerColor = Color.Chartreuse; /// <summary> /// Gets or sets the inner color of the elapsed. /// </summary> /// <value>The inner color of the elapsed.</value> [Description("Set Slider's elapsed part inner color")] [Category("ColorSlider")] [DefaultValue(typeof(Color), "Chartreuse")] public Color ElapsedInnerColor { get { return elapsedInnerColor; } set { elapsedInnerColor = value; Invalidate(); } }
#endregion
#region Color schemas
//define own color schemas private Color[,] aColorSchema = new Color[,] { { Color.White, Color.Gainsboro, Color.Silver, Color.SkyBlue, Color.DarkSlateBlue, Color.Gainsboro, Color.DarkGreen, Color.Chartreuse }, { Color.White, Color.Gainsboro, Color.Silver, Color.Red, Color.DarkRed, Color.Gainsboro, Color.Coral, Color.LightCoral }, { Color.White, Color.Gainsboro, Color.Silver, Color.GreenYellow, Color.Yellow, Color.Gold, Color.Orange, Color.OrangeRed }, { Color.White, Color.Gainsboro, Color.Silver, Color.Red, Color.Crimson, Color.Gainsboro, Color.DarkViolet , Color.Violet } };
public enum ColorSchemas { PerlBlueGreen, PerlRedCoral, PerlGold, PerlRoyalColors }
private ColorSchemas colorSchema = ColorSchemas.PerlBlueGreen; /// <summary> /// Sets color schema. Color generalization / fast color changing. Has no effect when slider colors are changed manually after schema was applied. /// </summary> /// <value>New color schema value</value> [Description("Set Slider color schema. Has no effect when slider colors are changed manually after schema was applied.")] [Category("ColorSlider")] [DefaultValue(typeof(ColorSchemas), "PerlBlueGreen")] public ColorSchemas ColorSchema { get { return colorSchema; } set { colorSchema = value; byte sn = (byte)value; thumbOuterColor = aColorSchema[sn, 0]; thumbInnerColor = aColorSchema[sn, 1]; thumbPenColor = aColorSchema[sn, 2]; barOuterColor = aColorSchema[sn, 3]; barInnerColor = aColorSchema[sn, 4]; barPenColor = aColorSchema[sn, 5]; elapsedOuterColor = aColorSchema[sn, 6]; elapsedInnerColor = aColorSchema[sn, 7];
Invalidate(); } }
#endregion #region Constructors
/// <summary> /// Initializes a new instance of the <see cref="ColorSlider"/> class. /// </summary> /// <param name="min">The minimum value.</param> /// <param name="max">The maximum value.</param> /// <param name="value">The current value.</param> public ColorSlider(int min, int max, int value) { InitializeComponent(); SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.Selectable | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserMouse | ControlStyles.UserPaint, true); BackColor = Color.Transparent;
Minimum = min; Maximum = max; Value = value; }
/// <summary> /// Initializes a new instance of the <see cref="ColorSlider"/> class. /// </summary> public ColorSlider() : this(0, 100, 50) { }
#endregion
#region Paint
/// <summary> /// Raises the <see cref="E:System.Windows.Forms.Control.Paint"></see> event. /// </summary> /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"></see> that contains the event data.</param> protected override void OnPaint(PaintEventArgs e) { if (!Enabled) { Color[] desaturatedColors = DesaturateColors(thumbOuterColor, thumbInnerColor, thumbPenColor, barOuterColor, barInnerColor, barPenColor, elapsedOuterColor, elapsedInnerColor); DrawColorSlider(e, desaturatedColors[0], desaturatedColors[1], desaturatedColors[2], desaturatedColors[3], desaturatedColors[4], desaturatedColors[5], desaturatedColors[6], desaturatedColors[7]); } else { if (mouseEffects && mouseInRegion) { Color[] lightenedColors = LightenColors(thumbOuterColor, thumbInnerColor, thumbPenColor, barOuterColor, barInnerColor, barPenColor, elapsedOuterColor, elapsedInnerColor); DrawColorSlider(e, lightenedColors[0], lightenedColors[1], lightenedColors[2], lightenedColors[3], lightenedColors[4], lightenedColors[5], lightenedColors[6], lightenedColors[7]); } else { DrawColorSlider(e, thumbOuterColor, thumbInnerColor, thumbPenColor, barOuterColor, barInnerColor, barPenColor, elapsedOuterColor, elapsedInnerColor); } } }
/// <summary> /// Draws the colorslider control using passed colors. /// </summary> /// <param name="e">The <see cref="T:System.Windows.Forms.PaintEventArgs"/> instance containing the event data.</param> /// <param name="thumbOuterColorPaint">The thumb outer color paint.</param> /// <param name="thumbInnerColorPaint">The thumb inner color paint.</param> /// <param name="thumbPenColorPaint">The thumb pen color paint.</param> /// <param name="barOuterColorPaint">The bar outer color paint.</param> /// <param name="barInnerColorPaint">The bar inner color paint.</param> /// <param name="barPenColorPaint">The bar pen color paint.</param> /// <param name="elapsedOuterColorPaint">The elapsed outer color paint.</param> /// <param name="elapsedInnerColorPaint">The elapsed inner color paint.</param> private void DrawColorSlider(PaintEventArgs e, Color thumbOuterColorPaint, Color thumbInnerColorPaint, Color thumbPenColorPaint, Color barOuterColorPaint, Color barInnerColorPaint, Color barPenColorPaint, Color elapsedOuterColorPaint, Color elapsedInnerColorPaint) { try { //set up thumbRect aproprietly if (barOrientation == Orientation.Horizontal) { int TrackX = (((trackerValue - barMinimum) * (ClientRectangle.Width - thumbSize)) / (barMaximum - barMinimum)); thumbRect = new Rectangle(TrackX, 1, thumbSize - 1, ClientRectangle.Height - 3); } else { int TrackY = (((trackerValue - barMinimum) * (ClientRectangle.Height - thumbSize)) / (barMaximum - barMinimum)); thumbRect = new Rectangle(1, TrackY, ClientRectangle.Width - 3, thumbSize - 1); }
//adjust drawing rects barRect = ClientRectangle; thumbHalfRect = thumbRect; LinearGradientMode gradientOrientation; if (barOrientation == Orientation.Horizontal) { barRect.Inflate(-1, -barRect.Height / 3); barHalfRect = barRect; barHalfRect.Height /= 2; gradientOrientation = LinearGradientMode.Vertical; thumbHalfRect.Height /= 2; elapsedRect = barRect; elapsedRect.Width = thumbRect.Left + thumbSize / 2; } else { barRect.Inflate(-barRect.Width / 3, -1); barHalfRect = barRect; barHalfRect.Width /= 2; gradientOrientation = LinearGradientMode.Horizontal; thumbHalfRect.Width /= 2; elapsedRect = barRect; elapsedRect.Height = thumbRect.Top + thumbSize / 2; } //get thumb shape path GraphicsPath thumbPath; if (thumbCustomShape == null) thumbPath = CreateRoundRectPath(thumbRect, thumbRoundRectSize); else { thumbPath = thumbCustomShape; Matrix m = new Matrix(); m.Translate(thumbRect.Left - thumbPath.GetBounds().Left, thumbRect.Top - thumbPath.GetBounds().Top); thumbPath.Transform(m); }
//draw bar using ( LinearGradientBrush lgbBar = new LinearGradientBrush(barHalfRect, barOuterColorPaint, barInnerColorPaint, gradientOrientation) ) { lgbBar.WrapMode = WrapMode.TileFlipXY; e.Graphics.FillRectangle(lgbBar, barRect); //draw elapsed bar using ( LinearGradientBrush lgbElapsed = new LinearGradientBrush(barHalfRect, elapsedOuterColorPaint, elapsedInnerColorPaint, gradientOrientation)) { lgbElapsed.WrapMode = WrapMode.TileFlipXY; if (Capture && drawSemitransparentThumb) { Region elapsedReg = new Region(elapsedRect); elapsedReg.Exclude(thumbPath); e.Graphics.FillRegion(lgbElapsed, elapsedReg); } else e.Graphics.FillRectangle(lgbElapsed, elapsedRect); } //draw bar band using (Pen barPen = new Pen(barPenColorPaint, 0.5f)) { | | | | | |