#region gnu_license
/*
Crystal Controls - C# control library containing the following tools:
CrystalControl - base class
CrystalGradientControl - a control that can either have a gradient background or be totally transparent.
CrystalLabel - a homegrown label that can have a gradient or transparent background.
CrystalPanel - a panel that can have a gradient or transparent background.
CrystalTrackBar - a homegrown trackbar that can have a gradient or transparent background.
CrystalToolStripTrackBar - a host for CrystalTrackBar that allows it to work in a ToolStrip.
CrystalImageGridView - a control that hosts thumbnail images in a virtual grid.
CrystalImageGridModel - a data model that holds a collection of CrystalImageItems
to feed to CrystalImageGridView.
CrystalImageItem - a class that describes an Image file.
CrystalThumbnailer - provides thumbnailing methods for images.
CrystalCollector - a base class for a controller that links
CrystalImageGridView to the CrystalImageGridModel.
CrystalFileCollector - a controller that works on disk-based Image files.
CrystalDesignCollector - a controller that works in Visual Studio toolbox designer.
CrystalMemoryCollector - a controller that can be used to add images from memory.
CrystalMemoryZipCollector - a controller that accesses images in zip files by streaming them into memory.
CrystalZipCollector - a controller that accesses images in zip files by unpacking them.
CrystalRarCollector - a controller that accesses images in rar files by unpacking them.
CrystalPictureBox - a picture box control, derived from CrystalGradientControl.
CrystalPictureShow - a control for viewing images and processing slideshows.
CrystalComicShow - a control for viewing comic-book images in the CDisplay format.
Copyright (C) 2006, 2008 Richard Guion
Attilan Software Factory: http://www.attilan.com
Contact: richard@attilan.com
Version 1.0.0
This is a work in progress: USE AT YOUR OWN RISK! Interfaces/Methods may change!
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using Attilan.Crystal.Tools;
namespace Attilan.Crystal.Controls
{
/// <summary>
/// Represents visual thumb states for CrystalTrackBar
/// </summary>
public enum CrystalThumbState
{
/// <summary>
/// The mouse is outside the CrystalTrackBar control.
/// </summary>
Normal = 0,
/// <summary>
/// user has clicked on the thumb inside the CrystalTrackBar control.
/// </summary>
Pressed = 1,
/// <summary>
/// The thumb inside the CrystalTrackBar control is being erased.
/// </summary>
Erased = 2,
/// <summary>
/// The mouse has entered the CrystalTrackBar control.
/// </summary>
Hover = 3,
/// <summary>
/// The control is disabled and the thumb state is disabled.
/// </summary>
Disabled = 4
}
/// <summary>
/// CrystalTrackBar is a TrackBar replacement that can have a gradient or
/// transparent background.
/// </summary>
[DesignerCategory("code")]
[
ToolboxItem(true),
ToolboxBitmap(typeof (resfinder), "CrystalToolkit.Resources.CrystalTrackBar.bmp")
//ToolboxBitmap(typeof(System.Windows.Forms.TrackBar))
]
public class CrystalTrackBar : CrystalGradientControl
{
#region Fields
// rects for trackbar, tickbar, and thumb
private Rectangle _trackRectangle = new Rectangle();
private Rectangle _ticksRectangleBottomRight = new Rectangle();
private Rectangle _ticksRectangleTopLeft = new Rectangle();
private RectangleF _thumbRectangle = new Rectangle();
// tick info
private int _value = 0;
private int _currentTickValue = 0;
private int _numberTicks = 11;
private int _minimum = 0;
private int _maximum = 10;
private int _tickFrequency = 1;
private int _smallChange = 1;
private int _largeChange = 5;
private float _tickSpace = 0;
private float _tickSingle = 0;
private TickStyle _tickStyle = TickStyle.BottomRight;
private EdgeStyle _tickEdgeStyle = EdgeStyle.Etched;
private List<int> _tickValues = null;
// states
private CrystalThumbState _thumbState = CrystalThumbState.Normal;
private Orientation _orientation = Orientation.Horizontal;
// track bar
private int _trackBarMargin = 10;
private int _trackBarHeight = 4;
// thumb images
private Image _thumbImage = null;
private Image _thumbHotImage = null;
private Image _thumbWarmImage = null;
private Image _thumbDisabledImage = null;
// keyboard input
private bool _keyboardControl = true;
#endregion
#region Events
/// <summary>
/// Any subscribers to the event handler will be called when CrystalTrackBar's value has changed.
/// </summary>
public event EventHandler ValueChanged;
#endregion
#region Public Properties
/// <summary>
/// Indicates where the ticks appear on the CrystalTrackBar.
/// </summary>
[
Browsable(true),
Category("Appearance"),
DefaultValue(TickStyle.BottomRight),
Description("Indicates where the ticks appear on the CrystalTrackBar.")
]
public TickStyle TickStyle
{
get { return _tickStyle; }
set
{
if (_tickStyle != value)
{
_tickStyle = value;
RedrawControl();
}
}
}
/// <summary>
/// The position of the thumb on the slider.
/// </summary>
[
Bindable(true),
Browsable(true),
Category("Behavior"),
DefaultValue(0),
Description("The position of the thumb on the slider.")
]
public int Value
{
get { return _value; }
set
{
if (value < _minimum || value > _maximum)
throw new ArgumentException(
string.Format(
"'{0}' is not a valid value for 'Value'. 'Value' should be between '{1}' and '{2}'", value,
_minimum, _maximum));
// BUG FIX: Process part of this code even with value change,
// to make the thumb display properly.
// Cache the boolean that tells us if the value has changed.
bool valChanged = (_value != value);
// save the new value
_value = value;
_currentTickValue = _value;
// Update subscribers when all of the above is done.
if ((ValueChanged != null) && (valChanged))
ValueChanged(this, new EventArgs());
// Recalc the thumb position
UpdateThumbRectangle();
if (!IsThumbPressed())
{
RedrawControl();
}
}
}
/// <summary>
/// The maximum value for the thumb position of the slider of the CrystalTrackBar.
/// </summary>
[
Browsable(true),
Category("Behavior"),
DefaultValue(10),
Description("The maximum value for the thumb position of the slider of the CrystalTrackBar.")
]
public int Maximum
{
get { return _maximum; }
set
{
if (_maximum != value)
{
_maximum = value;
//CalcTicks();
SetupTrackBar();
RedrawControl();
}
}
}
/// <summary>
/// The minimum value for the thumb position of the slider of the CrystalTrackBar.
/// </summary>
[
Browsable(true),
Category("Behavior"),
DefaultValue(0),
Description("The minimum value for the thumb position of the slider of the CrystalTrackBar.")
]
public int Minimum
{
get { return _minimum; }
set
{
if (_minimum != value)
{
_minimum = value;
//CalcTicks();
SetupTrackBar();
RedrawControl();
}
}
}
/// <summary>
/// Indicates the interval between ticks on the CrystalTrackBar.
/// </summary>
[
Browsable(true),
Category("Appearance"),
DefaultValue(1),
Description("Indicates the interval between ticks on the CrystalTrackBar.")
]
public int TickFrequency
{
get { return _tickFrequency; }
set
{
if (_tickFrequency != value)
{
_tickFrequency = value;
SetupTrackBar();
RedrawControl();
}
}
}
/// <summary>
/// The number of positions the slider moves in response to keyboard input (arrow keys).
/// </summary>
[
Browsable(true),
Category("Behavior"),
DefaultValue(1),
Description("The number of positions the slider moves in response to keyboard input (arrow keys).")
]
public int SmallChange
{
get { return _smallChange; }
set { _smallChange = value; }
}
/// <summary>
/// The number of positions the slider moves in response to mouse clicks or the PAGE UP and PAGE DOWN keys.
/// </summary>
[
Browsable(true),
Category("Behavior"),
DefaultValue(5),
Description(
"The number of positions the slider moves in response to mouse clicks or the PAGE UP and PAGE DOWN keys."
)
]
public int LargeChange
{
get { return _largeChange; }
set { _largeChange = value; }
}
/// <summary>
/// A list of integer values for each tick item on trackbar.
/// </summary>
[
Browsable(false),
Description("A list (List<int>) of integer values for each tick item on trackbar.")
]
public List<int> TickValues
{
get { return _tickValues; }
}
/// <summary>
/// Allows the user to adjust trackbar with the keys: left arrow, right arrow, up, down, home, end.
/// </summary>
[
Browsable(true),
Category("Behavior"),
DefaultValue(true),
Description(
"Allows the user to adjust trackbar with the keys: left arrow, right arrow, up, down, home, end.")
]
public bool KeyboardControl
{
get { return _keyboardControl; }
set { _keyboardControl = value; }
}
/// <summary>
/// Allows the CrystalTrackBar to be displayed horizontally or vertically.
/// </summary>
[
Browsable(true),
Category("Appearance"),
Description("Allows the CrystalTrackBar to be displayed horizontally or vertically.")
]
public Orientation Orientation
{
get { return _orientation; }
set
{
if (_orientation != value)
{
_orientation = value;
// flip the size
Size = new Size(Size.Height, Size.Width);
}
}
}
/// <summary>
/// Determines the appearance of the ticks on the CrystalTrackBar.
/// </summary>
[
Browsable(true),
Category("Appearance"),
Description("Determines the appearance of the ticks on the CrystalTrackBar.")
]
public EdgeStyle TickEdgeStyle
{
get { return _tickEdgeStyle; }
set
{
if (_tickEdgeStyle != value)
{
_tickEdgeStyle = value;
RedrawControl();
}
}
}
/// <summary>
/// Enabled thumb image.
/// </summary>
public Image ThumbNormalImage
{
get { return _thumbImage; }
set { _thumbImage = value; }
}
/// <summary>
/// Pressed thumb image.
/// </summary>
public Image ThumbPressImage
{
get { return _thumbHotImage; }
set { _thumbHotImage = value; }
}
/// <summary>
/// Hover thumb image.
/// </summary>
public Image ThumbHoverImage
{
get { return _thumbWarmImage; }
set { _thumbWarmImage = value; }
}
/// <summary>
/// Disabled thumb image.
/// </summary>
public Image ThumbDisabledImage
{
get { return _thumbDisabledImage; }
set { _thumbDisabledImage = value; }
}
#endregion
#region Constructors and Initializers
/// <summary>
/// Default constructor for CrystalTrackBar.
/// </summary>
public CrystalTrackBar()
{
// this call says "I'll draw it myself"
SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw |
ControlStyles.DoubleBuffer, true);
SetDefaultSize();
}
/// <summary>
/// Sets the default size for the control, used for display in the Forms designer.
/// </summary>
protected void SetDefaultSize()
{
// Set default size so that user will see the control in the designer
if (IsHorizontal())
Size = new Size(105, 45);
else
Size = new Size(45, 105);
}
#endregion
#region Tick Methods
/// <summary>
/// Calculates the tick intervals based on the Minimum, Maximum, and TickFrequency values.
/// </summary>
protected virtual void CalcTicks()
{
_numberTicks = 0;
_tickValues = new List<int>();
for (int tickCount = _minimum; tickCount <= _maximum; tickCount += _tickFrequency)
{
_tickValues.Add(tickCount);
_numberTicks++;
}
// Make sure that maximum value is the last value.
_tickValues.RemoveAt(_numberTicks - 1);
_tickValues.Add(_maximum);
}
/// <summary>
/// Draws the ticks using the TrackBarRenderer.
/// </summary>
/// <param name="gfx">Graphics object.</param>
private void DrawRenderTicks(Graphics gfx)
{
if (TickStyle != TickStyle.None)
{
if (IsHorizontal())
{
if ((_tickStyle == TickStyle.Both) || (_tickStyle == TickStyle.BottomRight))
TrackBarRenderer.DrawHorizontalTicks(gfx, _ticksRectangleBottomRight, _numberTicks,
_tickEdgeStyle);
if ((_tickStyle == TickStyle.Both) || (_tickStyle == TickStyle.TopLeft))
TrackBarRenderer.DrawHorizontalTicks(gfx, _ticksRectangleTopLeft, _numberTicks, _tickEdgeStyle);
}
else
{
if ((_tickStyle == TickStyle.Both) || (_tickStyle == TickStyle.BottomRight))
TrackBarRenderer.DrawVerticalTicks(gfx, _ticksRectangleBottomRight, _numberTicks, _tickEdgeStyle);
if ((_tickStyle == TickStyle.Both) || (_tickStyle == TickStyle.TopLeft))
TrackBarRenderer.DrawVerticalTicks(gfx, _ticksRectangleTopLeft, _numberTicks, _tickEdgeStyle);
}
}
}
/// <summary>
/// Draws the Ticks using a line, horizontally.
/// </summary>
/// <param name="gfx">Graphics object.</param>
/// <param name="ticksRect">Ticks rectangle.</param>
private void DrawHorizLineTicks(Graphics gfx, Rectangle ticksRect)
{
for (int index = 0; index < _numberTicks; index++)
{
// Calculate where the current tick value X coordinate is.
float xTick = ticksRect.X;
xTick += (_tickSpace*(index));
using (Pen linePen = new Pen(Color.White, 2))
{
linePen.EndCap = LineCap.Round;
gfx.DrawLine(linePen, xTick,
ticksRect.Y,
xTick,
ticksRect.Y + ticksRect.Height);
}
}
}
/// <summary>
/// Draws the Ticks using a line, vertically.
/// </summary>
/// <param name="gfx">Graphics object.</param>
/// <param name="ticksRect">Ticks rectangle.</param>
private void DrawVertLineTicks(Graphics gfx, Rectangle ticksRect)
{
for (int index = 0; index < _numberTicks; index++)
{
// Calculate where the current tick value X coordinate is.
float yTick = ticksRect.Y;
yTick += (_tickSpace*(index));
float xTick = ticksRect.X;
using (Pen linePen = new Pen(Color.White, 2))
{
linePen.EndCap = LineCap.Round;
gfx.DrawLine(linePen, xTick,
yTick,
xTick + ticksRect.Width,
yTick);
}
}
}
/// <summary>
/// Draws the Ticks using a dash line.
/// </summary>
/// <param name="gfx">Graphics object.</param>
private void DrawLineTicks(Graphics gfx)
{
if (TickStyle != TickStyle.None)
{
if (IsHorizontal())
{
if ((_tickStyle == TickStyle.Both) || (_tickStyle == TickStyle.BottomRight))
DrawHorizLineTicks(gfx, _ticksRectangleBottomRight);
if ((_tickStyle == TickStyle.Both) || (_tickStyle == TickStyle.TopLeft))
DrawHorizLineTicks(gfx, _ticksRectangleBottomRight);
}
else
{
if ((_tickStyle == TickStyle.Both) || (_tickStyle == TickStyle.BottomRight))
DrawVertLineTicks(gfx, _ticksRectangleBottomRight);
if ((_tickStyle == TickStyle.Both) || (_tickStyle == TickStyle.TopLeft))
DrawVertLineTicks(gfx, _ticksRectangleTopLeft);
}
}
}
/// <summary>
/// Draws the ticks above, below, left, or right of the trackbar.
/// </summary>
/// <param name="gfx">The Graphics object to draw on.</param>
protected virtual void DrawTicks(Graphics gfx)
{
if (TrackBarRenderer.IsSupported)
DrawRenderTicks(gfx);
else
DrawLineTicks(gfx);
}
/// <summary>
/// Calculates the current X tick coordinate for a horizontal CrystalTrackBar.
/// </summary>
/// <returns></returns>
protected float CurrentTickXCoordinate()
{
// Calculate where the current tick value X coordinate is.
float xTick = _tickSingle*_currentTickValue;
xTick += _trackBarMargin;
// Take half the width of the thumb...
float halfThumb = _thumbRectangle.Width/2.0f;
// ...subtract this from the current X tick and return
return xTick - halfThumb;
}
/// <summary>
/// Calculates the current Y tick coordinate for a horizontal CrystalTrackBar.
/// </summary>
/// <returns></returns>
protected float CurrentTickYCoordinate()
{
// Calculate where the current tick value X coordinate is.
float yTick = _tickSingle*_currentTickValue;
yTick += _trackBarMargin;
// Take half the height of the thumb...
float halfThumb = _thumbRectangle.Height/2;
// ...subtract this from the current Y tick and return
return yTick - halfThumb;
}
/// <summary>
/// Returns the current tick coordinate based on the orientation of the CrystalTrackBar.
/// </summary>
/// <returns>Returns the current tick coordinate.</returns>
protected virtual float CurrentThumbTickCoordinate()
{
if (IsHorizontal())
return CurrentTickXCoordinate();
else
return CurrentTickYCoordinate();
}
/// <summary>
/// Returns the thumb tick at the given position
/// </summary>
/// <param name="location">Point location to determine the thumb tick</param>
/// <returns>Thumb tick integer.</returns>
protected virtual int GetThumbTick(Point location)
{
//float xVal = location.X - _trackBarMargin;
float valCoord;
if (IsHorizontal())
valCoord = location.X;
else
valCoord = location.Y;
if (valCoord > 0.0f)
{
int retval = (int) (valCoord/_tickSingle);
return retval;
}
return 0;
}
#endregion
#region TrackBar Methods
/// <summary>
/// Draws the TrackBar using TrackBarRenderer
/// </summary>
/// <param name="gfx">The Graphics object to draw on.</param>
private void DrawRendererTrackBar(Graphics gfx)
{
if (IsHorizontal())
TrackBarRenderer.DrawHorizontalTrack(gfx, _trackRectangle);
else
TrackBarRenderer.DrawVerticalTrack(gfx, _trackRectangle);
}
/// <summary>
/// Draws the TrackBar using a line.
/// </summary>
/// <param name="gfx">The Graphics object to draw on.</param>
private void DrawLineTrackBar(Graphics gfx)
{
if (IsHorizontal())
{
using (Pen linePen = new Pen(Color.White, 4))
{
linePen.EndCap = LineCap.Round;
gfx.DrawLine(linePen, _trackRectangle.X, _trackRectangle.Y + 2,
_trackRectangle.X + _trackRectangle.Width,
_trackRectangle.Y + 2);
}
using (Pen linePen = new Pen(Color.Gray, 2))
{
linePen.EndCap = LineCap.Round;
gfx.DrawLine(linePen, _trackRectangle.X, _trackRectangle.Y,
_trackRectangle.X + _trackRectangle.Width,
_trackRectangle.Y);
}
}
else
{
using (Pen linePen = new Pen(Color.White, 4))
{
linePen.EndCap = LineCap.Round;
gfx.DrawLine(linePen, _trackRectangle.X + 2, _trackRectangle.Y,
_trackRectangle.X + 2,
_trackRectangle.Y + _trackRectangle.Height);
}
using (Pen linePen = new Pen(Color.Gray, 2))
{
linePen.EndCap = LineCap.Round;
gfx.DrawLine(linePen, _trackRectangle.X, _trackRectangle.Y,
_trackRectangle.X,
_trackRectangle.Y + _trackRectangle.Height);
}
}
}
/// <summary>
/// Draws the solid track bar line.
/// </summary>
/// <param name="gfx">The Graphics object to draw on.</param>
protected virtual void DrawTrackBar(Graphics gfx)
{
if (!TrackBarRenderer.IsSupported)
DrawLineTrackBar(gfx);
else
DrawRendererTrackBar(gfx);
}
/// <summary>
/// Calculates the sizes of the bar, thumb, and ticks rectangle for a horizontal track bar.
/// </summary>
private void SetupHorizontalTrackBar()
{
using (Graphics g = CreateGraphics())
{
_trackRectangle.X = ClientRectangle.X + _trackBarMargin;
_trackRectangle.Y = ClientRectangle.Height/2;
_trackRectangle.Width = ClientRectangle.Width - (_trackBarMargin*2);
_trackRectangle.Height = _trackBarHeight;
// Calculate the size of the rectangle in which to
// draw the ticks.
_ticksRectangleBottomRight.X = _trackRectangle.X;
_ticksRectangleBottomRight.Y = _trackRectangle.Y + 8; // ticks on the bottom
_ticksRectangleBottomRight.Width = _trackRectangle.Width;
_ticksRectangleBottomRight.Height = 4;
_ticksRectangleTopLeft = _ticksRectangleBottomRight;
_ticksRectangleTopLeft.Y = _trackRectangle.Y - 8; // ticks on the Top
_tickSpace = ((float) _ticksRectangleBottomRight.Width - 1)/
((float) _numberTicks - 1);
float numTicks = Maximum - Minimum;
_tickSingle = _trackRectangle.Width/numTicks;
// Calculate the size of the thumb.
// w = 11.0, h = 21.0
if (TrackBarRenderer.IsSupported)
{
_thumbRectangle.Size =
TrackBarRenderer.GetBottomPointingThumbSize(g,
TrackBarThumbState.Normal);
}
else
{
_thumbRectangle.Size = new SizeF(11.0f, 21.0f);
}
UpdateThumbRectangle();
_thumbRectangle.Y = _trackRectangle.Y - 8;
}
}
/// <summary>
/// Calculates the sizes of the bar, thumb, and ticks rectangle for a vertical track bar.
/// </summary>
private void SetupVerticalTrackBar()
{
using (Graphics g = CreateGraphics())
{
_trackRectangle.X = ClientRectangle.Width/2;
_trackRectangle.Y = ClientRectangle.Y + _trackBarMargin;
_trackRectangle.Width = _trackBarHeight;
_trackRectangle.Height = ClientRectangle.Height - (_trackBarMargin*2);
// Calculate the size of the rectangle in which to
// draw the ticks.
_ticksRectangleBottomRight.Y = _trackRectangle.Y;
_ticksRectangleBottomRight.X = _trackRectangle.X + 8; // ticks on the right
_ticksRectangleBottomRight.Width = 4;
_ticksRectangleBottomRight.Height = _trackRectangle.Height;
_ticksRectangleTopLeft = _ticksRectangleBottomRight;
_ticksRectangleTopLeft.X = _trackRectangle.X - 8; // ticks on the left
_tickSpace = ((float) _ticksRectangleBottomRight.Height - 1)/
((float) _numberTicks - 1);
float numTicks = Maximum - Minimum;
_tickSingle = _trackRectangle.Height/numTicks;
// Calculate the size of the thumb.
// w = 21.0, h = 11.0
if (TrackBarRenderer.IsSupported)
{
_thumbRectangle.Size =
TrackBarRenderer.GetRightPointingThumbSize(g,
TrackBarThumbState.Normal);
}
else
{
_thumbRectangle.Size = new SizeF(21.0f, 11.0f);
}
UpdateThumbRectangle();
_thumbRectangle.X = _trackRectangle.X - 8;
}
}
protected virtual void SetupThumbImages()
{
GetTransparentThumbImage(CrystalThumbState.Disabled);
GetTransparentThumbImage(CrystalThumbState.Normal);
GetTransparentThumbImage(CrystalThumbState.Pressed);
GetTransparentThumbImage(CrystalThumbState.Hover);
}
/// <summary>
/// Calculates the sizes of the bar, thumb, and ticks rectangle.
/// </summary>
protected virtual void SetupTrackBar()
{
SetupThumbImages();
CalcTicks();
if (IsHorizontal())
SetupHorizontalTrackBar();
else
SetupVerticalTrackBar();
}
/// <summary>
/// Tells the CrystalTrackBar that it needs to repaint the entire client area.
/// </summary>
public virtual void RedrawTrackBar()
{
Rectangle rc = new Rectangle(Location, Size);
base.InvalidateEx(rc);
}
#endregion
#region Thumb Methods
/// <summary>
/// Gets the string containing the resource name of the thumb image matching the "Normal" state.
/// </summary>
/// <returns>The string containing the resource name of the image.</returns>
protected static string GetNormalThumbImageName()
{
return CrystalTools.ToolstripThumbImageName;
}
/// <summary>
/// Gets the string containing the resource name of the thumb image matching the "Hover" state.
/// </summary>
/// <returns>The string containing the resource name of the image.</returns>
protected static string GetWarmThumbImageName()
{
return CrystalTools.ToolstripThumbWarmImageName;
}
/// <summary>
/// Gets the string containing the resource name of the thumb image matching the "Pressed" state.
/// </summary>
/// <returns>The string containing the resource name of the image.</returns>
protected static string GetHotThumbImageName()
{
return CrystalTools.ToolstripThumbHotImageName;
}
/// <summary>
/// Gets the string containing the resource name of the thumb image matching the "Disabled" state.
/// </summary>
/// <returns>The string containing the resource name of the image.</returns>
protected static string GetDisabledThumbImageName()
{
return CrystalTools.ToolstripThumbDisabledImageName;
}
/// <summary>
/// Gets the thumb image name that matches the given state.
/// </summary>
/// <param name="thumbState">The state of the desired thumb image.</param>
/// <returns></returns>
protected static string GetThumbImageName(CrystalThumbState thumbState)
{
switch (thumbState)
{
case CrystalThumbState.Pressed:
return GetHotThumbImageName();
case CrystalThumbState.Hover:
return GetWarmThumbImageName();
case CrystalThumbState.Disabled:
return GetDisabledThumbImageName();
default:
return GetNormalThumbImageName();
}
}
/// <summary>
/// Gets the image field matching a given thumb state.
/// </summary>
/// <param name="thumbState">The desired thumb state.</param>
/// <returns>The Image matching the thumb state.</returns>
protected Image GetCachedThumbImage(CrystalThumbState thumbState)
{
switch (thumbState)
{
case CrystalThumbState.Pressed:
return ThumbPressImage;
case CrystalThumbState.Hover:
return ThumbHoverImage;
case CrystalThumbState.Disabled:
return ThumbDisabledImage;
default:
return ThumbNormalImage;
}
}
/// <summary>
/// Sets the image field matching a given thumb state, allowing us to cache the image.
/// </summary>
/// <param name="thumbState">The desired thumb state.</param>
/// <param name="thumbImage">The image to cache.</param>
protected void SetCachedThumbImage(CrystalThumbState thumbState, Image thumbImage)
{
switch (thumbState)
{
case CrystalThumbState.Pressed:
ThumbPressImage = thumbImage;
break;
case CrystalThumbState.Hover:
ThumbHoverImage = thumbImage;
break;
case CrystalThumbState.Disabled:
ThumbDisabledImage = thumbImage;
break;
default:
ThumbNormalImage = thumbImage;
break;
}
}
protected virtual Image GetTransparentThumbImage(CrystalThumbState thumbState)
{
Image thumbImage = GetCachedThumbImage(thumbState);
if (thumbImage == null)
{
thumbImage = CrystalTools.GetAssemblyImage(
Assembly.GetAssembly(typeof(CrystalTrackBar)),
GetThumbImageName(thumbState));
thumbImage = CrystalTools.MakeTransparentImage(thumbImage);
SetCachedThumbImage(thumbState, thumbImage);
}
return thumbImage;
}
/// <summary>
/// Gets the thumb image matching the current thumb state.
/// </summary>
/// <returns>The image matching the current thumb state.</returns>
protected Image GetThumbImage()
{
return GetTransparentThumbImage(_thumbState);
}
/// <summary>
/// Draws the image of the thumb on the CrystalTrackBar.
/// </summary>
/// <param name="gfx">The Graphics object to draw on.</param>
/// <param name="thumbRect">The rectangle area where the thumb should be drawn.</param>
protected void DrawThumbImage(Graphics gfx, RectangleF thumbRect)
{
Image thumbImage = GetThumbImage();
if (thumbImage != null)
{
if (IsHorizontal())
{
// The thumb images in our assembly are smaller than the
// actual thumb rect supplied by TrackBarRenderer.
// Drawing smaller than the system rect allows us to erase
// the thumb easier.
thumbRect.Height = thumbImage.Height;
thumbRect.Width = thumbImage.Width;
}
else
{
// If the track bar is vertical, we're going to take
// the horizontal thumb image and rotate it to match
// the tickstyle.
Bitmap flipImage = new Bitmap(thumbImage);
if (_tickStyle == TickStyle.TopLeft)
flipImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
else
flipImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
thumbImage = flipImage;
// The thumb images in our assembly are smaller than the
// actual thumb rect supplied by TrackBarRenderer.
// Drawing smaller than the system rect allows us to erase
// the thumb easier.
thumbRect.Height = thumbImage.Height;
thumbRect.Width = thumbImage.Width;
}
gfx.DrawImage(thumbImage, thumbRect);
}
}
/// <summary>
/// Draws the thumb on the CrystalTrackBar.
/// </summary>
/// <param name="gfx">The Graphics object to draw on.</param>
protected virtual void DrawThumb(Graphics gfx)
{
// if the thumb is getting erased, we just want to draw
// the track bar and ticks. A second repaint will have us
// draw the thumb in an updated position later.
if (IsThumbErasing())
return;
DrawThumbImage(gfx, _thumbRectangle);
}
/// <summary>
/// Erases the thumb from the CrystalTrackBar.
/// </summary>
protected virtual void EraseThumb()
{
CrystalThumbState oldThumbState = _thumbState;
_thumbState = CrystalThumbState.Erased;
// This will force a repaint in the base class...
RectangleF _eraseRect = new RectangleF(_thumbRectangle.Location, _thumbRectangle.Size);
_eraseRect.Inflate(2.0f, 2.0f);
InvalidateEx(_thumbRectangle);
//...by the time we reach here, we know that the
// trackbar and ticks have been repainted without the thumb.
_thumbState = oldThumbState;
}
/// <summary>
/// Updates the thumb using the current tick value of the CrystalTrackBar.
/// </summary>
private void UpdateThumbRectangle()
{
if (IsHorizontal())
_thumbRectangle.X = CurrentTickXCoordinate();
else
_thumbRectangle.Y = CurrentTickYCoordinate();
}
#endregion
#region Helper Methods: States, Tick Adjustment, etc.
/// <summary>
/// Returns the current X or Y location depending on the orientation.
/// </summary>
/// <param name="location">A point within the CrystalTrackBar.</param>
/// <returns>Returns the current X or Y location depending on the orientation.</returns>
protected float CurrentLocation(Point location)
{
if (IsHorizontal())
return location.X;
else
return location.Y;
}
/// <summary>
/// Determines if the current thumb position on the track bar has changed.
/// </summary>
/// <param name="location">The current point location of the mouse.</param>
/// <returns>Boolean indicating that the thumb position has changed.</returns>
private bool HasTrackValueChanged(Point location)
{
#if CRYSTAL_TRACKBAR_DEBUG
System.Console.WriteLine("\nHasTrackValueChanged:");
System.Console.WriteLine("_currentTickValue = {0}, CurrentLocation(location) = {1}, CurrentThumbTick = {2}",
_currentTickValue, CurrentLocation(location), CurrentThumbTickCoordinate());
System.Console.WriteLine("Minimum = {0}, Maximum = {1}", Minimum, Maximum);
#endif
if (_currentTickValue < Maximum &&
CurrentLocation(location) > CurrentThumbTickCoordinate())
{
return true;
}
// Track movements to the next tick to the left, if
// cursor has moved halfway to the next tick.
else if (_currentTickValue > Minimum &&
CurrentLocation(location) < CurrentThumbTickCoordinate())
{
return true;
}
return false;
}
/// <summary>
/// Increments the value of the CrystalTrackBar.
/// </summary>
protected void IncrementValue(int changeValue)
{
if (_currentTickValue < Maximum)
{
EraseThumb();
_currentTickValue += changeValue;
if (_currentTickValue > Maximum)
_currentTickValue = Maximum;
#if CRYSTAL_TRACKBAR_DEBUG
System.Console.WriteLine("IncrementValue, _currentTickValue = {0}, changeValue = {1}", _currentTickValue, changeValue);
#endif
Value = _currentTickValue;
RedrawControl();
}
}
/// <summary>
/// Decrements the value of the CrystalTrackBar.
/// </summary>
protected void DecrementValue(int changeValue)
{
if (_currentTickValue > Minimum)
{
EraseThumb();
_currentTickValue -= changeValue;
if (_currentTickValue < Minimum)
_currentTickValue = Minimum;
#if CRYSTAL_TRACKBAR_DEBUG
System.Console.WriteLine("IncrementValue, _currentTickValue = {0}, changeValue = {1}", _currentTickValue, changeValue);
#endif
Value = _currentTickValue;
RedrawControl();
}
}
/// <summary>
/// Sets the value of the CrystalTrackBar to the first tick item.
/// </summary>
protected void FirstValue()
{
if (_currentTickValue != Minimum)
{
EraseThumb();
_currentTickValue = Minimum;
Value = Minimum;
RedrawControl();
}
}
/// <summary>
/// Sets the value of the CrystalTrackBar to the last tick item.
/// </summary>
protected void LastValue()
{
if (_currentTickValue != Maximum)
{
EraseThumb();
_currentTickValue = Maximum;
Value = Maximum;
RedrawControl();
}
}
/// <summary>
/// Determines if the thumb on the CrystalTrackBar has been clicked.
/// </summary>
/// <returns>Boolean value indicating that the thumb was pressed.</returns>
protected bool IsThumbPressed()
{
return (_thumbState == CrystalThumbState.Pressed);
}
/// <summary>
/// Determines if the thumb on the CrystalTrackBar is being erased.
/// </summary>
/// <returns>Boolean value indicating that the thumb is being erased.</returns>
protected bool IsThumbErasing()
{
return (_thumbState == CrystalThumbState.Erased);
}
/// <summary>
/// Determines if the CrystalTrackBar is horizontal.
/// </summary>
/// <returns>Boolean value indicating that the CrystalTrackBar is horizontal.</returns>
private bool IsHorizontal()
{
return (_orientation == Orientation.Horizontal);
}
#endregion
#region Overriden Methods
/// <summary>
/// Handles the Enabled state of the control.
/// </summary>
/// <param name="e">The event argument.</param>
protected override void OnEnabledChanged(EventArgs e)
{
base.OnEnabledChanged(e);
if (!Enabled)
_thumbState = CrystalThumbState.Disabled;
else
_thumbState = CrystalThumbState.Normal;
RedrawTrackBar();
}
/// <summary>
/// Provides the initial layout for the CrystalTrackBar.
/// </summary>
protected override void InitLayout()
{
SetupTrackBar();
base.InitLayout();
}
/// <summary>
/// Adjusts the CrystalTrackBar when the size has been changed.
/// </summary>
/// <param name="e">The event argument.</param>
protected override void OnSizeChanged(EventArgs e)
{
SetupTrackBar();
base.OnSizeChanged(e);
}
/// <summary>
/// Paints the CrystalTrackBar.
/// </summary>
/// <param name="e">The paint event argument.</param>
protected override void OnPaint(PaintEventArgs e)
{
DrawTrackBar(e.Graphics);
DrawTicks(e.Graphics);
DrawThumb(e.Graphics);
}
/// <summary>
/// Determine whether the user has clicked the mouse button on the track bar thumb.
/// </summary>
/// <param name="e">The mouse event argument.</param>
protected override void OnMouseDown(MouseEventArgs e)
{
if (!Enabled)
return;
Focus();
if (_thumbRectangle.Contains(e.Location))
{
_thumbState = CrystalThumbState.Pressed;
}
else
{
if ((IsThumbPressed()) || (IsThumbErasing()))
return;
#if CRYSTAL_TRACKBAR_DEBUG
System.Console.WriteLine("OnMouseDown, checking for LargeChange with Mouse click.");
#endif
if (CurrentLocation(e.Location) > CurrentThumbTickCoordinate())
{
IncrementValue(LargeChange);
}
else if (CurrentLocation(e.Location) < CurrentThumbTickCoordinate())
{
DecrementValue(LargeChange);
}
}
}
// Redraw the track bar thumb if the user has moved it.
/// <summary>
/// Determine whether the user has released the mouse button.
/// </summary>
/// <param name="e">The mouse event argument.</param>
protected override void OnMouseUp(MouseEventArgs e)
{
if (!Enabled)
return;
_thumbState = CrystalThumbState.Hover;
RedrawControl();
}
/// <summary>
/// Tracks the mouse movement within the CrystalTrackBar.
/// </summary>
/// <param name="e">The mouse event argument.</param>
protected override void OnMouseMove(MouseEventArgs e)
{
if (!Enabled)
return;
// The user is moving the thumb.
if (IsThumbPressed())
{
// if the value hasn't changed (the user is just holding at one position),
// then it may not necessary to erase/redraw the thumb,
// as it may cause too much flicker.
if (!HasTrackValueChanged(e.Location))
{
// BUG FIX: Without this call to redraw the control,
// the background gets erased when the user holds the mouse
// down, but does not move the track value.
if (TransparentMode)
RedrawControl();
#if CRYSTAL_TRACKBAR_DEBUG
System.Console.WriteLine("OnMouseMove, HasTrackValueChanged == false");
#endif
return;
}
int newTickPos = GetThumbTick(e.Location);
#if CRYSTAL_TRACKBAR_DEBUG
System.Console.WriteLine("OnMouseMove, before adjust, _currentTickValue = {0}, newTickPos = {1}", _currentTickValue, newTickPos);
#endif
// Track movements to the next tick to the right, if
// the cursor has moved halfway to the next tick.
if (newTickPos > _currentTickValue)
{
int delta = newTickPos - _currentTickValue;
IncrementValue(delta);
}
// Track movements to the next tick to the left, if
// cursor has moved halfway to the next tick.
else
{
int delta = _currentTickValue - newTickPos;
DecrementValue(delta);
}
#if CRYSTAL_TRACKBAR_DEBUG
System.Console.WriteLine("OnMouseMove, after adjust, _currentTickValue = {0}", _currentTickValue);
#endif
}
else
{
// ThumbState switches to hover because user is still
// in trackbar area.
_thumbState = CrystalThumbState.Hover;
#if CRYSTAL_TRACKBAR_DEBUG
System.Console.WriteLine("OnMouseMove, switch to Hover mode.");
#endif
// Don't call redraw here, it will cause more flicker than necessary.
//RedrawControl();
}
}
/// <summary>
/// Determines whether the mouse cursor has entered the CrystalTrackBar.
/// </summary>
/// <param name="e">The mouse event argument.</param>
protected override void OnMouseEnter(EventArgs e)
{
if (!Enabled)
return;
_thumbState = CrystalThumbState.Hover;
RedrawControl();
base.OnMouseEnter(e);
}
/// <summary>
/// Determines whether the mouse cursor has left the CrystalTrackBar.
/// </summary>
/// <param name="e">The mouse event argument.</param>
protected override void OnMouseLeave(EventArgs e)
{
if (!Enabled)
return;
_thumbState = CrystalThumbState.Normal;
RedrawControl();
base.OnMouseLeave(e);
}
/// <summary>
/// Processes the keystroke for the trackbar.
/// </summary>
/// <param name="keyData">The keystroke data.</param>
/// <returns>True if the CrystalTrackBar processes a keystroke, false if it does not process the keystroke.</returns>
public virtual bool ProcessKeystroke(Keys keyData)
{
switch (keyData)
{
case Keys.PageUp:
IncrementValue(LargeChange);
return true;
case Keys.PageDown:
DecrementValue(LargeChange);
return true;
case Keys.Left:
if (IsHorizontal())
DecrementValue(SmallChange);
return true;
case Keys.Right:
if (IsHorizontal())
IncrementValue(SmallChange);
return true;
case Keys.Up:
if (!IsHorizontal())
DecrementValue(SmallChange);
return true;
case Keys.Down:
if (!IsHorizontal())
IncrementValue(SmallChange);
return true;
case Keys.Home:
FirstValue();
return true;
case Keys.End:
LastValue();
return true;
}
return false;
}
/// <summary>
/// Processes the up, down, left, right, pgup, pgdn keystrokes.
/// Note this only takes effect when the property KeyboardControl is true.
/// </summary>
/// <param name="msg">The windows message.</param>
/// <param name="keyData">The keystroke data.</param>
/// <returns></returns>
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (KeyboardControl)
{
if (msg.Msg == (int)WindowsMessages.WM_KEYDOWN)
{
if (ProcessKeystroke(keyData))
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
#endregion
}
}