diff --git a/CUEControls/CUEControls.csproj b/CUEControls/CUEControls.csproj
index b7cf434..61ab018 100644
--- a/CUEControls/CUEControls.csproj
+++ b/CUEControls/CUEControls.csproj
@@ -52,6 +52,18 @@
FileSystemTreeView.cs
+
+ UserControl
+
+
+ MediaSlider.cs
+
+
+ Component
+
+
+ PeakMeterCtrl.cs
+
True
@@ -69,6 +81,7 @@
+
diff --git a/CUEControls/MediaSlider.Designer.cs b/CUEControls/MediaSlider.Designer.cs
new file mode 100644
index 0000000..6075dd4
--- /dev/null
+++ b/CUEControls/MediaSlider.Designer.cs
@@ -0,0 +1,46 @@
+namespace MediaSlider
+{
+ partial class MediaSlider
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ //
+ // MediaSlider
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.Transparent;
+ this.Margin = new System.Windows.Forms.Padding(0);
+ this.Name = "MediaSlider";
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ }
+}
diff --git a/CUEControls/MediaSlider.cs b/CUEControls/MediaSlider.cs
new file mode 100644
index 0000000..a04f1c5
--- /dev/null
+++ b/CUEControls/MediaSlider.cs
@@ -0,0 +1,4111 @@
+#region Author/About
+/************************************************************************************
+ * MediaSlider v1.3 *
+ * *
+ * Created: Febuary 7, 2010 *
+ * Built on: Win7 *
+ * Purpose: Animated slider control *
+ * Revision: 1.3 *
+ * Tested On: Win7 32bit, Vista 64bit, XP Professional *
+ * IDE: C# 2008 SP1 FW 3.5 *
+ * Referenced: Control Library VTD *
+ * Author: John Underhill (Steppenwolfe) *
+ * *
+ *************************************************************************************
+
+ You can not:
+ -Sell or redistribute this code or the binary for profit.
+ -Use this in spyware, malware, or any generally acknowledged form of malicious software.
+ -Remove or alter the above author accreditation, or this disclaimer.
+
+ You can:
+ -Use this code in your applications in any way you like.
+ -Use this in a published program, (a credit to vtdev.com would be nice)
+
+ I will not:
+ -Except any responsibility for this code whatsoever.
+ -Modify on demand.. you have the source code, read it, learn from it, write it.
+ -There is no guarantee of fitness, nor should you have any expectation of support.
+ -I further renounce any and all responsibilities for this code, in every way conceivable,
+ now, and for the rest of time.
+
+ Updates to 1.1
+ -fixed bug in incremental value
+ -added jump to position when track clicked w/ SmoothScrolling enabled
+ -fixed bug in ButtonSize property set
+ -fixed a couple of things in example form
+
+ Updates to 1.2
+ -Fixed false error condition on Value init
+ -Fixed ButtonSize property to update at design time
+ -Removed native properties that are incompatible with control
+ -Fixed control so that Minimum and Maximum values can both be negative -(but Maximum has to be more then Minimum)
+
+ Updates to 1.3
+ Fixed scrolling ceter pointer in button 'issue'
+ Fixed button resize bug
+ Fixed track resize bug
+ Fixed backwards scroll step bug
+
+ Cheers,
+ John
+ steppenwolfe_2000@yahoo.com
+ */
+#endregion
+
+#region Directives
+using System;
+using System.Text;
+using System.Timers;
+using System.Windows.Forms;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+#endregion
+
+namespace MediaSlider
+{
+ [DefaultEvent("ValueChanged"), ToolboxBitmap(typeof(MediaSlider), "tbimage")]
+ public partial class MediaSlider : UserControl
+ {
+ #region Constants
+ private const int TrackMinDepth = 2;
+ private const int TrackMaxDepth = 6;
+ #endregion
+
+ #region Enums
+ public enum AnimateSpeed : int
+ {
+ Fast = 1,
+ Normal = 5,
+ Slow = 20
+ }
+
+ public enum ButtonType : uint
+ {
+ Round = 0,
+ RoundedRectInline,
+ RoundedRectOverlap,
+ PointerUpRight,
+ PointerDownLeft,
+ Hybrid,
+ GlassInline,
+ GlassOverlap
+ }
+
+ public enum FlyOutStyle : int
+ {
+ None = 0,
+ OnFocus,
+ Persistant
+ }
+
+ public enum PresetType : uint
+ {
+ WmpVolume,
+ WmpTrackbar,
+ WmcTrackBar,
+ Office2007,
+ Glass
+ }
+
+ public enum TickMode : int
+ {
+ Standard = 0,
+ Composite,
+ Precision,
+ LargeStepped
+ }
+
+ public enum TrackType : uint
+ {
+ Progress = 0,
+ Value
+ }
+
+ private enum PointDirection : int
+ {
+ Bottom = 0,
+ Right
+ }
+ private enum SliderSelectedState : uint
+ {
+ None = 0,
+ Disabled,
+ Focused,
+ MouseLeave,
+ Pressed,
+ Depressed,
+ Hover
+ }
+
+ private enum ChangeType : uint
+ {
+ Large = 0,
+ Small
+ }
+
+ private enum HitTest : uint
+ {
+ Nowhere = 0,
+ Button,
+ Track
+ }
+ #endregion
+
+ #region Structs
+ [StructLayout(LayoutKind.Sequential)]
+ private struct RECT
+ {
+ public RECT(int x, int y, int right, int bottom)
+ {
+ this.Left = x;
+ this.Top = y;
+ this.Right = right;
+ this.Bottom = bottom;
+ }
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+ }
+ #endregion
+
+ #region API
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetDC(IntPtr handle);
+
+ [DllImport("user32.dll")]
+ private static extern int ReleaseDC(IntPtr handle, IntPtr hdc);
+
+ [DllImport("gdi32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
+
+ [DllImport("user32.dll")]
+ private static extern bool ValidateRect(IntPtr hWnd, ref RECT lpRect);
+
+ [DllImport("user32.dll")]
+ private static extern bool GetClientRect(IntPtr hWnd, ref RECT r);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool GetCursorPos(ref Point lpPoint);
+
+ [DllImport("user32.dll")]
+ private static extern bool ScreenToClient(IntPtr hWnd, ref Point lpPoint);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool PtInRect(ref RECT lprc, Point pt);
+ #endregion
+
+ #region Fields
+ private bool _bHasInitialized = false;
+ private bool _bPulseTimerOn = false;
+ private bool _bAnimated = false;
+ private bool _bSmoothScrolling = false;
+ private bool _bTrackShadow = false;
+ private bool _bShowButtonOnHover = false;
+ private bool _bInTarget = false;
+ private bool _bPropInit = false;
+ private bool _bFinishedPropRun = false;
+ private int _iLargeChange = 0;
+ private int _iMaximum = 10;
+ private int _iMinimum = 0;
+ private int _iSmallChange = 0;
+ private int _iValue = 0;
+ private int _iTrackDepth = 6;
+ private int _iButtonCornerRadius = 4;
+ private int _iTrackPadding = 2;
+ private int _iTickMaxLength = 4;
+ private int _iTickMinPadding = 2;
+ private int _iFlyOutMaxDepth = 16;
+ private int _iFlyOutMaxWidth = 12;
+ private int _iFlyOutSpacer = 6;
+ private int _iLinePos = 0;
+ private double _dButtonPosition = 0;
+ private float _fAnimationSize = .1f;
+
+ private Color _clrButtonAccentColor = Color.FromArgb(128, 64, 64, 64);
+ private Color _clrButtonBorderColor = Color.Black;
+ private Color _clrButtonColor = Color.FromArgb(160, 0, 0, 0);
+ private Color _clrBackColor = Color.Black;
+ private Color _clrTrackBorderColor = Color.FromArgb(160, Color.White);
+ private Color _clrTrackFillColor = Color.Transparent;
+ private Color _clrTrackProgressColor = Color.FromArgb(5, 101, 188);
+ private Color _clrTickColor = Color.DarkGray;
+ private Color _clrTrackShadowColor = Color.DarkGray;
+
+ private Size _szButtonSize = new Size(14, 14);
+ private Size _szMinSize = new Size(0, 0);
+ private Size _szMaxSize = new Size(0, 0);
+ private ButtonType _eButtonStyle = ButtonType.Round;
+ private TrackType _eTrackStyle = TrackType.Value;
+ private SliderSelectedState _eSliderState = SliderSelectedState.None;
+ private Orientation _eOrientation = Orientation.Horizontal;
+ private TickMode _eTickType = TickMode.Standard;
+ private TickStyle _eTickStyle = TickStyle.None;
+ private FlyOutStyle _eFlyOutOnFocus = FlyOutStyle.None;
+ private AnimateSpeed _eAnimationSpeed = AnimateSpeed.Normal;
+
+ private RECT _trackRect;
+ private RECT _buttonRect;
+
+ private Bitmap _bmpBackground;
+ private Bitmap _bmpButton;
+ private Bitmap _bmpSprite;
+ private FadeTimer _cPulseTimer;
+ private cStoreDc _cControlDc;
+ private cStoreDc _cTrackDc;
+ private cStoreDc _cAnimationDc;
+ private ErrorProvider ErrorHandler;
+
+ private delegate void ResetCallback();
+
+ [Description("Callback event for the FlyOut window")]
+ public event EventHandler FlyOutInfo;
+ #endregion
+
+ #region Events and Delegates
+ [Description("Raised when the Slider Value property changes")]
+ public event EventHandler ValueChanged;
+ [Description("Raised when the mSlider has scrolled.")]
+ public event EventHandler Scrolled;
+ #endregion
+
+ #region Constructor
+ public MediaSlider()
+ {
+ Init();
+ InitializeComponent();
+ }
+
+ private void Init()
+ {
+ CreateGraphicsObjects();
+ _bHasInitialized = true;
+
+ if (this.DesignMode)
+ {
+ ErrorHandler = new ErrorProvider();
+ this.Minimum = 0;
+ this.Maximum = 10;
+ this.SmallChange = 1;
+ this.LargeChange = 2;
+ }
+ _clrBackColor = Color.FromKnownColor(KnownColor.Control);
+ }
+ #endregion
+
+ #region Destructor
+ private void DeInit()
+ {
+ _bHasInitialized = false;
+ DestroyGraphicsObjects();
+ if (ErrorHandler != null)
+ ErrorHandler.Dispose();
+ }
+
+ public void Dispose()
+ {
+ DeInit();
+ }
+ #endregion
+
+ #region Properties
+ #region Hidden Properties
+ [Browsable(false)]
+ public new bool AllowDrop
+ {
+ get { return base.AllowDrop; }
+ set { base.AllowDrop = value; }
+ }
+ [Browsable(false)]
+ public new AnchorStyles Anchor
+ {
+ get { return base.Anchor; }
+ set { base.Anchor = value; }
+ }
+ [Browsable(false)]
+ public new bool AutoScroll
+ {
+ get { return base.AutoScroll; }
+ set { base.AutoScroll = value; }
+ }
+ [Browsable(false)]
+ public new Size AutoScrollMargin
+ {
+ get { return base.AutoScrollMargin; }
+ set { base.AutoScrollMargin = value; }
+ }
+ [Browsable(false)]
+ public new Size AutoScrollMinSize
+ {
+ get { return base.AutoScrollMinSize; }
+ set { base.AutoScrollMinSize = value; }
+ }
+ [Browsable(false)]
+ public new AutoSizeMode AutoSizeMode
+ {
+ get { return base.AutoSizeMode; }
+ set { base.AutoSizeMode = value; }
+ }
+ [Browsable(false)]
+ public new AutoValidate AutoValidate
+ {
+ get { return base.AutoValidate; }
+ set { base.AutoValidate = value; }
+ }
+ [Browsable(false)]
+ public new ImageLayout BackgroundImageLayout
+ {
+ get { return base.BackgroundImageLayout; }
+ set { base.BackgroundImageLayout = value; }
+ }
+ [Browsable(false)]
+ public new ContextMenu ContextMenuStrip
+ {
+ get { return base.ContextMenu; }
+ set { base.ContextMenu = value; }
+ }
+ [Browsable(false)]
+ public new DockStyle Dock
+ {
+ get { return base.Dock; }
+ set { base.Dock = value; }
+ }
+ [Browsable(false)]
+ public new Font Font
+ {
+ get { return base.Font; }
+ set { base.Font = value; }
+ }
+ [Browsable(false)]
+ public new Color ForeColor
+ {
+ get { return base.ForeColor; }
+ set { base.ForeColor = value; }
+ }
+ [Browsable(false)]
+ public new RightToLeft RightToLeft
+ {
+ get { return base.RightToLeft; }
+ set { base.RightToLeft = value; }
+ }
+ [Browsable(false)]
+ public new Padding Padding
+ {
+ get { return base.Padding; }
+ set { base.Padding = value; }
+ }
+ #endregion
+
+ #region Private Properties
+ private int TrackPadding
+ {
+ get { return _iTrackPadding; }
+ set { _iTrackPadding = value; }
+ }
+
+ private bool FinishedPropRun
+ {
+ get { return _bFinishedPropRun; }
+ set { _bFinishedPropRun = value; }
+ }
+
+ private int FlyOutMaxWidth
+ {
+ get { return _iFlyOutMaxWidth; }
+ set { _iFlyOutMaxWidth = value; }
+ }
+
+ private int FlyOutMaxDepth
+ {
+ get { return _iFlyOutMaxDepth; }
+ set { _iFlyOutMaxDepth = value; }
+ }
+
+ private int FlyOutSpacer
+ {
+ get { return _iFlyOutSpacer; }
+ set { _iFlyOutSpacer = value; }
+ }
+
+ private bool InTarget
+ {
+ get { return _bInTarget; }
+ set { _bInTarget = value; }
+ }
+
+ private int TickMaxLength
+ {
+ get { return _iTickMaxLength; }
+ set { _iTickMaxLength = value; }
+ }
+
+ private int TickMinPadding
+ {
+ get { return _iTickMinPadding; }
+ set { _iTickMinPadding = value; }
+ }
+ #endregion
+
+ #region Public Properties
+ /// Run the animation effect when focused
+ [Browsable(true), Category("Appearence"),
+ Description("Run the animation effect when focused")]
+ public bool Animated
+ {
+ get { return _bAnimated; }
+ set
+ {
+ _bAnimated = value;
+ if (!this.DesignMode)
+ {
+ if (this.Focused && _bAnimated)
+ StartPulseTimer();
+ else
+ StopPulseTimer();
+ DrawSlider();
+ }
+ }
+ }
+
+ /// Animation cycle speed
+ [Browsable(true), Category("Appearence"),
+ Description("Animation cycle speed")]
+ public AnimateSpeed AnimationSpeed
+ {
+ get { return _eAnimationSpeed; }
+ set { _eAnimationSpeed = value; }
+ }
+
+ /// Percentage of size of sprite height/width to track height/width [min .05 - max .2]
+ [Browsable(false),
+ Description("Percentage of size of sprite width to track width [min .05 - max .2]")]
+ public float AnimationSize
+ {
+ get { return _fAnimationSize; }
+ set
+ {
+ if (value < .02f)
+ _fAnimationSize = .02f;
+ else if (value < .2f)
+ _fAnimationSize = .2f;
+ else
+ _fAnimationSize = value;
+ }
+ }
+
+ /// Use an image for the slider background
+ [Browsable(true), Category("Appearence"),
+ Description("Use an image for the slider background")]
+ public new Bitmap BackgroundImage
+ {
+ get { return _bmpBackground; }
+ set
+ {
+ try
+ {
+ if (value != null && value.GetType() == typeof(Bitmap))
+ {
+ if (this.ErrorHandler != null)
+ this.ErrorHandler.Clear();
+ _bmpBackground = value;
+ base.Width = _bmpBackground.Width;
+ base.Height = _bmpBackground.Height;
+ PropertyChange();
+ }
+ else if (value != null && this.DesignMode)
+ {
+ throw new Exception("Invalid BackGroundImage Property Setting: Invalid image type. Base of image must be a Bitmap");
+ }
+ else if (value == null)
+ {
+ if (this.ErrorHandler != null)
+ this.ErrorHandler.Clear();
+ if (_bmpBackground != null)
+ _bmpBackground.Dispose();
+ _bmpBackground = null;
+ }
+ }
+ catch (Exception ex) { this.ErrorHandler.SetError(this, ex.Message); }
+ }
+ }
+
+ /// Modify button accent color
+ [Browsable(true), Category("Appearence"),
+ Description("Modify button accent color")]
+ public Color ButtonAccentColor
+ {
+ get { return _clrButtonAccentColor; }
+ set
+ {
+ _clrButtonAccentColor = value;
+ PropertyChange();
+ }
+ }
+
+ /// Modify button border color
+ [Browsable(true), Category("Appearence"),
+ Description("Modify button border color")]
+ public Color ButtonBorderColor
+ {
+ get { return _clrButtonBorderColor; }
+ set
+ {
+ _clrButtonBorderColor = value;
+ PropertyChange();
+ }
+ }
+
+ /// Modify button base color
+ [Browsable(true), Category("Appearence"),
+ Description("Modify button base color")]
+ public Color ButtonColor
+ {
+ get { return _clrButtonColor; }
+ set
+ {
+ _clrButtonColor = value;
+ PropertyChange();
+ }
+ }
+
+ /// Adjusts the slider buttons corner radius
+ [Browsable(false),
+ Description("Adjusts the slider buttons corner radius")]
+ public uint ButtonCornerRadius
+ {
+ get { return (uint)_iButtonCornerRadius; }
+ set { _iButtonCornerRadius = (int)value; }
+ }
+
+ /// Modify slider button size
+ [Browsable(true), Category("Appearence"), RefreshProperties(RefreshProperties.All),
+ Description("Modify slider button size")]
+ public Size ButtonSize
+ {
+ get { return _szButtonSize; }
+ set
+ {
+ _szButtonSize = value;
+ if (this.DesignMode && !this.AutoSize)
+ PropertyChange();
+ }
+ }
+
+ /// Set the button style
+ [Browsable(true), Category("Appearence"), RefreshProperties(RefreshProperties.All),
+ Description("Set the button style")]
+ public ButtonType ButtonStyle
+ {
+ get { return _eButtonStyle; }
+ set
+ {
+
+ if (this.FinishedPropRun && this.DesignMode && _eButtonStyle != value)
+ {
+ _eButtonStyle = value;
+ DefaultButtonSize(_eButtonStyle);
+ }
+ else
+ {
+ _eButtonStyle = value;
+ }
+ PropertyChange();
+ }
+ }
+
+ /// Returns the property initiated state
+ [Browsable(false),
+ Description("Returns the property initiated state")]
+ public bool IsInited
+ {
+ get { return this.Visible && _bPropInit; }
+ private set { _bPropInit = this.Visible && value; }
+ }
+
+ /// The number of clicks the slider moves in response to mouse clicks or pageup/pagedown
+ [Browsable(true), Category("Behavior"),
+ Description("The number of clicks the slider moves in response to mouse clicks or pageup/pagedown")]
+ public int LargeChange
+ {
+ get { return _iLargeChange; }
+ set
+ {
+ try
+ {
+ if (value < 1 && this.DesignMode && this.FinishedPropRun)
+ {
+ throw new Exception("Invalid LargeChange Property Setting: Large change can not be less then 1");
+ }
+ else
+ {
+ if (this.ErrorHandler != null)
+ this.ErrorHandler.Clear();
+ _iLargeChange = value;
+ PropertyChange();
+ }
+ }
+ catch (Exception ex) { this.ErrorHandler.SetError(this, ex.Message); }
+ }
+ }
+
+ /// The maximum value for the position of the slider
+ [Browsable(true), Category("Behavior"),
+ Description("The maximum value for the position of the slider")]
+ public int Maximum
+ {
+ get { return _iMaximum; }
+ set
+ {
+ try
+ {
+ if (value <= this.Minimum && this.FinishedPropRun)
+ {
+ if (this.DesignMode)
+ throw new Exception("Invalid Maximum Property Setting: Maximum can not be less then the Minimum value setting");
+ }
+ else
+ {
+ if (this.ErrorHandler != null)
+ this.ErrorHandler.Clear();
+ _iMaximum = value;
+ PropertyChange();
+ }
+ }
+ catch (Exception ex) { this.ErrorHandler.SetError(this, ex.Message); }
+ finally
+ {
+ if (!this.DesignMode)
+ SliderFlyOut = _eFlyOutOnFocus;
+ }
+ }
+ }
+
+ /// The maximum Size value for the control
+ [Browsable(true), Category("Behavior"),
+ Description("The maximum Size value for the control [private set]")]
+ public Size MaxSize
+ {
+ get { return _szMaxSize; }
+ private set { _szMaxSize = value; }
+ }
+
+ /// The minimum value for the position of the slider
+ [Browsable(true), Category("Behavior"),
+ Description("The minimum value for the position of the slider")]
+ public int Minimum
+ {
+ get { return _iMinimum; }
+ set
+ {
+ try
+ {
+ if (value >= this.Maximum && this.FinishedPropRun)
+ {
+ if (this.DesignMode)
+ throw new Exception("Invalid Minimum Property Setting: Minimum can not be more then the Maximum value setting");
+ }
+ else
+ {
+ if (this.ErrorHandler != null)
+ this.ErrorHandler.Clear();
+ _iMinimum = value;
+ PropertyChange();
+ }
+ }
+ catch (Exception ex) { this.ErrorHandler.SetError(this, ex.Message); }
+ }
+ }
+
+ /// The minimum Size value for the control
+ [Browsable(true), Category("Behavior"),
+ Description("The minimum Size value for the control [private set]")]
+ public Size MinSize
+ {
+ get { return _szMinSize; }
+ private set { _szMinSize = value; }
+ }
+
+ /// The orientation of the control
+ [Browsable(true), Category("Appearence"), RefreshProperties(RefreshProperties.All),
+ Description("The orientation of the control")]
+ public Orientation Orientation
+ {
+ get { return _eOrientation; }
+ set
+ {
+ _eOrientation = value;
+ if (this.FinishedPropRun && this.DesignMode && _eOrientation != value)
+ {
+ _eOrientation = value;
+ DefaultButtonSize(_eButtonStyle);
+ }
+ else
+ {
+ _eOrientation = value;
+ }
+ PropertyChange();
+ }
+ }
+
+ /// Returns the slider position to a floating point, requires SmoothScrolling set to true
+ [Browsable(false),
+ Description("Returns the slider position to a floating point, requires SmoothScrolling set to true")]
+ public double PrecisionValue
+ {
+ get { return IncrementalValue(); }
+ }
+
+ /// Show the slider button only when control is focused or mouse is hovering
+ [Browsable(true), Category("Appearence"),
+ Description("Show the slider button only when control is focused or mouse is hovering")]
+ public bool ShowButtonOnHover
+ {
+ get { return _bShowButtonOnHover; }
+ set { _bShowButtonOnHover = value; }
+ }
+
+ /// Enable the flyout caption window
+ [Browsable(true), Category("Appearence"),
+ Description("Enable the flyout caption window")]
+ public FlyOutStyle SliderFlyOut
+ {
+ get { return _eFlyOutOnFocus; }
+ set
+ {
+ _eFlyOutOnFocus = value;
+ if (_eFlyOutOnFocus != FlyOutStyle.None)
+ {
+ if (Orientation == Orientation.Horizontal)
+ {
+ this.FlyOutMaxDepth = 14;
+ this.FlyOutSpacer = 6;
+ if (this.Maximum < 10)
+ {
+ this.FlyOutMaxWidth = 10;
+ this.TrackPadding = 4;
+ }
+ else if (this.Maximum < 100)
+ {
+ this.FlyOutMaxWidth = 20;
+ this.TrackPadding = 6;
+ }
+ else if (this.Maximum < 1000)
+ {
+ this.FlyOutMaxWidth = 30;
+ this.TrackPadding = 12;
+ }
+ else if (this.Maximum > 999)
+ {
+ // probably time
+ this.FlyOutMaxWidth = 54;
+ this.TrackPadding = 24;
+ }
+ }
+ else
+ {
+ if (this.Minimum < 0)
+ {
+ // max 2 digit vertical
+ this.FlyOutSpacer = 2;
+ this.FlyOutMaxDepth = 30;
+ this.FlyOutMaxWidth = 20;
+ this.TrackPadding = 12;
+ }
+ else
+ {
+ // max 2 digit vertical
+ this.FlyOutSpacer = 2;
+ this.FlyOutMaxDepth = 20;
+ this.FlyOutMaxWidth = 18;
+ this.TrackPadding = 5;
+ }
+ }
+ }
+ else
+ {
+ this.FlyOutMaxDepth = 0;
+ this.TrackPadding = 2;
+ }
+ PropertyChange();
+ }
+ }
+
+ /// The number of positions the slider movers in response to arrow keys
+ [Browsable(true), Category("Behavior"),
+ Description("The number of positions the slider movers in response to arrow keys")]
+ public int SmallChange
+ {
+ get { return _iSmallChange; }
+ set
+ {
+ try
+ {
+ if (value < 1 && this.DesignMode && this.FinishedPropRun)
+ {
+ throw new Exception("Invalid SmallChange Property Setting: Small change can not be less then 1");
+ }
+ else
+ {
+ if (this.ErrorHandler != null)
+ this.ErrorHandler.Clear();
+ _iSmallChange = value;
+ PropertyChange();
+ }
+ }
+ catch (Exception ex) { this.ErrorHandler.SetError(this, ex.Message); }
+ }
+ }
+
+ /// Run the animation effect when focused
+ [Browsable(true), Category("Behavior"),
+ Description("Enable smooth scrolling style")]
+ public bool SmoothScrolling
+ {
+ get { return _bSmoothScrolling; }
+ set { _bSmoothScrolling = value; }
+ }
+
+ /// Modify slider tick color
+ [Browsable(true), Category("Appearence"),
+ Description("Modify slider tick color")]
+ public Color TickColor
+ {
+ get { return _clrTickColor; }
+ set
+ {
+ _clrTickColor = value;
+ PropertyChange();
+ }
+ }
+
+ /// Select the tickstyle
+ [Browsable(true), Category("Appearence"),
+ Description("Select the tickstyle")]
+ public TickStyle TickStyle
+ {
+ get { return _eTickStyle; }
+ set
+ {
+ _eTickStyle = value;
+ PropertyChange();
+ }
+ }
+
+ /// Select the tick drawing style
+ [Browsable(true), Category("Appearence"),
+ Description("Select the tick drawing style")]
+ public TickMode TickType
+ {
+ get { return _eTickType; }
+ set
+ {
+ _eTickType = value;
+ PropertyChange();
+ }
+ }
+
+ /// Modify slider border color
+ [Browsable(true), Category("Appearence"),
+ Description("Modify slider border color")]
+ public Color TrackBorderColor
+ {
+ get { return _clrTrackBorderColor; }
+ set
+ {
+ _clrTrackBorderColor = value;
+ PropertyChange();
+ }
+ }
+
+ /// Adjust the slider track depth
+ [Browsable(true), Category("Appearence"), RefreshProperties(RefreshProperties.All),
+ Description("Adjust the slider track depth")]
+ public int TrackDepth
+ {
+ get { return _iTrackDepth; }
+ set
+ {
+ _iTrackDepth = value;
+ if (this.DesignMode && !this.AutoSize)
+ PropertyChange();
+ }
+ }
+
+ /// Set the track fill color
+ [Browsable(true), Category("Appearence"),
+ Description("Set the track fill color")]
+ public Color TrackFillColor
+ {
+ get { return _clrTrackFillColor; }
+ set
+ {
+ _clrTrackFillColor = value;
+ PropertyChange();
+ }
+ }
+
+ /// Set the track progress color
+ [Browsable(true), Category("Appearence"),
+ Description("Set the track progress color")]
+ public Color TrackProgressColor
+ {
+ get { return _clrTrackProgressColor; }
+ set
+ {
+ _clrTrackProgressColor = value;
+ PropertyChange();
+ }
+ }
+
+ /// Enable track border shadow
+ [Browsable(true), Category("Appearence"),
+ Description("Enable track shadow")]
+ public bool TrackShadow
+ {
+ get { return _bTrackShadow; }
+ set
+ {
+ _bTrackShadow = value;
+ PropertyChange();
+ }
+ }
+
+ /// Modify track shadow color
+ [Browsable(true), Category("Appearence"),
+ Description("Modify track shadow color")]
+ public Color TrackShadowColor
+ {
+ get { return _clrTrackShadowColor; }
+ set
+ {
+ _clrTrackShadowColor = value;
+ PropertyChange();
+ }
+ }
+
+ /// Modify the display style of track
+ [Browsable(true), Category("Appearence"),
+ Description("Modify the display style of track")]
+ public TrackType TrackStyle
+ {
+ get { return _eTrackStyle; }
+ set
+ {
+ _eTrackStyle = value;
+ PropertyChange();
+ }
+ }
+
+ /// The position of the slider
+ [Browsable(true), Category("Behavior"),
+ Description("The position of the slider")]
+ public int Value
+ {
+ get { return _iValue; }
+ set
+ {
+ this.IsInited = !this.DesignMode;
+ try
+ {
+ if (value > this.Maximum)
+ {
+ if (this.DesignMode && this.FinishedPropRun)
+ throw new Exception("Invalid Value Property Setting: Value can not be more then Maximum setting");
+ else
+ _iValue = this.Maximum;
+ }
+ else if (value < this.Minimum)
+ {
+ if (this.DesignMode && this.FinishedPropRun)
+ throw new Exception("Invalid Value Property Setting: Value can not be less then Minimum setting");
+ else
+ _iValue = this.Minimum;
+ }
+ else
+ {
+ if (this.ErrorHandler != null)
+ this.ErrorHandler.Clear();
+ _iValue = value;
+ }
+
+ if (this.DesignMode)
+ _dButtonPosition = IncrementalValue();
+
+ if (!this.FinishedPropRun)
+ {
+ PropertyChange();
+ this.FinishedPropRun = true;
+ }
+ else if (!this.DesignMode)
+ {
+ _dButtonPosition = IncrementalValue();
+ if (ValueChanged != null)
+ ValueChanged(this, new EventArgs());
+ DrawSlider();
+ }
+ }
+ catch (Exception ex) { this.ErrorHandler.SetError(this, ex.Message); }
+ }
+ }
+ #endregion
+ #endregion
+
+ #region Overrides
+ protected override void OnCreateControl()
+ {
+ base.OnCreateControl();
+ }
+
+ protected override void OnHandleCreated(EventArgs e)
+ {
+ Init();
+ base.OnHandleCreated(e);
+ }
+
+ protected override void OnHandleDestroyed(EventArgs e)
+ {
+ DeInit();
+ base.OnHandleDestroyed(e);
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ if (_bHasInitialized)
+ DrawSlider();
+ base.OnPaint(e);
+ }
+
+ protected override void OnBackColorChanged(EventArgs e)
+ {
+ Init();
+ base.OnBackColorChanged(e);
+ }
+
+ protected override void OnGotFocus(EventArgs e)
+ {
+ if (!this.InTarget)
+ {
+ _eSliderState = SliderSelectedState.Focused;
+ DrawSlider();
+ }
+ base.OnGotFocus(e);
+ }
+
+ protected override void OnLostFocus(EventArgs e)
+ {
+ _eSliderState = SliderSelectedState.None;
+ DrawSlider();
+ base.OnLostFocus(e);
+ }
+
+ protected override void OnMouseClick(MouseEventArgs e)
+ {
+ if (e.Button == MouseButtons.Left)
+ {
+ HitTest tst = SliderHitTest();
+ if (tst == HitTest.Track || tst == HitTest.Nowhere)
+ {
+ int pos;
+ if (Orientation == Orientation.Horizontal)
+ pos = e.X;
+ else
+ pos = e.Y;
+ if (this.SmoothScrolling)
+ {
+ ScrollThis(pos);
+ }
+ else
+ {
+ if (pos < IncrementalValue())
+ ScrollChange(ChangeType.Large, (Orientation == Orientation.Horizontal));
+ else
+ ScrollChange(ChangeType.Large, (Orientation != Orientation.Horizontal));
+ }
+ }
+ }
+ base.OnMouseClick(e);
+ }
+
+ protected override void OnMouseDown(MouseEventArgs e)
+ {
+ this.InTarget = (SliderHitTest() == HitTest.Button);
+ if (this.InTarget)
+ _eSliderState = SliderSelectedState.Pressed;
+ else
+ _eSliderState = SliderSelectedState.Focused;
+ DrawSlider();
+ base.OnMouseDown(e);
+ }
+
+ protected override void OnMouseHover(EventArgs e)
+ {
+ _eSliderState = SliderSelectedState.Hover;
+ DrawSlider();
+ base.OnMouseHover(e);
+ }
+
+ protected override void OnMouseUp(MouseEventArgs e)
+ {
+ _eSliderState = SliderSelectedState.Depressed;
+ _bInTarget = false;
+ DrawSlider();
+ base.OnMouseUp(e);
+ }
+
+ protected override void OnMouseLeave(EventArgs e)
+ {
+ _eSliderState = SliderSelectedState.MouseLeave;
+ DrawSlider();
+ base.OnMouseLeave(e);
+ }
+
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ if (e.Button == MouseButtons.Left && _bInTarget)
+ {
+ if (Orientation == Orientation.Horizontal)
+ ScrollThis(e.X);
+ else
+ ScrollThis(e.Y);
+ }
+ base.OnMouseMove(e);
+ }
+
+ protected override void OnResize(EventArgs e)
+ {
+ PropertyChange();
+ base.OnResize(e);
+ }
+
+ protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+ {
+ switch (keyData)
+ {
+ case Keys.Left:
+ ScrollChange(ChangeType.Small, true);
+ DrawSlider();
+ return true;
+ case Keys.Right:
+ ScrollChange(ChangeType.Small, false);
+ DrawSlider();
+ return true;
+ case Keys.Up:
+ ScrollChange(ChangeType.Small, false);
+ DrawSlider();
+ return true;
+ case Keys.Down:
+ ScrollChange(ChangeType.Small, true);
+ DrawSlider();
+ return true;
+ case Keys.Home:
+ this.Value = this.Minimum;
+ return true;
+ case Keys.End:
+ this.Value = this.Maximum;
+ return true;
+ }
+ return base.ProcessCmdKey(ref msg, keyData);
+ }
+ #endregion
+
+ #region Methods
+ #region Graphics
+ #region Drawing
+ /// Drawing hub
+ private void DrawSlider()
+ {
+ Rectangle bounds = new Rectangle(0, 0, this.Width, this.Height);
+ using (Graphics g = Graphics.FromHdc(_cControlDc.Hdc))
+ {
+ DrawTrack();
+ if (this.SliderFlyOut == FlyOutStyle.Persistant)
+ DrawFlyOut(g);
+
+ switch (_eSliderState)
+ {
+ case SliderSelectedState.None:
+ {
+ if (_bPulseTimerOn)
+ StopPulseTimer();
+ if (!ShowButtonOnHover)
+ DrawButton(g, bounds, 1f);
+ break;
+ }
+ case SliderSelectedState.Disabled:
+ {
+ DrawButton(g, bounds, -1f);
+ break;
+ }
+ case SliderSelectedState.MouseLeave:
+ {
+ if (!ShowButtonOnHover || _bPulseTimerOn)
+ {
+ if (this.Focused)
+ DrawButton(g, bounds, 1.2f);
+ else
+ DrawButton(g, bounds, 1f);
+ }
+ break;
+ }
+ case SliderSelectedState.Hover:
+ {
+ if (this.SliderFlyOut == FlyOutStyle.OnFocus)
+ DrawFlyOut(g);
+ DrawButton(g, bounds, 1.2f);
+ break;
+ }
+ case SliderSelectedState.Depressed:
+ case SliderSelectedState.Focused:
+ {
+ if (!_bPulseTimerOn)
+ {
+ if (this.SliderFlyOut == FlyOutStyle.OnFocus)
+ DrawFlyOut(g);
+ DrawButton(g, bounds, 1.2f);
+ if (this.Animated)
+ StartPulseTimer();
+ }
+ else if (!this.InTarget)
+ {
+ DrawButton(g, bounds, 1.0f);
+ }
+ break;
+ }
+ case SliderSelectedState.Pressed:
+ {
+ if (_bPulseTimerOn)
+ StopPulseTimer();
+ if (this.SliderFlyOut == FlyOutStyle.OnFocus)
+ DrawFlyOut(g);
+ DrawButton(g, bounds, .9f);
+ break;
+ }
+ }
+ }
+
+ if (!_bPulseTimerOn)
+ {
+ // draw buffer to control
+ using (Graphics g = Graphics.FromHwnd(this.Handle))
+ {
+ BitBlt(g.GetHdc(), 0, 0, _cControlDc.Width, _cControlDc.Height, _cControlDc.Hdc, 0, 0, 0xCC0020);
+ g.ReleaseHdc();
+ }
+ RECT r = new RECT(0, 0, this.Width, this.Height);
+ ValidateRect(this.Handle, ref r);
+ }
+ }
+
+ /// Backfill the buffer
+ private void DrawBackGround(Graphics g, Rectangle bounds)
+ {
+ using (Brush br = new SolidBrush(this.BackColor))
+ g.FillRectangle(br, bounds);
+ }
+
+ /// Adjust gamma of an image [not used]
+ private void DrawBrightImage(Graphics g, Image img, Rectangle bounds, float gamma)
+ {
+ try
+ {
+ using (Bitmap buttonImage = new Bitmap(img))
+ {
+ using (ImageAttributes imageAttr = new ImageAttributes())
+ {
+ if (gamma > .9f)
+ gamma = .9f;
+ if (gamma < .2f)
+ gamma = .2f;
+ // raise gamma
+ imageAttr.SetGamma(gamma);
+ g.DrawImage(buttonImage,
+ bounds,
+ 0, 0,
+ buttonImage.Width,
+ buttonImage.Height,
+ GraphicsUnit.Pixel,
+ imageAttr);
+ }
+ }
+ }
+ catch { }
+ }
+
+ private void DrawButton(Graphics g, Rectangle bounds, float level)
+ {
+ Rectangle buttonRect = GetButtonRectangle();
+ if (level != 1f)
+ {
+ using (ImageAttributes ia = new ImageAttributes())
+ {
+ ColorMatrix cm = new ColorMatrix();
+ if (level == -1)
+ {
+ cm.Matrix00 = 1f;//r
+ cm.Matrix11 = 1f;//g
+ cm.Matrix22 = 1f;//b
+ cm.Matrix33 = .7f;//a
+ cm.Matrix44 = 1f;//w
+ }
+ else
+ {
+ cm.Matrix00 = level;
+ cm.Matrix11 = level;
+ cm.Matrix22 = level;
+ cm.Matrix33 = 1f;
+ cm.Matrix44 = 1f;
+ }
+ ia.SetColorMatrix(cm);
+ g.DrawImage(_bmpButton, buttonRect, 0, 0, _bmpButton.Width, _bmpButton.Height, GraphicsUnit.Pixel, ia);
+ }
+ }
+ else
+ {
+ DrawImage(g, _bmpButton, buttonRect);
+ }
+ }
+
+ /// Draw a disabled image using the control
+ private void DrawDisabledImage(Graphics g, Image image, Rectangle bounds)
+ {
+ ControlPaint.DrawImageDisabled(g, image, bounds.X, bounds.Y, Color.Transparent);
+ }
+
+ /// Draw an unaltered image
+ private void DrawImage(Graphics g, Image image, Rectangle bounds)
+ {
+ g.DrawImage(image, bounds);
+ }
+
+ /// Draw the slider ticks
+ private void DrawTicks(Graphics g, Rectangle bounds)
+ {
+ Rectangle trackRect = GetTrackRectangle();
+ float increment = (float)Increment();
+ increment = (float)Increment();
+ int count = (int)(IncrementScale());
+
+ float endcap = (Orientation == Orientation.Horizontal ? (float)trackRect.Right - (1 + this.ButtonSize.Width / 2) : (float)trackRect.Bottom - (1 + this.ButtonSize.Height / 2));
+ float offset = 0;
+ int shadowlen = this.TickMaxLength - 1;
+ int spacer = this.TickMaxLength + this.TickMinPadding;
+ RectangleF buttonRect = GetButtonRectangle();
+
+ switch (this.TickType)
+ {
+ #region Composite Style
+ case TickMode.Composite:
+ {
+ using (GraphicsMode md = new GraphicsMode(g, SmoothingMode.None))
+ {
+ switch (this.TickStyle)
+ {
+ case TickStyle.Both:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float top = buttonRect.Top - spacer;
+ float bottom = buttonRect.Bottom + spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(val, top), new PointF(val, top + this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, top + 1), new PointF(val + 1, top + shadowlen));
+ g.DrawLine(pn2, new PointF(val, bottom), new PointF(val, bottom - this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, bottom), new PointF(val + 1, bottom - shadowlen));
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(val, top), new PointF(val, top + 2));
+ g.DrawLine(pn, new PointF(val, bottom), new PointF(val, bottom - 2));
+ }
+ }
+ }
+ }
+ else
+ {
+ float left = buttonRect.Left - spacer;
+ float right = buttonRect.Right + spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(left, val), new PointF(left + this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(left + 1, val + 1), new PointF(left + shadowlen, val + 1));
+ g.DrawLine(pn2, new PointF(right, val), new PointF(right - this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(right, val + 1), new PointF(right - shadowlen, val + 1));
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(left, val), new PointF(left + 2, val));
+ g.DrawLine(pn, new PointF(right, val), new PointF(right - 2, val));
+ }
+ }
+ }
+ }
+ break;
+ }
+ case TickStyle.BottomRight:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float bottom = buttonRect.Bottom + spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(val, bottom), new PointF(val, bottom - this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, bottom), new PointF(val + 1, bottom - shadowlen));
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(val, bottom), new PointF(val, bottom - 2));
+ }
+ }
+ }
+ }
+ else
+ {
+ float right = buttonRect.Right + spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(right, val), new PointF(right - this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(right, val + 1), new PointF(right - shadowlen, val + 1));
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(right, val), new PointF(right - 2, val));
+ }
+ }
+ }
+ }
+ break;
+ }
+ case TickStyle.TopLeft:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float top = buttonRect.Top - spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(val, top), new PointF(val, top + this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, top + 1), new PointF(val + 1, top + shadowlen));
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(val, top), new PointF(val, top + 2));
+ }
+ }
+ }
+ }
+ else
+ {
+ float left = buttonRect.Left - spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(left, val), new PointF(left + this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(left + 1, val + 1), new PointF(left + shadowlen, val + 1));
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(left, val), new PointF(left + 2, val));
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ #endregion
+
+ #region Large Stepped Style
+ case TickMode.LargeStepped:
+ {
+ using (GraphicsMode md = new GraphicsMode(g, SmoothingMode.None))
+ {
+ switch (this.TickStyle)
+ {
+ case TickStyle.Both:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float top = buttonRect.Top - spacer;
+ float bottom = buttonRect.Bottom + spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ if (Mod(i, this.LargeChange))
+ {
+ val = (increment * i) + offset;
+ g.DrawLine(pn2, new PointF(val, top), new PointF(val, top + this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, top + 1), new PointF(val + 1, top + shadowlen));
+ g.DrawLine(pn2, new PointF(val, bottom), new PointF(val, bottom - this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, bottom), new PointF(val + 1, bottom - shadowlen));
+ }
+ }
+ }
+ }
+ else
+ {
+ float left = buttonRect.Left - spacer;
+ float right = buttonRect.Right + spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ if (Mod(i, this.LargeChange))
+ {
+ val = (increment * i) + offset;
+ g.DrawLine(pn2, new PointF(left, val), new PointF(left + this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(left + 1, val + 1), new PointF(left + shadowlen, val + 1));
+ g.DrawLine(pn2, new PointF(right, val), new PointF(right - this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(right, val + 1), new PointF(right - shadowlen, val + 1));
+ }
+ }
+ }
+ }
+ break;
+ }
+ case TickStyle.BottomRight:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float bottom = buttonRect.Bottom + spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ if (Mod(i, this.LargeChange))
+ {
+ val = (increment * i) + offset;
+ g.DrawLine(pn2, new PointF(val, bottom), new PointF(val, bottom - this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, bottom), new PointF(val + 1, bottom - shadowlen));
+ }
+ }
+ }
+ }
+ else
+ {
+ float right = buttonRect.Right + spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(right, val), new PointF(right - this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(right, val + 1), new PointF(right - shadowlen, val + 1));
+ }
+ }
+ }
+ }
+ break;
+ }
+ case TickStyle.TopLeft:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float top = buttonRect.Top - spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(val, top), new PointF(val, top + this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, top + 1), new PointF(val + 1, top + shadowlen));
+ }
+ }
+ }
+ }
+ else
+ {
+ float left = buttonRect.Left - spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(left, val), new PointF(left + this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(left + 1, val + 1), new PointF(left + shadowlen, val + 1));
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ #endregion
+
+ #region Precision Style
+ case TickMode.Precision:
+ {
+ using (GraphicsMode md = new GraphicsMode(g, SmoothingMode.None))
+ {
+ float split = increment * .5f;
+ bool valid = split > 2;
+ switch (this.TickStyle)
+ {
+ case TickStyle.Both:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float top = buttonRect.Top - spacer;
+ float bottom = buttonRect.Bottom + spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(val, top), new PointF(val, top + this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, top + 1), new PointF(val + 1, top + shadowlen));
+ g.DrawLine(pn2, new PointF(val, bottom), new PointF(val, bottom - this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, bottom), new PointF(val + 1, bottom - shadowlen));
+ if (valid && val < endcap)
+ {
+ g.DrawLine(pn, new PointF(val + split, top), new PointF(val + split, top + 1));
+ g.DrawLine(pn, new PointF(val + split, bottom), new PointF(val + split, bottom - 1));
+ }
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(val, top), new PointF(val, top + 2));
+ g.DrawLine(pn, new PointF(val, bottom), new PointF(val, bottom - 2));
+ if (valid && val < endcap)
+ {
+ g.DrawLine(pn, new PointF(val + split, top), new PointF(val + split, top + 1));
+ g.DrawLine(pn, new PointF(val + split, bottom), new PointF(val + split, bottom - 1));
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ float left = buttonRect.Left - spacer;
+ float right = buttonRect.Right + spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(left, val), new PointF(left + this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(left + 1, val + 1), new PointF(left + shadowlen, val + 1));
+ g.DrawLine(pn2, new PointF(right, val), new PointF(right - this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(right, val + 1), new PointF(right - shadowlen, val + 1));
+ if (valid && val < endcap)
+ {
+ g.DrawLine(pn, new PointF(left, val + split), new PointF(left + 1, val + split));
+ g.DrawLine(pn, new PointF(right, val + split), new PointF(right - 1, val + split));
+ }
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(left, val), new PointF(left + 2, val));
+ g.DrawLine(pn, new PointF(right, val), new PointF(right - 2, val));
+ if (valid && val < endcap)
+ {
+ g.DrawLine(pn, new PointF(left, val + split), new PointF(left + 1, val + split));
+ g.DrawLine(pn, new PointF(right, val + split), new PointF(right - 1, val + split));
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ case TickStyle.BottomRight:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float bottom = buttonRect.Bottom + spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(val, bottom), new PointF(val, bottom - this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, bottom), new PointF(val + 1, bottom - shadowlen));
+ if (valid && val < endcap)
+ g.DrawLine(pn, new PointF(val + split, bottom), new PointF(val + split, bottom - 1));
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(val, bottom), new PointF(val, bottom - 2));
+ if (valid && val < endcap)
+ g.DrawLine(pn, new PointF(val + split, bottom), new PointF(val + split, bottom - 1));
+ }
+ }
+ }
+ }
+ else
+ {
+ float right = buttonRect.Right + spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(right, val), new PointF(right - this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(right, val + 1), new PointF(right - shadowlen, val + 1));
+ if (valid && val < endcap)
+ g.DrawLine(pn, new PointF(right, val + split), new PointF(right - 2, val + split));
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(right, val), new PointF(right - 2, val));
+ if (valid && val < endcap)
+ g.DrawLine(pn, new PointF(right, val + split), new PointF(right - 2, val + split));
+ }
+ }
+ }
+ }
+ break;
+ }
+ case TickStyle.TopLeft:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float top = buttonRect.Top - spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(val, top), new PointF(val, top + this.TickMaxLength));
+ g.DrawLine(pn3, new PointF(val + 1, top + 1), new PointF(val + 1, top + shadowlen));
+ if (valid && val < endcap)
+ g.DrawLine(pn, new PointF(val + split, top), new PointF(val + split, top + 1));
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(val, top), new PointF(val, top + 2));
+ if (valid && val < endcap)
+ g.DrawLine(pn, new PointF(val + split, top), new PointF(val + split, top + 1));
+ }
+ }
+ }
+ }
+ else
+ {
+ float left = buttonRect.Left - spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ if (Mod(i, this.LargeChange))
+ {
+ g.DrawLine(pn2, new PointF(left, val), new PointF(left + this.TickMaxLength, val));
+ g.DrawLine(pn3, new PointF(left + 1, val + 1), new PointF(left + shadowlen, val + 1));
+ if (valid && val < endcap)
+ g.DrawLine(pn, new PointF(left, val + split), new PointF(left + 2, val + split));
+ }
+ else
+ {
+ g.DrawLine(pn, new PointF(left, val), new PointF(left + 2, val));
+ if (valid && val < endcap)
+ g.DrawLine(pn, new PointF(left, val + split), new PointF(left + 2, val + split));
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ #endregion
+
+ #region Standard Tick Style
+ case TickMode.Standard:
+ {
+ using (GraphicsMode md = new GraphicsMode(g, SmoothingMode.None))
+ {
+ switch (this.TickStyle)
+ {
+ case TickStyle.Both:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float top = buttonRect.Top - spacer;
+ float bottom = buttonRect.Bottom + spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ g.DrawLine(pn, new PointF(val, top), new PointF(val, top + 2));
+ g.DrawLine(pn, new PointF(val, bottom), new PointF(val, bottom - 2));
+ }
+ }
+ }
+ else
+ {
+ float left = buttonRect.Left - spacer;
+ float right = buttonRect.Right + spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ g.DrawLine(pn, new PointF(left, val), new PointF(left + 2, val));
+ g.DrawLine(pn, new PointF(right, val), new PointF(right - 2, val));
+ }
+ }
+ }
+ break;
+ }
+ case TickStyle.BottomRight:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float bottom = buttonRect.Bottom + spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ g.DrawLine(pn, new PointF(val, bottom), new PointF(val, bottom - 2));
+ }
+ }
+ }
+ else
+ {
+ float right = buttonRect.Right + spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ g.DrawLine(pn, new PointF(right, val), new PointF(right - 2, val));
+ }
+ }
+ }
+ break;
+ }
+ case TickStyle.TopLeft:
+ {
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ float top = buttonRect.Top - spacer;
+ offset = (this.ButtonSize.Width / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ g.DrawLine(pn, new PointF(val, top), new PointF(val, top + 2));
+ }
+ }
+ }
+ else
+ {
+ float left = buttonRect.Left - spacer;
+ offset = (this.ButtonSize.Height / 2) + this.TrackPadding;
+ float val = offset;
+ using (Pen pn = new Pen(this.TickColor, .5f), pn2 = new Pen(this.TickColor, 1f), pn3 = new Pen(Color.FromArgb(100, Color.DarkGray), 1f))
+ {
+ for (int i = 0; i < count + 1; i++)
+ {
+ val = (increment * i) + offset;
+ g.DrawLine(pn, new PointF(left, val), new PointF(left + 2, val));
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ #endregion
+ }
+ }
+
+ /// Draw slider and background dc
+ private void DrawTrack()
+ {
+ BitBlt(_cControlDc.Hdc, 0, 0, _cTrackDc.Width, _cTrackDc.Height, _cTrackDc.Hdc, 0, 0, 0xCC0020);
+ if (TrackStyle == TrackType.Progress)
+ {
+ Rectangle trackRect = GetTrackRectangle();
+ Rectangle buttonRect = GetButtonRectangle();
+ int length;
+
+ trackRect.Inflate(-1, -1);
+ if (Orientation == Orientation.Horizontal)
+ {
+ if (_iValue == _iMinimum)
+ {
+ length = 0;
+ }
+ else if (_iValue == _iMaximum)
+ {
+ if (this.SmoothScrolling)
+ {
+ length = buttonRect.Right - (trackRect.Left + 1);
+ trackRect.Width = length;
+ }
+ else
+ {
+ length = buttonRect.Right - (trackRect.Left + 2);
+ trackRect.Width = length;
+ }
+ }
+ else
+ {
+ length = buttonRect.Right - (trackRect.Left + (int)(buttonRect.Width * .5f));
+ trackRect.Width = length;
+ }
+ }
+ else
+ {
+ if (_iValue == _iMinimum)
+ {
+ length = 0;
+ }
+ else if (_iValue == _iMaximum)
+ {
+ if (this.SmoothScrolling)
+ {
+ length = trackRect.Bottom - (buttonRect.Top + 1);
+ trackRect.Y = buttonRect.Top - 1;
+ trackRect.Height = length;
+ }
+ else
+ {
+ length = trackRect.Bottom - (buttonRect.Top + 3);
+ trackRect.Height = length;
+ }
+ }
+ else
+ {
+ length = trackRect.Bottom - (buttonRect.Top + (int)(buttonRect.Height * .5f));
+ trackRect.Y = buttonRect.Top + (int)(buttonRect.Height * .5f) - 2;
+ trackRect.Height = length;
+ }
+ }
+ if (length > 1)
+ {
+ using (Graphics g = Graphics.FromHdc(_cControlDc.Hdc))
+ {
+ using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ using (GraphicsPath gp = CreateRoundRectanglePath(g, trackRect, 2))
+ {
+ using (LinearGradientBrush fillBrush = new LinearGradientBrush(
+ buttonRect,
+ Color.FromArgb(120, Color.White),
+ Color.FromArgb(250, this.TrackProgressColor),
+ (Orientation == Orientation.Horizontal) ? LinearGradientMode.Vertical : LinearGradientMode.Horizontal))
+ {
+ Blend blnd = new Blend();
+ blnd.Positions = new float[] { 0f, .5f, 1f };
+ blnd.Factors = new float[] { .5f, .7f, .3f };
+ fillBrush.Blend = blnd;
+ g.FillPath(fillBrush, gp);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region Graphics Creation
+ /// Create the button bitmap
+ private void CreateButtonBitmap()
+ {
+ Rectangle buttonRect = GetButtonRectangle();
+ float fx;
+ float fy;
+
+ buttonRect.X = 0;
+ buttonRect.Y = 0;
+ Rectangle accentRect = buttonRect;
+
+ _bmpButton = new Bitmap(buttonRect.Width + 1, buttonRect.Height + 1);
+
+ switch (this.ButtonStyle)
+ {
+ #region Precision
+ case ButtonType.PointerUpRight:
+ case ButtonType.PointerDownLeft:
+ {
+ using (Graphics g = Graphics.FromImage(_bmpButton))
+ {
+ using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ int offset = (int)(buttonRect.Height * .2);
+ buttonRect.Inflate(0, -offset);
+ buttonRect.Y = 0;
+
+ using (GraphicsPath gp = CreatePointedRectangularPath(g, buttonRect, PointDirection.Bottom, 3, offset * 2, -1))
+ {
+ using (Brush br = new SolidBrush(Color.LightGray))
+ g.FillPath(br, gp);
+ using (LinearGradientBrush fillBrush = new LinearGradientBrush(
+ buttonRect,
+ this.ButtonAccentColor,
+ this.ButtonColor,
+ LinearGradientMode.Horizontal))
+ {
+ Blend blnd = new Blend();
+ blnd.Positions = new float[] { 0f, .5f, 1f };
+ blnd.Factors = new float[] { .2f, .8f, .2f };
+ fillBrush.Blend = blnd;
+ g.FillPath(fillBrush, gp);
+ }
+ using (Pen borderPen = new Pen(Color.FromArgb(180, this.ButtonBorderColor), .5f))
+ g.DrawPath(borderPen, gp);
+ }
+ }
+ }
+ if (this.ButtonStyle == ButtonType.PointerUpRight)
+ {
+ if (this.ButtonStyle == ButtonType.PointerUpRight)
+ _bmpButton.RotateFlip(RotateFlipType.Rotate180FlipX);
+ }
+ if (Orientation == Orientation.Vertical)
+ _bmpButton.RotateFlip(RotateFlipType.Rotate90FlipNone);
+ break;
+ }
+ #endregion
+
+ #region Round
+ // round button style
+ case ButtonType.Round:
+ {
+ using (Graphics g = Graphics.FromImage(_bmpButton))
+ {
+ using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ using (GraphicsPath gp = new GraphicsPath())
+ {
+ gp.AddEllipse(buttonRect);
+ // fill with base color
+ using (Brush br = new SolidBrush(Color.FromArgb(255, this.ButtonColor)))
+ g.FillPath(br, gp);
+ // add top sheen
+ using (LinearGradientBrush fillBrush = new LinearGradientBrush(
+ buttonRect,
+ Color.FromArgb(180, Color.White),
+ this.ButtonColor,
+ LinearGradientMode.Vertical))
+ {
+ Blend blnd = new Blend();
+ blnd.Positions = new float[] { 0f, .1f, .2f, .3f, .6f, 1f };
+ blnd.Factors = new float[] { .2f, .3f, .4f, .5f, 1f, 1f };
+ fillBrush.Blend = blnd;
+ g.FillPath(fillBrush, gp);
+ }
+ // add the bottom glow
+ using (PathGradientBrush borderBrush = new PathGradientBrush(gp))
+ {
+ using (GraphicsPath ga = new GraphicsPath())
+ {
+ accentRect.Inflate(0, (int)-(accentRect.Height * .2f));
+ accentRect.Offset(0, (int)(ButtonSize.Width * .2f));
+ ga.AddEllipse(accentRect);
+ // center focus
+ fx = accentRect.Width * .5f;
+ fy = accentRect.Height * 1f;
+ borderBrush.CenterColor = this.ButtonColor;
+ borderBrush.SurroundColors = new Color[] { this.ButtonAccentColor };
+ borderBrush.FocusScales = new PointF(1f, 0f);
+ borderBrush.CenterPoint = new PointF(fx, fy);
+ g.FillPath(borderBrush, ga);
+ }
+ // spotight offsets
+ fx = buttonRect.Width * .2f;
+ fy = buttonRect.Height * .05f;
+ // draw the spotlight
+ borderBrush.CenterColor = Color.FromArgb(120, Color.White);
+ borderBrush.SurroundColors = new Color[] { Color.FromArgb(5, Color.Silver) };
+ borderBrush.FocusScales = new PointF(.2f, .2f);
+ borderBrush.CenterPoint = new PointF(fx, fy);
+ g.FillPath(borderBrush, gp);
+ }
+ // draw the border
+ using (Pen borderPen = new Pen(this.ButtonBorderColor, .5f))
+ g.DrawPath(borderPen, gp);
+ }
+ }
+ }
+ break;
+ }
+ #endregion
+
+ #region Hybrid
+ case ButtonType.Hybrid:
+ {
+ using (Graphics g = Graphics.FromImage(_bmpButton))
+ {
+ using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ using (GraphicsPath gp = new GraphicsPath())
+ {
+ gp.AddEllipse(buttonRect);
+ using (PathGradientBrush borderBrush = new PathGradientBrush(gp))
+ {
+ // center focus
+ fx = buttonRect.Width * .5f;
+ fy = buttonRect.Height * .5f;
+ borderBrush.CenterColor = this.ButtonColor;
+ borderBrush.SurroundColors = new Color[] { this.ButtonAccentColor };
+ borderBrush.FocusScales = new PointF(.5f, .5f);
+ borderBrush.CenterPoint = new PointF(fx, fy);
+ g.FillPath(borderBrush, gp);
+
+ }// draw the border
+ using (Pen borderPen = new Pen(this.ButtonBorderColor, .5f))
+ g.DrawPath(borderPen, gp);
+ }
+ }
+ }
+ break;
+ }
+ #endregion
+
+ #region Rounded Rectangle
+ case ButtonType.RoundedRectInline:
+ case ButtonType.RoundedRectOverlap:
+ {
+ using (Graphics g = Graphics.FromImage(_bmpButton))
+ {
+ using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ using (GraphicsPath gp = CreateRoundRectanglePath(g, buttonRect, this.ButtonCornerRadius))
+ {
+ // fill with solid base color
+ using (Brush br = new SolidBrush(Color.FromArgb(255, this.ButtonColor)))
+ g.FillPath(br, gp);
+ fx = buttonRect.Width * .5f;
+ fy = buttonRect.Height * .5f;
+ // add a shine
+ LinearGradientMode md;
+ if (Orientation == Orientation.Horizontal)
+ {
+ if (this.ButtonStyle == ButtonType.RoundedRectOverlap)
+ md = LinearGradientMode.Horizontal;
+ else
+ md = LinearGradientMode.Vertical;
+ }
+ else
+ {
+ if (this.ButtonStyle == ButtonType.RoundedRectOverlap)
+ md = LinearGradientMode.Vertical;
+ else
+ md = LinearGradientMode.Horizontal;
+ }
+ // draw it
+ using (LinearGradientBrush fillBrush = new LinearGradientBrush(
+ buttonRect,
+ Color.FromArgb(120, Color.White),
+ Color.FromArgb(5, Color.Silver),
+ md))
+ {
+ Blend blnd = new Blend();
+ blnd.Positions = new float[] { 0f, .2f, .4f, .7f, .8f, 1f };
+ blnd.Factors = new float[] { .2f, .4f, .5f, .4f, .2f, .1f };
+ fillBrush.Blend = blnd;
+ g.FillPath(fillBrush, gp);
+ }
+ // draw the border
+ using (Pen borderPen = new Pen(Color.FromArgb(220, this.ButtonBorderColor), .5f))
+ g.DrawPath(borderPen, gp);
+ // add a spotlight underneath
+ accentRect.Offset(0, (int)(accentRect.Height * .6f));
+ // center focus
+ if (Orientation == Orientation.Horizontal && this.ButtonStyle == ButtonType.RoundedRectOverlap
+ || Orientation == Orientation.Vertical && this.ButtonStyle == ButtonType.RoundedRectInline)
+ {
+
+ fx = accentRect.Width * .1f;
+ fy = accentRect.Height * .5f;
+ // notch it down a little
+ accentRect.Offset(0, (int)(accentRect.Height * .2f));
+ }
+ else
+ {
+ fx = accentRect.Width * .5f;
+ fy = accentRect.Height * .1f;
+ }
+
+ using (GraphicsPath ga = new GraphicsPath())
+ {
+ ga.AddEllipse(accentRect);
+ // draw bottom glow
+ using (PathGradientBrush borderBrush = new PathGradientBrush(ga))
+ {
+ borderBrush.CenterColor = this.ButtonAccentColor;
+ borderBrush.SurroundColors = new Color[] { Color.Transparent };
+ borderBrush.FocusScales = new PointF(.1f, .2f);
+ borderBrush.CenterPoint = new PointF(fx, fy);
+ g.FillPath(borderBrush, ga);
+ }
+ }
+ using (GraphicsPath ga = new GraphicsPath())
+ {
+ if (this.ButtonStyle == ButtonType.RoundedRectOverlap)
+ ga.AddEllipse(0, 0, buttonRect.Width, 4);
+ else
+ ga.AddEllipse(2, 0, buttonRect.Width - 4, 4);
+ // spotight offsets
+ fx = buttonRect.Width * .5f;
+ fy = buttonRect.Height * .05f;
+ // draw the top spotlight
+ using (PathGradientBrush borderBrush = new PathGradientBrush(ga))
+ {
+ borderBrush.CenterColor = Color.FromArgb(120, Color.White);
+ borderBrush.SurroundColors = new Color[] { Color.FromArgb(5, Color.Silver) };
+ borderBrush.FocusScales = new PointF(.2f, .2f);
+ borderBrush.CenterPoint = new PointF(fx, fy);
+ g.FillPath(borderBrush, gp);
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ #endregion
+
+ #region Glass
+ case ButtonType.GlassInline:
+ case ButtonType.GlassOverlap:
+ {
+ using (Graphics g = Graphics.FromImage(_bmpButton))
+ {
+ using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ using (GraphicsPath gp = CreateRoundRectanglePath(g, buttonRect, this.ButtonCornerRadius))
+ {
+ fx = buttonRect.Width * .5f;
+ fy = buttonRect.Height * .5f;
+ // add a shine
+ using (PathGradientBrush borderBrush = new PathGradientBrush(gp))
+ {
+ borderBrush.CenterColor = Color.FromArgb(100, Color.DarkGray);
+ borderBrush.SurroundColors = new Color[] { Color.FromArgb(120, Color.Silver) };
+ borderBrush.FocusScales = new PointF(1f, .5f);
+ borderBrush.CenterPoint = new PointF(fx, fy);
+ g.FillPath(borderBrush, gp);
+ }
+ // draw the border
+ using (Pen borderPen = new Pen(this.ButtonBorderColor, .5f))
+ g.DrawPath(borderPen, gp);
+ // add a spotlight underneath
+ accentRect.Offset(0, (int)(accentRect.Height * .8f));
+ // center focus
+ if (Orientation == Orientation.Horizontal && this.ButtonStyle == ButtonType.RoundedRectOverlap
+ || Orientation == Orientation.Vertical && this.ButtonStyle == ButtonType.RoundedRectInline)
+ {
+
+ fx = accentRect.Width * .05f;
+ fy = accentRect.Height * .5f;
+ }
+ else
+ {
+ fx = accentRect.Width * .5f;
+ fy = accentRect.Height * .05f;
+ }
+ using (GraphicsPath ga = new GraphicsPath())
+ {
+ ga.AddEllipse(accentRect);
+ using (PathGradientBrush borderBrush = new PathGradientBrush(ga))
+ {
+ borderBrush.CenterColor = Color.FromArgb(120, this.ButtonAccentColor);
+ borderBrush.SurroundColors = new Color[] { Color.FromArgb(5, Color.Silver) };
+ borderBrush.FocusScales = new PointF(.2f, .2f);
+ borderBrush.CenterPoint = new PointF(fx, fy);
+ g.FillPath(borderBrush, ga);
+ }
+ }
+ using (GraphicsPath ga = new GraphicsPath())
+ {
+ ga.AddEllipse(0, 0, buttonRect.Width, 4);
+ // spotight offsets
+ fx = buttonRect.Width * .5f;
+ fy = buttonRect.Height * .05f;
+ // draw the top spotlight
+ using (PathGradientBrush borderBrush = new PathGradientBrush(ga))
+ {
+ borderBrush.CenterColor = Color.FromArgb(120, Color.White);
+ borderBrush.SurroundColors = new Color[] { Color.FromArgb(5, Color.Silver) };
+ borderBrush.FocusScales = new PointF(.2f, .2f);
+ borderBrush.CenterPoint = new PointF(fx, fy);
+ g.FillPath(borderBrush, gp);
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ #endregion
+ }
+ _bmpButton.MakeTransparent();
+ }
+
+ /// Create graphics objects
+ private void CreateGraphicsObjects()
+ {
+ DestroyGraphicsObjects();
+ // load primary buffer
+ _cControlDc = new cStoreDc();
+ _cControlDc.Height = this.Height;
+ _cControlDc.Width = this.Width;
+ // track and background dc
+ _cTrackDc = new cStoreDc();
+ _cTrackDc.Height = this.Height;
+ _cTrackDc.Width = this.Width;
+ // draw the track
+ CreateTrack();
+ // create the button image
+ CreateButtonBitmap();
+ // create the animation sprite
+ CreateSprite();
+ }
+
+ /// create the animations sprite
+ private void CreateSprite()
+ {
+ Rectangle trackRect = GetTrackRectangle();
+ int width = (int)(Orientation == Orientation.Horizontal ? trackRect.Width * .1f : trackRect.Height * .1f);
+ int height = this.TrackDepth;
+
+ DestroySprite();
+ // draw the line sprite into a bmp
+ _bmpSprite = new Bitmap(width, height);
+ using (Graphics g = Graphics.FromImage(_bmpSprite))
+ {
+ using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ g.CompositingMode = CompositingMode.SourceOver;
+ Rectangle imageRect = new Rectangle(0, 0, width, height);
+ // draw sprite
+ using (LinearGradientBrush fillBrush = new LinearGradientBrush(
+ imageRect,
+ Color.White,
+ Color.Transparent,
+ LinearGradientMode.Horizontal))
+ {
+ Blend blnd = new Blend();
+ blnd.Positions = new float[] { 0f, .2f, .5f, .8f, 1f };
+ blnd.Factors = new float[] { 1f, .6f, 0f, .4f, 1f };
+ fillBrush.Blend = blnd;
+ using (GraphicsPath gp = CreateRoundRectanglePath(g, imageRect, 2))
+ g.FillPath(fillBrush, gp);
+ }
+ }
+ }
+ // make transparent
+ _bmpSprite.MakeTransparent();
+ // rotate
+ if (Orientation == Orientation.Vertical)
+ _bmpSprite.RotateFlip(RotateFlipType.Rotate90FlipX);
+ }
+
+ /// Create the track dc
+ private void CreateTrack()
+ {
+ Rectangle bounds = new Rectangle(0, 0, this.Width, this.Height);
+ Rectangle trackRect = GetTrackRectangle();
+
+ using (Graphics g = Graphics.FromHdc(_cTrackDc.Hdc))
+ {
+ // fill it in
+ if (this.BackgroundImage != null)
+ {
+ using (GraphicsMode md = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ using (ImageAttributes ia = new ImageAttributes())
+ g.DrawImage(this.BackgroundImage, bounds, 0, 0, this.BackgroundImage.Width, this.BackgroundImage.Height, GraphicsUnit.Pixel, ia);
+ }
+ }
+ else
+ {
+ DrawBackGround(g, bounds);
+ }
+ // draw ticks
+ if (this.TickStyle != TickStyle.None)
+ DrawTicks(g, bounds);
+ // create the path
+ if (Orientation == Orientation.Horizontal)//***offsets wrong on createpath?
+ trackRect.Width -= 1;
+ else
+ trackRect.Height -= 1;
+ using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ // draw track shadow
+ if (this.TrackShadow)
+ {
+ trackRect.Inflate(2, 2);
+ using (GraphicsPath gp = CreateRoundRectanglePath(g, trackRect, 2))
+ {
+ // light shadow
+ using (Pen pn = new Pen(Color.FromArgb(80, this.TrackShadowColor), 1f))
+ g.DrawPath(pn, gp);
+ }
+ trackRect.Inflate(-1, -1);
+ using (GraphicsPath gp = CreateRoundRectanglePath(g, trackRect, 2))
+ {
+ // darker
+ using (Pen pn = new Pen(Color.FromArgb(120, this.TrackShadowColor), 1f))
+ g.DrawPath(pn, gp);
+ }
+ trackRect.Inflate(-1, -1);
+ }
+
+ using (GraphicsPath gp = CreateRoundRectanglePath(g, trackRect, 2))
+ {
+ // fill color
+ if (this.TrackFillColor != Color.Transparent)
+ {
+ using (Brush br = new SolidBrush(this.TrackFillColor))
+ g.FillPath(br, gp);
+ }
+ // draw the outline
+ using (Pen pn = new Pen(this.TrackBorderColor, 1f))
+ g.DrawPath(pn, gp);
+ }
+ }
+ }
+ }
+
+ /// Destroy grahics objects
+ private void DestroyGraphicsObjects()
+ {
+ // destroy sprite and timer
+ StopPulseTimer();
+ DestroySprite();
+ // destroy buffers
+ if (_cControlDc != null)
+ _cControlDc.Dispose();
+ if (_cTrackDc != null)
+ _cTrackDc.Dispose();
+ if (_cAnimationDc != null)
+ _cAnimationDc.Dispose();
+ // destroy images
+ if (_bmpButton != null)
+ _bmpButton.Dispose();
+ if (_bmpSprite != null)
+ _bmpSprite.Dispose();
+ }
+
+ /// Destroy animation sprite
+ private void DestroySprite()
+ {
+ if (_bmpSprite != null)
+ _bmpSprite.Dispose();
+ }
+ #endregion
+
+ #region Animation
+ #region Drawing
+ private void DrawPulse()
+ {
+ if (_cControlDc != null)
+ {
+ int offset = 0;
+ Rectangle buttonRect = GetButtonRectangle();
+ Rectangle trackRect = GetTrackRectangle();
+ Rectangle lineRect;
+ Rectangle clipRect = trackRect;
+
+ // copy unaltered image into buffer
+ BitBlt(_cAnimationDc.Hdc, 0, 0, _cAnimationDc.Width, _cAnimationDc.Height, _cControlDc.Hdc, 0, 0, 0xCC0020);
+
+ if (Orientation == Orientation.Horizontal)
+ {
+ _iLinePos += 2;
+ if (_iLinePos > trackRect.Right - _bmpSprite.Width)
+ _iLinePos = trackRect.Left + 1;
+ if (_iLinePos < buttonRect.Left)
+ {
+ if (_iLinePos + _bmpSprite.Width > buttonRect.Left)
+ offset = _iLinePos + _bmpSprite.Width - buttonRect.Left;
+ lineRect = new Rectangle(_iLinePos, trackRect.Y, _bmpSprite.Width - offset, _bmpSprite.Height);
+ // draw sprite -horz
+ DrawPulseSprite(_cAnimationDc.Hdc, _bmpSprite, lineRect, .4f);
+ }
+ }
+ else
+ {
+ _iLinePos -= 1;
+ if (_iLinePos < trackRect.Top + _bmpSprite.Height)
+ _iLinePos = trackRect.Bottom - _bmpSprite.Height;
+ if (_iLinePos > buttonRect.Bottom)
+ {
+ if (_iLinePos - _bmpSprite.Height < buttonRect.Bottom)
+ offset = buttonRect.Bottom - (_iLinePos - _bmpSprite.Height);
+ lineRect = new Rectangle(trackRect.X, _iLinePos, _bmpSprite.Width, _bmpSprite.Height - offset);
+ // draw sprite -vert
+ DrawPulseSprite(_cAnimationDc.Hdc, _bmpSprite, lineRect, .4f);
+ }
+ }
+ // draw to control
+ using (Graphics g = Graphics.FromHwnd(this.Handle))
+ {
+ BitBlt(g.GetHdc(), 0, 0, _cAnimationDc.Width, _cAnimationDc.Height, _cAnimationDc.Hdc, 0, 0, 0xCC0020);
+ g.ReleaseHdc();
+ }
+ RECT r = new RECT(0, 0, this.Width, this.Height);
+ ValidateRect(this.Handle, ref r);
+ }
+ }
+
+ /// Draws the line sprite
+ private void DrawPulseSprite(IntPtr destdc, Bitmap source, Rectangle bounds, float intensity)
+ {
+ using (Graphics g = Graphics.FromHdc(destdc))
+ {
+ g.CompositingMode = CompositingMode.SourceOver;
+ AlphaBlend(g, source, bounds, intensity);
+ }
+ }
+ #endregion
+
+ #region Timer
+ private void StartPulseTimer()
+ {
+ if (_cPulseTimer == null)
+ {
+ _bPulseTimerOn = true;
+ if (_cAnimationDc != null)
+ _cAnimationDc.Dispose();
+ _cAnimationDc = new cStoreDc();
+ _cAnimationDc.Width = _cControlDc.Width;
+ _cAnimationDc.Height = _cControlDc.Height;
+ BitBlt(_cAnimationDc.Hdc, 0, 0, _cControlDc.Width, _cControlDc.Height, _cControlDc.Hdc, 0, 0, 0xCC0020);
+ // timer setup
+ _cPulseTimer = new FadeTimer(this);
+ _cPulseTimer.Tick += new FadeTimer.TickDelegate(_cPulseTimer_Tick);
+ _cPulseTimer.Complete += new FadeTimer.CompleteDelegate(_cPulseTimer_Complete);
+ _cPulseTimer.Interval = (int)this.AnimationSpeed;
+ _cPulseTimer.Fade(FadeTimer.FadeType.Loop);
+ }
+ }
+
+ private void StopPulseTimer()
+ {
+ if (_cPulseTimer != null)
+ {
+ _iLinePos = 0;
+ if (_cAnimationDc != null)
+ _cAnimationDc.Dispose();
+ // tear down the timer class
+ _cPulseTimer.Reset();
+ _cPulseTimer.Tick -= _cPulseTimer_Tick;
+ _cPulseTimer.Complete -= _cPulseTimer_Complete;
+ _cPulseTimer.Dispose();
+ _cPulseTimer = null;
+ _bPulseTimerOn = false;
+ }
+ }
+
+ private void _cPulseTimer_Complete(object sender)
+ {
+ ResetCallback rs = new ResetCallback(StopPulseTimer);
+ this.Invoke(rs);
+ }
+
+ private void _cPulseTimer_Tick(object sender)
+ {
+ DrawPulse();
+ }
+
+ #endregion
+ #endregion
+
+ #region FlyOut Caption
+ private void DrawFlyOut(Graphics g)
+ {
+ Rectangle buttonRect = GetButtonRectangle();
+ Rectangle flyoutRect;
+ int pos;
+
+ if (Orientation == Orientation.Horizontal)
+ {
+ pos = buttonRect.Left + (int)(buttonRect.Width * .5f);
+ int offset = (int)(this.FlyOutMaxWidth * .5f);
+ flyoutRect = new Rectangle((int)pos - offset, buttonRect.Top - (this.FlyOutMaxDepth + this.FlyOutSpacer), this.FlyOutMaxWidth, this.FlyOutMaxDepth);
+ offset -= 8;
+ using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ using (GraphicsPath gp = CreatePointedRectangularPath(g, flyoutRect, PointDirection.Bottom, 5, 4, offset))
+ {
+ using (Brush br = new SolidBrush(Color.FromArgb(220, Color.White)))
+ g.FillPath(br, gp);
+ using (Pen pn = new Pen(Color.FromArgb(160, Color.DimGray)))
+ g.DrawPath(pn, gp);
+
+ FlyOutEventArgs flyOutData = new FlyOutEventArgs();
+ if (FlyOutInfo != null)
+ FlyOutInfo(this, flyOutData);
+ if (flyOutData.text.Length == 0)
+ flyOutData.text = this.Value.ToString("0");
+ using (StringFormat sf = new StringFormat())
+ {
+ sf.FormatFlags = StringFormatFlags.NoWrap;
+ sf.Alignment = StringAlignment.Center;
+ sf.LineAlignment = StringAlignment.Center;
+ using (Font ft = new Font("Arial", 8f, FontStyle.Regular))
+ g.DrawString(flyOutData.text, ft, Brushes.Black, flyoutRect, sf);
+ }
+ }
+ }
+ }
+ else
+ {
+ pos = buttonRect.Top + (int)(buttonRect.Height * .5f);
+ int offset = (int)(this.FlyOutMaxWidth * .5f);
+ flyoutRect = new Rectangle(buttonRect.Left - (this.FlyOutMaxDepth + this.FlyOutSpacer), pos - offset, this.FlyOutMaxDepth, this.FlyOutMaxWidth);
+ using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.HighQuality))
+ {
+ using (GraphicsPath gp = CreatePointedRectangularPath(g, flyoutRect, PointDirection.Right, 5, 4, 1))
+ {
+ using (Brush br = new SolidBrush(Color.FromArgb(200, Color.White)))
+ g.FillPath(br, gp);
+ using (Pen pn = new Pen(Color.FromArgb(240, this.ButtonBorderColor)))
+ g.DrawPath(pn, gp);
+
+ FlyOutEventArgs flyOutData = new FlyOutEventArgs();
+ if (FlyOutInfo != null)
+ FlyOutInfo(this, flyOutData);
+ if (flyOutData.text.Length == 0)
+ flyOutData.text = this.Value.ToString("0");
+ flyoutRect.Width -= 4;
+ using (StringFormat sf = new StringFormat())
+ {
+ sf.FormatFlags = StringFormatFlags.NoWrap;
+ sf.Alignment = StringAlignment.Center;
+ sf.LineAlignment = StringAlignment.Center;
+ using (Font ft = new Font("Arial", 8f, FontStyle.Regular))
+ g.DrawString(flyOutData.text, ft, Brushes.Black, flyoutRect, sf);
+ }
+ }
+ }
+ }
+
+ }
+ #endregion
+ #endregion
+
+ #region Helpers
+ /// AlphaBlend an image, alpha .1-1
+ private void AlphaBlend(Graphics g, Bitmap bmp, Rectangle bounds, float alpha)
+ {
+ if (alpha > 1f)
+ alpha = 1f;
+ else if (alpha < .01f)
+ alpha = .01f;
+ using (ImageAttributes ia = new ImageAttributes())
+ {
+ ColorMatrix cm = new ColorMatrix();
+ cm.Matrix00 = 1f;
+ cm.Matrix11 = 1f;
+ cm.Matrix22 = 1f;
+ cm.Matrix44 = 1f;
+ cm.Matrix33 = alpha;
+ ia.SetColorMatrix(cm);
+ g.DrawImage(bmp, bounds, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, ia);
+ }
+ }
+
+ /// Maximun size based on control options
+ private void CalculateMaximumSize()
+ {
+ Size sz = new Size(0, 0);
+
+ if (this.TickStyle != TickStyle.None)
+ sz.Height += (this.TickMaxLength + this.TickMinPadding) * (this.TickStyle == TickStyle.Both ? 2 : 1);
+ if (this.SliderFlyOut != FlyOutStyle.None)
+ sz.Height += this.FlyOutMaxDepth + this.FlyOutSpacer;
+
+ switch (this.ButtonStyle)
+ {
+ case ButtonType.GlassInline:
+ case ButtonType.RoundedRectInline:
+ {
+ sz.Height += TrackMaxDepth + 6;
+ break;
+ }
+ case ButtonType.GlassOverlap:
+ case ButtonType.RoundedRectOverlap:
+ {
+ sz.Height += TrackMaxDepth * 4;
+ break;
+ }
+ case ButtonType.Round:
+ case ButtonType.Hybrid:
+ {
+ sz.Height += TrackMaxDepth + 8;
+ break;
+ }
+ case ButtonType.PointerDownLeft:
+ case ButtonType.PointerUpRight:
+ {
+ sz.Height += TrackMaxDepth * 4;
+ break;
+ }
+ }
+ if (Orientation == Orientation.Horizontal)
+ {
+ this.MaxSize = sz;
+ }
+ else
+ {
+ Size flip = new Size(sz.Height, sz.Width);
+ this.MaxSize = flip;
+ }
+ }
+
+ /// Minimum size based on control options
+ private void CalculateMinimumSize()
+ {
+ Size sz = new Size(0, 0);
+
+ if (this.TickStyle != TickStyle.None)
+ sz.Height += (this.TickMaxLength + this.TickMinPadding) * (this.TickStyle == TickStyle.Both ? 2 : 1);
+ if (this.SliderFlyOut != FlyOutStyle.None)
+ sz.Height += this.FlyOutMaxDepth + this.FlyOutSpacer;
+
+ switch (this.ButtonStyle)
+ {
+ case ButtonType.GlassInline:
+ case ButtonType.RoundedRectInline:
+ {
+ sz.Height += TrackMinDepth + 6;
+ break;
+ }
+ case ButtonType.GlassOverlap:
+ case ButtonType.RoundedRectOverlap:
+ {
+ sz.Height += TrackMinDepth * 4;
+ break;
+ }
+ case ButtonType.Round:
+ case ButtonType.Hybrid:
+ {
+ sz.Height += TrackMinDepth + 8;
+ break;
+ }
+ case ButtonType.PointerDownLeft:
+ case ButtonType.PointerUpRight:
+ {
+ sz.Height += TrackMinDepth * 4;
+ break;
+ }
+ }
+ if (Orientation == Orientation.Horizontal)
+ {
+ this.MinSize = sz;
+ }
+ else
+ {
+ Size flip = new Size(sz.Height, sz.Width);
+ this.MinSize = flip;
+ }
+ }
+
+ private GraphicsPath CreatePointedRectangularPath(Graphics g, Rectangle bounds, PointDirection direction, float radius, int depth, int inset)
+ {
+ int diff = 0;
+ // create a path
+ GraphicsPath pathBounds = new GraphicsPath();
+ switch (direction)
+ {
+ case PointDirection.Bottom:
+ {
+ // line left
+ pathBounds.AddLine(bounds.Left, bounds.Bottom - radius, bounds.Left, bounds.Top + radius);
+ if (radius > 0)
+ pathBounds.AddArc(bounds.Left, bounds.Top, radius, radius, 180, 90);
+ // line top
+ pathBounds.AddLine(bounds.Left + radius, bounds.Top, bounds.Right - radius, bounds.Top);
+ if (radius > 0)
+ pathBounds.AddArc(bounds.Right - radius, bounds.Top, radius, radius, 270, 90);
+ // line right
+ pathBounds.AddLine(bounds.Right, bounds.Top + radius, bounds.Right, bounds.Bottom - radius);
+ // pointed path //
+ if (inset == -1)
+ radius = 0;
+ if (radius > 0)
+ pathBounds.AddArc(bounds.Right - radius, bounds.Bottom - radius, radius, radius, 0, 90);
+ // line bottom right
+ pathBounds.AddLine(bounds.Right - radius, bounds.Bottom, bounds.Right - (radius + inset), bounds.Bottom);
+ // pointed center
+ diff = (bounds.Width / 2) - ((int)radius + inset);
+ // right half
+ pathBounds.AddLine(bounds.Right - (radius + inset), bounds.Bottom, bounds.Right - (radius + inset + diff), bounds.Bottom + depth);
+ // left half
+ pathBounds.AddLine(bounds.Right - (radius + inset + diff), bounds.Bottom + depth, bounds.Left + radius + inset, bounds.Bottom);
+ // line bottom left
+ pathBounds.AddLine(bounds.Left + radius + inset, bounds.Bottom, bounds.Left + radius, bounds.Bottom);
+ if (radius > 0)
+ pathBounds.AddArc(bounds.Left, bounds.Bottom - radius, radius, radius, 90, 90);
+
+ break;
+ }
+ case PointDirection.Right:
+ {
+ // line top
+ pathBounds.AddLine(bounds.Left + radius, bounds.Top, bounds.Right - (radius + depth), bounds.Top);
+ // arc top right
+ if (radius > 0)
+ pathBounds.AddArc(bounds.Right - (radius + depth), bounds.Top, radius, radius, 270, 90);
+
+ // top line
+ pathBounds.AddLine(bounds.Right - depth, bounds.Top + radius, bounds.Right - depth, bounds.Top + (radius + inset));
+ // pointed center
+ diff = (bounds.Height / 2) - ((int)radius + inset);
+ // top half
+ pathBounds.AddLine(bounds.Right - depth, bounds.Top + (radius + inset), bounds.Right, bounds.Bottom - (radius + inset + diff));
+ // bottom half
+ pathBounds.AddLine(bounds.Right, bounds.Bottom - (radius + inset + diff), bounds.Right - depth, bounds.Bottom - (radius + inset));
+ // line right bottom
+ pathBounds.AddLine(bounds.Right - depth, bounds.Bottom - (radius + inset), bounds.Right - depth, bounds.Bottom - radius);
+ // arc bottom right
+ if (radius > 0)
+ pathBounds.AddArc(bounds.Right - (radius + depth), bounds.Bottom - radius, radius, radius, 0, 90);
+ // line bottom
+ pathBounds.AddLine(bounds.Right - (radius + depth), bounds.Bottom, bounds.Left + radius, bounds.Bottom);
+ if (inset == -1)
+ radius = 0;
+ // arc bottom left
+ if (radius > 0)
+ pathBounds.AddArc(bounds.Left, bounds.Bottom - radius, radius, radius, 90, 90);
+ // line left
+ pathBounds.AddLine(bounds.Left, bounds.Bottom - radius, bounds.Left, bounds.Top + radius);
+ // arc top left
+ if (radius > 0)
+ pathBounds.AddArc(bounds.Left, bounds.Top, radius, radius, 180, 90);
+
+ /*// pointed path //
+ // line left bottom
+ pathBounds.AddLine(bounds.Left, bounds.Bottom - radius, bounds.Left, bounds.Bottom - (radius + inset));
+ // pointed center
+ diff = (bounds.Height / 2) - ((int)radius + inset);
+ // bottom half
+ pathBounds.AddLine(bounds.Left, bounds.Bottom - (radius + inset), bounds.Left - depth, bounds.Bottom - (radius + inset + diff));
+ // top half
+ pathBounds.AddLine(bounds.Left - depth, bounds.Bottom - (radius + inset + diff), bounds.Left, bounds.Top + (radius + inset));
+ // top line
+ pathBounds.AddLine(bounds.Left, bounds.Top + (radius + inset), bounds.Left, bounds.Top + radius);
+ if (radius > 0)
+ pathBounds.AddArc(bounds.Left, bounds.Top, radius, radius, 180, 90);*/
+ break;
+ }
+ }
+
+ pathBounds.CloseFigure();
+ return pathBounds;
+ }
+
+ /// Create a round GraphicsPath [not used]
+ private GraphicsPath CreateRoundPath(Graphics g, Rectangle bounds)
+ {
+ int size = bounds.Width > bounds.Height ? bounds.Height : bounds.Width;
+ bounds.Height = size;
+ bounds.Width = size;
+ GraphicsPath circlePath = new GraphicsPath();
+ // create the path
+ circlePath.AddEllipse(bounds);
+ circlePath.CloseFigure();
+ return circlePath;
+ }
+
+ /// Create a rounded rectangle GraphicsPath
+ private GraphicsPath CreateRoundRectanglePath(Graphics g, Rectangle bounds, float radius)
+ {
+ // create a path
+ GraphicsPath pathBounds = new GraphicsPath();
+ // arc top left
+ pathBounds.AddArc(bounds.Left, bounds.Top, radius, radius, 180, 90);
+ // line top
+ pathBounds.AddLine(bounds.Left + radius, bounds.Top, bounds.Right - radius, bounds.Top);
+ // arc top right
+ pathBounds.AddArc(bounds.Right - radius, bounds.Top, radius, radius, 270, 90);
+ // line right
+ pathBounds.AddLine(bounds.Right, bounds.Top + radius, bounds.Right, bounds.Bottom - radius);
+ // arc bottom right
+ pathBounds.AddArc(bounds.Right - radius, bounds.Bottom - radius, radius, radius, 0, 90);
+ // line bottom
+ pathBounds.AddLine(bounds.Right - radius, bounds.Bottom, bounds.Left + radius, bounds.Bottom);
+ // arc bottom left
+ pathBounds.AddArc(bounds.Left, bounds.Bottom - radius, radius, radius, 90, 90);
+ // line left
+ pathBounds.AddLine(bounds.Left, bounds.Bottom - radius, bounds.Left, bounds.Top + radius);
+ pathBounds.CloseFigure();
+ return pathBounds;
+ }
+
+ /// Set default button sizes
+ private void DefaultButtonSize(ButtonType type)
+ {
+ Size sz = new Size(14, 14);
+ switch (type)
+ {
+ case ButtonType.Hybrid:
+ case ButtonType.Round:
+ _iTrackDepth = 4;
+ sz.Height = _iTrackDepth + 8;
+ sz.Width = sz.Height;
+ break;
+ case ButtonType.PointerDownLeft:
+ case ButtonType.PointerUpRight:
+ _iTrackDepth = 5;
+ sz.Height = _iTrackDepth * 4;
+ sz.Width = _iTrackDepth + 2;
+ break;
+ case ButtonType.RoundedRectInline:
+ _iTrackDepth = 4;
+ _iButtonCornerRadius = 6;
+ sz.Height = _iTrackDepth + 6;
+ sz.Width = sz.Height * 2;
+ break;
+ case ButtonType.RoundedRectOverlap:
+ _iTrackDepth = 4;
+ _iButtonCornerRadius = 4;
+ sz.Height = _iTrackDepth * 4;
+ sz.Width = _iTrackDepth + 6;
+ break;
+ case ButtonType.GlassInline:
+ _iTrackDepth = 6;
+ _iButtonCornerRadius = 2;
+ sz.Height = _iTrackDepth + 6;
+ sz.Width = sz.Height * 2;
+ break;
+ case ButtonType.GlassOverlap:
+ _iTrackDepth = 4;
+ _iButtonCornerRadius = 2;
+ sz.Height = _iTrackDepth * 4;
+ sz.Width = _iTrackDepth + 6;
+ break;
+ }
+
+ if (Orientation == Orientation.Vertical)
+ {
+ Size sv = new Size(sz.Height, sz.Width);
+ _szButtonSize = sv;
+ }
+ else
+ {
+ _szButtonSize = sz;
+ }
+ }
+
+ /// Return button size and coordinates
+ private Rectangle GetButtonRectangle()
+ {
+ Rectangle bounds = new Rectangle(0, 0, this.Width, this.Height);
+ RectangleF buttonRect = new RectangleF();
+ int offsetX = (bounds.Width / 2);
+ int offset = 0;
+ double pos = _dButtonPosition + this.TrackPadding;
+
+ if (Orientation == Orientation.Horizontal)
+ {
+ if (this.SliderFlyOut != FlyOutStyle.None)
+ offset = this.FlyOutMaxDepth + this.FlyOutSpacer;
+ if (this.TickStyle == TickStyle.TopLeft)
+ offset += this.TickMaxLength + this.TickMinPadding;
+ else if (this.TickStyle == TickStyle.BottomRight)
+ offset -= this.TickMaxLength + this.TickMinPadding;
+ offset += (int)((bounds.Height - offset) * .5f);
+ offset -= (int)(this.ButtonSize.Height * .5f);
+ buttonRect = new RectangleF((float)pos, offset, this.ButtonSize.Width, this.ButtonSize.Height);
+ }
+ else
+ {
+ // offset on track
+ if (this.SliderFlyOut != FlyOutStyle.None)
+ offset = this.FlyOutMaxDepth + this.FlyOutSpacer;
+ if (this.TickStyle == TickStyle.TopLeft)
+ offset += this.TickMaxLength + this.TickMinPadding;
+ else if (this.TickStyle == TickStyle.BottomRight)
+ offset -= this.TickMaxLength + this.TickMinPadding;
+ offset += (int)((bounds.Width - offset) * .5f);
+ offset -= (int)(this.ButtonSize.Width * .5f);
+ buttonRect = new RectangleF(offset, (float)pos, this.ButtonSize.Width, this.ButtonSize.Height);
+ }
+ // store it for hit testing
+ _buttonRect = new RECT((int)buttonRect.X, (int)buttonRect.Y, (int)buttonRect.Right, (int)buttonRect.Bottom);
+ return Rectangle.Round(buttonRect);
+ }
+
+ /// Return track size and coordinates
+ private Rectangle GetTrackRectangle()
+ {
+ Rectangle bounds = new Rectangle(0, 0, this.Width, this.Height);
+ Rectangle trackRect;
+ int offset;
+
+ if (Orientation == Orientation.Horizontal)
+ {
+ // reduce for padding and center rect
+ offset = (int)(this.TrackPadding);
+ bounds.Inflate(-offset, 0);
+ offset = 0;
+ if (this.SliderFlyOut != FlyOutStyle.None)
+ offset = this.FlyOutMaxDepth + this.FlyOutSpacer;
+ if (this.TickStyle == TickStyle.TopLeft)
+ offset += this.TickMaxLength + this.TickMinPadding;
+ else if (this.TickStyle == TickStyle.BottomRight)
+ offset -= this.TickMaxLength + this.TickMinPadding;
+ offset += (int)((bounds.Height - offset) * .5f);
+ offset -= (int)(this.TrackDepth * .5f);
+ trackRect = new Rectangle(bounds.X, offset, bounds.Width, this.TrackDepth);
+ }
+ else
+ {
+ offset = (int)(this.TrackPadding);
+ bounds.Inflate(0, -offset);
+ offset = 0;
+ if (this.SliderFlyOut != FlyOutStyle.None)
+ offset = this.FlyOutMaxDepth + this.FlyOutSpacer;
+ if (this.TickStyle == TickStyle.TopLeft)
+ offset += this.TickMaxLength + this.TickMinPadding;
+ else if (this.TickStyle == TickStyle.BottomRight)
+ offset -= this.TickMaxLength + this.TickMinPadding;
+ offset += (int)((bounds.Width - offset) * .5f);
+ offset -= (int)(this.TrackDepth * .5f);
+ trackRect = new Rectangle(offset, bounds.Y, this.TrackDepth, bounds.Height);
+ }
+ // store for hit testing
+ _trackRect = new RECT(trackRect.X, trackRect.Y, trackRect.Right, trackRect.Bottom);
+ return trackRect;
+ }
+
+ /// Exact size between ticks
+ private double Increment()
+ {
+ Rectangle trackRect = GetTrackRectangle();
+
+ if (Orientation == Orientation.Horizontal)
+ return (double)((trackRect.Width - this.ButtonSize.Width) / IncrementScale());
+ else
+ return (double)((trackRect.Height - this.ButtonSize.Height) / IncrementScale());
+ }
+
+ /// Offset number if Minimum and Maximum are negative to positive integers
+ private double IncrementOffset()
+ {
+ double center = 0;
+ if (this.Minimum < 0 && this.Maximum > 0)
+ center = 1;
+ return center;
+ }
+
+ /// The total number of tick increments
+ private double IncrementScale()
+ {
+ return (double)Math.Abs(this.Maximum - this.Minimum);
+ }
+
+ /// The incremental size between the Minimum and Value
+ private double IncrementalValue()
+ {
+ if (Orientation == Orientation.Horizontal)
+ return Increment() * (double)(Math.Abs(this.Value - this.Minimum));
+ else
+ return Increment() * (double)(IncrementScale() - (Math.Abs(this.Value - this.Minimum)));
+ }
+
+ /// Modulus returns true if divisible with no remainder
+ private bool Mod(int a, int b)
+ {
+ if (Math.IEEERemainder((double)a, (double)b) == 0)
+ return true;
+ return false;
+ }
+
+ /// Return position coordinates from value
+ private double PosFromValue(int val)
+ {
+ if (Orientation == Orientation.Horizontal)
+ return Increment() * (double)(Math.Abs(val - this.Minimum + (val != this.Minimum ? IncrementOffset() : 0)));
+ else
+ return Increment() * (double)(IncrementScale() - (Math.Abs(val - this.Minimum) + (val != this.Minimum ? IncrementOffset() : 0)));
+ }
+
+ /// Repaint and optionally resize
+ private void PropertyChange()
+ {
+ if (this.DesignMode)
+ {
+ if (this.SmoothScrolling)
+ _dButtonPosition = PosFromValue(this.Value);
+ else
+ _dButtonPosition = IncrementalValue();
+ if (this.AutoSize && this.FinishedPropRun)
+ ResizeThis();
+ CreateGraphicsObjects();
+ }
+ else if (this.IsInited)
+ {
+ if (this.SmoothScrolling)
+ _dButtonPosition = PosFromValue(this.Value);
+ else
+ _dButtonPosition = IncrementalValue();
+ CreateGraphicsObjects();
+ }
+ DrawSlider();
+ }
+
+ /// Repaint the control
+ private void Repaint()
+ {
+ this.Invalidate();
+ this.Update();
+ }
+
+ /// Resize the control via alignments and options
+ private void ResizeThis()
+ {
+ int offset = 0;
+ int depth = 0;
+ int diff = 0;
+ Size sz = new Size(14, 14);
+
+ CalculateMaximumSize();
+ CalculateMinimumSize();
+
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ if (this.MinSize.Height == 0 || this.MaxSize.Height == 0)
+ return;
+
+ if (this.Height <= this.MinSize.Height)
+ this.Height = this.MinSize.Height;
+ else if (this.Height >= this.MaxSize.Height)
+ this.Height = this.MaxSize.Height;
+
+ offset = this.Height - this.MinSize.Height;
+ diff = this.MinSize.Height - ButtonSize.Height;
+
+ if (offset < 2)
+ depth = TrackMinDepth;
+ else if (offset < 3)
+ depth = TrackMinDepth + 1;
+ else if (offset < 4)
+ depth = TrackMinDepth + 2;
+ else
+ depth = TrackMaxDepth;
+
+ switch (this.ButtonStyle)
+ {
+ case ButtonType.GlassInline:
+ {
+ sz.Height = depth + 6;
+ sz.Width = sz.Height * 2;
+ break;
+ }
+ case ButtonType.RoundedRectInline:
+ {
+ sz.Height = depth + 6;
+ sz.Width = sz.Height * 2;
+ break;
+ }
+ case ButtonType.GlassOverlap:
+ {
+ sz.Height = depth * 4;
+ sz.Width = depth + 6;
+ break;
+ }
+ case ButtonType.RoundedRectOverlap:
+ {
+ sz.Height = depth * 4;
+ sz.Width = depth + 6;
+ break;
+ }
+ case ButtonType.Round:
+ case ButtonType.Hybrid:
+ {
+ sz.Height = depth + 8;
+ sz.Width = sz.Height;
+ break;
+ }
+ case ButtonType.PointerDownLeft:
+ case ButtonType.PointerUpRight:
+ {
+ sz.Height = depth * 4;
+ sz.Width = depth + 2;
+ break;
+ }
+ default:
+ {
+ sz.Height = depth * 4;
+ sz.Width = depth + 2;
+ break;
+ }
+ }
+
+ if (this.Width < (this.ButtonSize.Height + this.TrackPadding) * 2)
+ this.Width = (this.ButtonSize.Height + this.TrackPadding) * 2;
+ if (sz.Height != this.ButtonSize.Height && this.Height >= sz.Height + diff)
+ {
+ _iTrackDepth = depth;
+ _szButtonSize = sz;
+ }
+ else if (sz.Height != this.ButtonSize.Height && this.Height < this.ButtonSize.Height + diff)
+ {
+ _iTrackDepth = depth;
+ _szButtonSize = sz;
+ }
+ }
+ else
+ {
+ if (this.MinSize.Width == 0 || this.MaxSize.Width == 0)
+ return;
+
+ if (this.Width <= this.MinSize.Width)
+ this.Width = this.MinSize.Width;
+ else if (this.Width >= this.MaxSize.Width)
+ this.Width = this.MaxSize.Width;
+
+ offset = this.Width - this.MinSize.Width;
+
+ if (offset < 2)
+ depth = TrackMinDepth;
+ else if (offset < 3)
+ depth = TrackMinDepth + 1;
+ else if (offset < 4)
+ depth = TrackMinDepth + 2;
+ else
+ depth = TrackMaxDepth;
+
+ switch (this.ButtonStyle)
+ {
+ case ButtonType.GlassInline:
+ {
+ sz.Width = depth + 6;
+ sz.Height = sz.Width * 2;
+ break;
+ }
+ case ButtonType.RoundedRectInline:
+ {
+ sz.Width = depth + 6;
+ sz.Height = sz.Width * 2;
+ break;
+ }
+ case ButtonType.GlassOverlap:
+ {
+ sz.Width = depth * 4;
+ sz.Height = depth + 6;
+ break;
+ }
+ case ButtonType.RoundedRectOverlap:
+ {
+ sz.Width = depth * 4;
+ sz.Height = depth + 6;
+ break;
+ }
+ case ButtonType.Round:
+ case ButtonType.Hybrid:
+ {
+ sz.Width = depth + 8;
+ sz.Height = sz.Width;
+ break;
+ }
+ case ButtonType.PointerDownLeft:
+ case ButtonType.PointerUpRight:
+ {
+ sz.Width = depth * 4;
+ sz.Height = depth + 2;
+ break;
+ }
+ default:
+ {
+ sz.Width = depth * 4;
+ sz.Height = depth + 2;
+ break;
+ }
+ }
+
+ if (this.Height < (this.ButtonSize.Width + this.TrackPadding) * 2)
+ this.Height = (this.ButtonSize.Width + this.TrackPadding) * 2;
+
+ if (sz.Width != this.ButtonSize.Width && this.Width >= sz.Width + diff)
+ {
+ _iTrackDepth = depth;
+ _szButtonSize = sz;
+ }
+ else if (sz.Width != this.ButtonSize.Width && this.Width < this.ButtonSize.Width + diff)
+ {
+ _iTrackDepth = depth;
+ _szButtonSize = sz;
+ }
+ }
+ }
+
+ /// Scroll by large or small change values
+ private void ScrollChange(ChangeType change, bool decrease)
+ {
+ int count = 0;
+ if (change == ChangeType.Large)
+ {
+ if (decrease)
+ count = this.Value - LargeChange;
+ else
+ count = this.Value + LargeChange;
+ }
+ else
+ {
+ if (decrease)
+ count = this.Value - SmallChange;
+ else
+ count = this.Value + SmallChange;
+ }
+
+ if (count < this.Minimum)
+ count = this.Minimum;
+ if (count > this.Maximum)
+ count = this.Maximum;
+
+ this.Value = count;
+ }
+
+ /// Estimate value from position
+ public int ValueFromPosition()
+ {
+ try
+ {
+ int pos = this.PointToClient(Cursor.Position).X;
+ double increment = Increment();
+ int sz = (Orientation == Orientation.Horizontal) ? this.ButtonSize.Width : this.ButtonSize.Height;
+ double val = IncrementalValue();
+ pos -= (sz / 2);
+
+ if (pos > -sz)
+ {
+ if (pos < this.TrackPadding)
+ pos = this.TrackPadding;
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ if (pos > PosFromValue(this.Maximum) + this.TrackPadding)
+ pos = (int)PosFromValue(this.Maximum) + this.TrackPadding;
+ }
+ else
+ {
+ if (pos > PosFromValue(this.Minimum) + this.TrackPadding)
+ pos = (int)PosFromValue(this.Minimum) + this.TrackPadding;
+ }
+ pos -= this.TrackPadding;
+ }
+ return ValueFromPos(pos);
+ }
+ catch { return 0; }
+ }
+
+ /// Scroll the slider to a position and set value
+ private void ScrollThis(double pos)
+ {
+ bool redraw = false;
+ double val;
+ double store = _dButtonPosition;
+ double increment = Increment();
+ int sz = (Orientation == Orientation.Horizontal) ? this.ButtonSize.Width : this.ButtonSize.Height;
+
+ val = IncrementalValue();
+ pos -= (sz / 2); //ju 1.3
+
+ if (pos > -sz)
+ {
+ if (SmoothScrolling)
+ {
+ if (pos < this.TrackPadding)
+ pos = this.TrackPadding;
+ if (this.Orientation == Orientation.Horizontal)
+ {
+ if (pos > PosFromValue(this.Maximum) + this.TrackPadding)
+ pos = PosFromValue(this.Maximum) + this.TrackPadding;
+ }
+ else
+ {
+ if (pos > PosFromValue(this.Minimum) + this.TrackPadding)
+ pos = PosFromValue(this.Minimum) + this.TrackPadding;
+ }
+ pos -= this.TrackPadding;
+ _dButtonPosition = pos;
+ if (store != pos)
+ {
+ val = this.Value;
+ _iValue = ValueFromPos(pos);
+ if (_iValue != val)
+ {
+ if (ValueChanged != null)
+ ValueChanged(this, EventArgs.Empty);
+ }
+ DrawSlider();
+ }
+ if (Scrolled != null)
+ Scrolled(this, EventArgs.Empty);
+ }
+ else
+ {
+ store = this.Value;
+ //pos -= this.TrackPadding; ju 1.3
+
+ if (pos > val + increment &&
+ (Orientation == Orientation.Horizontal && this.Value != this.Maximum) ||
+ (Orientation == Orientation.Vertical && this.Value != this.Minimum))
+ {
+ _iValue = ValueFromPos(pos);
+ if (Scrolled != null)
+ Scrolled(this, EventArgs.Empty);
+ }
+ else if (pos < val && // ju 1.3
+ (Orientation == Orientation.Horizontal && this.Value != this.Minimum) ||
+ (Orientation == Orientation.Vertical && this.Value != this.Maximum))
+ {
+ _iValue = ValueFromPos(pos);
+ if (Scrolled != null)
+ Scrolled(this, EventArgs.Empty);
+ }
+ if (_iValue != store)
+ this.Value = _iValue;
+ else if (redraw)
+ DrawSlider();
+ }
+
+ }
+ }
+
+ /// Mouse Hit test
+ private HitTest SliderHitTest()
+ {
+ Point pt = new Point();
+ RECT tr = new RECT();
+
+ GetClientRect(this.Handle, ref tr);
+ GetCursorPos(ref pt);
+ ScreenToClient(this.Handle, ref pt);
+ if (PtInRect(ref _buttonRect, pt))
+ return HitTest.Button;
+ else if (PtInRect(ref _trackRect, pt))
+ return HitTest.Track;
+ else
+ return HitTest.Nowhere;
+ }
+
+ /// The value at a provided position
+ private int ValueFromPos(double pos)
+ {
+ int val;
+ //pos -= this.TrackPadding;
+ if (Orientation == Orientation.Horizontal)
+ val = this.Minimum + (int)Math.Round(pos / Increment());
+ else
+ val = this.Maximum - (int)Math.Round(pos / Increment());
+
+ if (val < this.Minimum)
+ val = this.Minimum;
+ if (val > this.Maximum)
+ val = this.Maximum;
+ return val;
+ }
+ #endregion
+ #endregion
+
+ #region Graphics Mode
+ /// Maintains graphic object state
+ internal class GraphicsMode : IDisposable
+ {
+ #region Fields
+ private Graphics _gGraphicCopy;
+ private SmoothingMode _eOldMode;
+ #endregion
+
+ #region Methods
+ ///
+ /// Initialize a new instance of the class.
+ ///
+ /// Graphics instance.
+ /// Desired Smoothing mode.
+ public GraphicsMode(Graphics g, SmoothingMode mode)
+ {
+ _gGraphicCopy = g;
+ _eOldMode = _gGraphicCopy.SmoothingMode;
+ _gGraphicCopy.SmoothingMode = mode;
+ }
+
+ ///
+ /// Revert the SmoothingMode to original setting.
+ ///
+ public void Dispose()
+ {
+ _gGraphicCopy.SmoothingMode = _eOldMode;
+ }
+ #endregion
+ }
+ #endregion
+
+ #region Effects Timer
+ /// Effect timer class
+ internal class FadeTimer : IDisposable
+ {
+ #region Enum
+ internal enum FadeType
+ {
+ None = 0,
+ FadeIn,
+ FadeOut,
+ FadeFast,
+ Loop
+ }
+ #endregion
+
+ #region Structs
+ [StructLayout(LayoutKind.Sequential)]
+ private struct RECT
+ {
+ public RECT(int X, int Y, int Width, int Height)
+ {
+ this.Left = X;
+ this.Top = Y;
+ this.Right = Width;
+ this.Bottom = Height;
+ }
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+ }
+ #endregion
+
+ #region API
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetDC(IntPtr handle);
+
+ [DllImport("user32.dll")]
+ private static extern int ReleaseDC(IntPtr handle, IntPtr hdc);
+
+ [DllImport("gdi32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetDesktopWindow();
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
+ #endregion
+
+ #region Events
+ public delegate void CompleteDelegate(object sender);
+ public delegate void TickDelegate(object sender);
+ public event CompleteDelegate Complete;
+ public event TickDelegate Tick;
+ #endregion
+
+ #region Fields
+ private bool _bCaptureScreen = false;
+ private bool _bCancelTimer;
+ private bool _bIsReset;
+ private int _iTickCounter;
+ private int _iTickMaximum;
+ private double _iTickRate;
+ private FadeType _eFadeType;
+ private cStoreDc _cButtonDc;
+ private UserControl _ctParentControl;
+ private System.Timers.Timer _aTimer;
+ private bool _bInvalidating = false;
+ #endregion
+
+ #region Constructor
+ public FadeTimer(object sender)
+ {
+ _iTickCounter = 0;
+ _iTickMaximum = 10;
+ _ctParentControl = (UserControl)sender;
+ _aTimer = new System.Timers.Timer();
+ _iTickRate = _aTimer.Interval;
+ _aTimer.SynchronizingObject = (ISynchronizeInvoke)sender;
+ _aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
+ }
+ #endregion
+
+ #region Properties
+ public cStoreDc ButtonDc
+ {
+ get { return _cButtonDc; }
+ set { _cButtonDc = value; }
+ }
+
+ public bool CaptureScreen
+ {
+ get { return _bCaptureScreen; }
+ set { _bCaptureScreen = value; }
+ }
+
+ public bool Invalidating
+ {
+ get { return _bInvalidating; }
+ set { _bInvalidating = value; }
+ }
+
+ public bool IsReset
+ {
+ get { return _bIsReset; }
+ set { _bIsReset = value; }
+ }
+
+ public bool Cancel
+ {
+ get { return _bCancelTimer; }
+ set { _bCancelTimer = value; }
+ }
+
+ public bool Enabled
+ {
+ get { return _aTimer.Enabled; }
+ }
+
+ public FadeType FadeStyle
+ {
+ get { return _eFadeType; }
+ set { _eFadeType = value; }
+ }
+
+ public double Interval
+ {
+ get { return _iTickRate; }
+ set
+ {
+ _iTickRate = value;
+ _aTimer.Interval = _iTickRate;
+ }
+ }
+
+ public int TickCount
+ {
+ get { return _iTickCounter; }
+ set { _iTickCounter = value; }
+ }
+
+ public int TickMaximum
+ {
+ get { return _iTickMaximum; }
+ set { _iTickMaximum = value; }
+ }
+ #endregion
+
+ #region Public Methods
+ public void Dispose()
+ {
+ Reset();
+ if (_cButtonDc != null)
+ _cButtonDc.Dispose();
+ if (_aTimer != null)
+ _aTimer.Dispose();
+ GC.SuppressFinalize(this);
+ }
+
+ public void Fade(FadeType ft)
+ {
+ Cancel = false;
+ IsReset = false;
+ Invalidating = false;
+ _eFadeType = ft;
+ if (_eFadeType == FadeType.FadeIn)
+ {
+ TickCount = 0;
+ if (CaptureScreen)
+ CaptureDc();
+ }
+ else if (_eFadeType == FadeType.FadeOut)
+ {
+ TickCount = 10;
+ }
+ else if (_eFadeType == FadeType.FadeFast)
+ {
+ TickCount = 10;
+ }
+ else if (_eFadeType == FadeType.Loop)
+ {
+ TickMaximum = 100000;
+ TickCount = 0;
+ if (CaptureScreen)
+ CaptureDc();
+ }
+ _aTimer.Enabled = true;
+ }
+
+ public void Stop()
+ {
+ _aTimer.Stop();
+ }
+
+ public void Reset()
+ {
+ TickCount = 0;
+ _eFadeType = FadeType.None;
+ IsReset = true;
+ _aTimer.Stop();
+ _aTimer.Enabled = false;
+ }
+ #endregion
+
+ #region Event Handlers
+ private void OnTimedEvent(object source, ElapsedEventArgs e)
+ {
+ if (Cancel)
+ {
+ Invalidating = true;
+ if (Complete != null) Complete(this);
+ return;
+ }
+ else
+ {
+ switch (_eFadeType)
+ {
+ case FadeType.FadeIn:
+ FadeIn();
+ break;
+ case FadeType.FadeFast:
+ FadeOut();
+ break;
+ case FadeType.FadeOut:
+ FadeOut();
+ break;
+ case FadeType.Loop:
+ FadeLoop();
+ break;
+ }
+ }
+ }
+ #endregion
+
+ #region private Methods
+ private void CaptureDc()
+ {
+ try
+ {
+ _cButtonDc.Width = _ctParentControl.Width;
+ _cButtonDc.Height = _ctParentControl.Height;
+ if (_cButtonDc.Hdc != IntPtr.Zero)
+ {
+ using (Graphics g = Graphics.FromHdc(_cButtonDc.Hdc))
+ {
+ RECT boundedRect = new RECT();
+ GetWindowRect(_ctParentControl.Handle, ref boundedRect);
+ g.CopyFromScreen(boundedRect.Left, boundedRect.Top, 0, 0, new Size(_cButtonDc.Width, _cButtonDc.Height), CopyPixelOperation.SourceCopy);
+ }
+ }
+ }
+ catch { }
+ }
+
+ private void FadeIn()
+ {
+ if (TickCount < TickMaximum)
+ {
+ TickCount++;
+ if (Tick != null)
+ Tick(this);
+ }
+ else
+ {
+ TickCount = TickMaximum;
+ }
+ }
+
+ private void FadeLoop()
+ {
+ if (TickCount < TickMaximum)
+ {
+ TickCount++;
+ if (Tick != null)
+ Tick(this);
+ }
+ else
+ {
+ TickCount = TickMaximum;
+ Reset();
+ Invalidating = true;
+ if (Complete != null)
+ Complete(this);
+ }
+ }
+
+ private void FadeOut()
+ {
+ if (TickCount > 0)
+ {
+ if (_eFadeType == FadeType.FadeFast)
+ {
+ TickCount -= 2;
+ if (TickCount < 0)
+ TickCount = 0;
+ }
+ else
+ {
+ TickCount--;
+ }
+ if (Tick != null)
+ Tick(this);
+ }
+ else
+ {
+ Reset();
+ Invalidating = true;
+ if (Complete != null)
+ Complete(this);
+ }
+ }
+
+ ~FadeTimer()
+ {
+ Dispose();
+ }
+ #endregion
+ }
+ #endregion
+
+ public class FlyOutEventArgs : EventArgs
+ {
+ public string text = "";
+ }
+
+ #region StoreDc
+ /// DC buffer class
+ internal class cStoreDc
+ {
+ #region API
+ [DllImport("gdi32.dll")]
+ private static extern IntPtr CreateDCA([MarshalAs(UnmanagedType.LPStr)]string lpszDriver, [MarshalAs(UnmanagedType.LPStr)]string lpszDevice, [MarshalAs(UnmanagedType.LPStr)]string lpszOutput, int lpInitData);
+
+ [DllImport("gdi32.dll")]
+ private static extern IntPtr CreateDCW([MarshalAs(UnmanagedType.LPWStr)]string lpszDriver, [MarshalAs(UnmanagedType.LPWStr)]string lpszDevice, [MarshalAs(UnmanagedType.LPWStr)]string lpszOutput, int lpInitData);
+
+ [DllImport("gdi32.dll")]
+ private static extern IntPtr CreateDC(string lpszDriver, string lpszDevice, string lpszOutput, int lpInitData);
+
+ [DllImport("gdi32.dll")]
+ private static extern IntPtr CreateCompatibleDC(IntPtr hdc);
+
+ [DllImport("gdi32.dll")]
+ private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
+
+ [DllImport("gdi32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool DeleteDC(IntPtr hdc);
+
+ [DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true)]
+ private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
+
+ [DllImport("gdi32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool DeleteObject(IntPtr hObject);
+ #endregion
+
+ #region Fields
+ private int _Height = 0;
+ private int _Width = 0;
+ private IntPtr _Hdc = IntPtr.Zero;
+ private IntPtr _Bmp = IntPtr.Zero;
+ private IntPtr _BmpOld = IntPtr.Zero;
+ #endregion
+
+ #region Methods
+ public IntPtr Hdc
+ {
+ get { return _Hdc; }
+ }
+
+ public IntPtr HBmp
+ {
+ get { return _Bmp; }
+ }
+
+ public int Height
+ {
+ get { return _Height; }
+ set
+ {
+ if (_Height != value)
+ {
+ _Height = value;
+ ImageCreate(_Width, _Height);
+ }
+ }
+ }
+
+ public int Width
+ {
+ get { return _Width; }
+ set
+ {
+ if (_Width != value)
+ {
+ _Width = value;
+ ImageCreate(_Width, _Height);
+ }
+ }
+ }
+
+ public void SelectImage(Bitmap image)
+ {
+ if (Hdc != IntPtr.Zero && image != null)
+ SelectObject(Hdc, image.GetHbitmap());
+ }
+
+ private void ImageCreate(int Width, int Height)
+ {
+ IntPtr pHdc = IntPtr.Zero;
+
+ ImageDestroy();
+ pHdc = CreateDCA("DISPLAY", "", "", 0);
+ _Hdc = CreateCompatibleDC(pHdc);
+ _Bmp = CreateCompatibleBitmap(pHdc, _Width, _Height);
+ _BmpOld = SelectObject(_Hdc, _Bmp);
+ if (_BmpOld == IntPtr.Zero)
+ {
+ ImageDestroy();
+ }
+ else
+ {
+ _Width = Width;
+ _Height = Height;
+ }
+ DeleteDC(pHdc);
+ pHdc = IntPtr.Zero;
+ }
+
+ private void ImageDestroy()
+ {
+ if (_BmpOld != IntPtr.Zero)
+ {
+ SelectObject(_Hdc, _BmpOld);
+ _BmpOld = IntPtr.Zero;
+ }
+ if (_Bmp != IntPtr.Zero)
+ {
+ DeleteObject(_Bmp);
+ _Bmp = IntPtr.Zero;
+ }
+ if (_Hdc != IntPtr.Zero)
+ {
+ DeleteDC(_Hdc);
+ _Hdc = IntPtr.Zero;
+ }
+ }
+
+ public void Dispose()
+ {
+ ImageDestroy();
+ }
+ #endregion
+ }
+ #endregion
+ }
+}
+
diff --git a/CUEControls/PeakMeterCtrl.Designer.cs b/CUEControls/PeakMeterCtrl.Designer.cs
new file mode 100644
index 0000000..47d8b59
--- /dev/null
+++ b/CUEControls/PeakMeterCtrl.Designer.cs
@@ -0,0 +1,39 @@
+using System;
+namespace Ernzo.WinForms.Controls
+{
+ partial class PeakMeterCtrl
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ StopAnimation();
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+
+ #endregion
+
+ }
+}
diff --git a/CUEControls/PeakMeterCtrl.cs b/CUEControls/PeakMeterCtrl.cs
new file mode 100644
index 0000000..2266db7
--- /dev/null
+++ b/CUEControls/PeakMeterCtrl.cs
@@ -0,0 +1,767 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2008 Ernest Laurentin (elaurentin@netzero.net)
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+///////////////////////////////////////////////////////////////////////////////
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+using System.Threading;
+
+namespace Ernzo.WinForms.Controls
+{
+ public enum PeakMeterStyle
+ {
+ PMS_Horizontal = 0,
+ PMS_Vertical = 1
+ }
+
+ internal struct PeakMeterData
+ {
+ public int Value;
+ public int Falloff;
+ public int Speed;
+ }
+
+ [ToolboxBitmap(typeof(MyResourceNamespace), "pmicon.bmp")]
+ public partial class PeakMeterCtrl : Control
+ {
+ private const byte DarkenByDefault = 40;
+ private const byte LightenByDefault = 150;
+ private const int MinRangeDefault = 60;
+ private const int MedRangeDefault = 80;
+ private const int MaxRangeDefault = 100;
+ private const int FalloffFast = 1;
+ private const int FalloffNormal = 10;
+ private const int FalloffSlow = 100;
+ private const int FalloffDefault = 10;
+ private const int DecrementPercent = 10;
+ private const int BandsMin = 1;
+ private const int BandsMax = 1000;
+ private const int BandsDefault = 8;
+ private const int LEDMin = 1;
+ private const int LEDMax = 1000;
+ private const int LEDDefault = 8;
+ private const int cxyMargin = 1;
+
+ private int _AnimDelay;
+ private int _MinRangeValue;
+ private int _MedRangeValue;
+ private int _MaxRangeValue;
+ private PeakMeterData[] _meterData;
+ private System.Threading.Timer _animationTimer;
+ public PeakMeterCtrl()
+ {
+ InitializeComponent();
+ InitDefault();
+ this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
+ this.SetStyle(ControlStyles.UserPaint, true);
+ //this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+ }
+
+ private void InitDefault()
+ {
+ _AnimDelay = Timeout.Infinite;
+ _MinRangeValue = MinRangeDefault; // [0,60[
+ _MedRangeValue = MedRangeDefault; // [60,80[
+ _MaxRangeValue = MaxRangeDefault; // [80,100[
+ _meterData = null;
+ _animationTimer = null;
+ _ShowGrid = true;
+ _ColoredGrid = false;
+ _GridColor = Color.Gainsboro;
+ _ColorNormal = Color.Green;
+ _ColorMedium = Color.Yellow;
+ _ColorHigh = Color.Red;
+ _ColorNormalBack = LightenColor(_ColorNormal, LightenByDefault);
+ _ColorMediumBack = LightenColor(_ColorMedium, LightenByDefault);
+ _ColorHighBack = LightenColor(_ColorHigh, LightenByDefault);
+ _BandsCount = BandsDefault;
+ _LEDCount = LEDDefault;
+ _FalloffSpeed = FalloffNormal;
+ _FalloffEffect = true;
+ _FalloffColor = DarkenColor(_GridColor, DarkenByDefault);
+ ResetControl();
+ }
+
+ #region Control properties
+ private PeakMeterStyle _PmsMeterStyle;
+ [Category("Appearance"), DefaultValue(PeakMeterStyle.PMS_Horizontal)]
+ public PeakMeterStyle MeterStyle
+ {
+ get { return _PmsMeterStyle; }
+ set { _PmsMeterStyle = value; Refresh(); }
+ }
+
+ private bool _ShowGrid;
+ [Category("Appearance"), DefaultValue(true)]
+ public bool ShowGrid
+ {
+ get { return _ShowGrid; }
+ set { _ShowGrid = value; Refresh(); }
+ }
+
+ private bool _ColoredGrid;
+ [Category("Appearance"), DefaultValue(false)]
+ public bool ColoredGrid
+ {
+ get { return _ColoredGrid; }
+ set { _ColoredGrid = value; Refresh(); }
+ }
+
+ private Color _GridColor;
+ [Category("Appearance")]
+ public Color GridColor
+ {
+ get { return _GridColor; }
+ set { _GridColor = value; Refresh(); }
+ }
+
+ private Color _ColorNormal;
+ [Category("Appearance")]
+ public Color ColorNormal
+ {
+ get { return _ColorNormal; }
+ set { _ColorNormal = value; Refresh(); }
+ }
+
+ private Color _ColorMedium;
+ [Category("Appearance")]
+ public Color ColorMedium
+ {
+ get { return _ColorMedium; }
+ set { _ColorMedium = value; Refresh(); }
+ }
+
+ private Color _ColorHigh;
+ [Category("Appearance")]
+ public Color ColorHigh
+ {
+ get { return _ColorHigh; }
+ set { _ColorHigh = value; Refresh(); }
+ }
+
+ private Color _ColorNormalBack;
+ [Category("Appearance")]
+ public Color ColorNormalBack
+ {
+ get { return _ColorNormalBack; }
+ set { _ColorNormalBack = value; Refresh(); }
+ }
+
+ private Color _ColorMediumBack;
+ [Category("Appearance")]
+ public Color ColorMediumBack
+ {
+ get { return _ColorMediumBack; }
+ set { _ColorMediumBack = value; Refresh(); }
+ }
+
+ private Color _ColorHighBack;
+ [Category("Appearance")]
+ public Color ColorHighBack
+ {
+ get { return _ColorHighBack; }
+ set { _ColorHighBack = value; Refresh(); }
+ }
+
+ private int _BandsCount;
+ [Category("Appearance"), DefaultValue(BandsDefault)]
+ public int BandsCount
+ {
+ get { return _BandsCount; }
+ set {
+ if (value >= BandsMin && value <= BandsMax)
+ {
+ _BandsCount = value;
+ ResetControl();
+ Refresh();
+ }
+ }
+ }
+
+ private int _LEDCount;
+ [Category("Appearance"), DefaultValue(LEDDefault)]
+ public int LEDCount
+ {
+ get { return _LEDCount; }
+ set {
+ if (value >= LEDMin && value <= LEDMax)
+ {
+ _LEDCount = value;
+ Refresh();
+ }
+ }
+ }
+
+ private int _FalloffSpeed;
+ [Category("Falloff Effect"), DefaultValue(FalloffDefault)]
+ public int FalloffSpeed
+ {
+ get { return _FalloffSpeed; }
+ set { _FalloffSpeed = value; }
+ }
+
+ private bool _FalloffEffect;
+ [Category("Falloff Effect"), DefaultValue(true)]
+ public bool FalloffEffect
+ {
+ get { return _FalloffEffect; }
+ set { _FalloffEffect = value; }
+ }
+
+ private Color _FalloffColor;
+ [Category("Falloff Effect")]
+ public Color FalloffColor
+ {
+ get { return _FalloffColor; }
+ set { _FalloffColor = value; }
+ }
+
+ #endregion
+
+ [Browsable(false)]
+ public bool IsActive
+ {
+ get { return (_animationTimer != null); }
+ }
+
+ #region Control Methods
+
+ // support for thread-safe version
+ private delegate bool StartDelegate(int delay);
+ ///
+ /// Start animation
+ ///
+ ///
+ ///
+ public bool Start(int delay)
+ {
+ if (this.InvokeRequired)
+ {
+ StartDelegate startDelegate = new StartDelegate(this.Start);
+ return (bool)this.Invoke(startDelegate, delay);
+ }
+ _AnimDelay = delay;
+ return StartAnimation(delay);
+ }
+
+ // support for thread-safe version
+ private delegate bool StopDelegate();
+ ///
+ /// Stop Animation
+ ///
+ ///
+ public bool Stop()
+ {
+ if (this.InvokeRequired)
+ {
+ StopDelegate stopDelegate = new StopDelegate(this.Stop);
+ return (bool)this.Invoke(stopDelegate);
+ }
+ _AnimDelay = Timeout.Infinite;
+ return StopAnimation();
+ }
+
+ ///
+ /// Set number of LED bands
+ ///
+ /// Number of bands
+ /// Number of LED per bands
+ public void SetMeterBands(int BandsCount, int LEDCount)
+ {
+ if (BandsCount < BandsMin || BandsCount > BandsMax)
+ throw new ArgumentOutOfRangeException("BandsCount");
+ if (LEDCount < LEDMin || LEDCount > LEDMax)
+ throw new ArgumentOutOfRangeException("LEDCount");
+ _BandsCount = BandsCount;
+ _LEDCount = LEDCount;
+ ResetControl();
+ Refresh();
+ }
+
+ ///
+ /// Set range info
+ ///
+ /// Min Range
+ /// Medium Range
+ /// High Range
+ public void SetRange(int minRangeVal, int medRangeVal, int maxRangeVal)
+ {
+ if (maxRangeVal <= medRangeVal || medRangeVal < minRangeVal )
+ throw new ArgumentOutOfRangeException("minRangeVal");
+ _MinRangeValue = minRangeVal;
+ _MedRangeValue = medRangeVal;
+ _MaxRangeValue = maxRangeVal;
+ ResetControl();
+ Refresh();
+ }
+
+ // support for thread-safe version
+ private delegate bool SetDataDelegate(int[] arrayValue, int offset, int size);
+ ///
+ /// Set meter band value
+ ///
+ /// Array value for the bands
+ /// Starting offset position
+ /// Number of values to set
+ ///
+ public bool SetData(int[] arrayValue, int offset, int size)
+ {
+ if (arrayValue == null)
+ throw new ArgumentNullException("arrayValue");
+ if (arrayValue.Length < (offset + size))
+ throw new ArgumentOutOfRangeException("arrayValue");
+
+ if (this.InvokeRequired)
+ {
+ SetDataDelegate setDelegate = new SetDataDelegate(this.SetData);
+ return (bool)this.Invoke(setDelegate, arrayValue, offset, size);
+ }
+ bool isRunning = this.IsActive;
+
+ Monitor.Enter(this._meterData);
+
+ int maxIndex = offset + size;
+ for (int i = offset; i < maxIndex; i++)
+ {
+ if (i < this._meterData.Length)
+ {
+ PeakMeterData pm = this._meterData[i];
+ pm.Value = Math.Min(arrayValue[i], this._MaxRangeValue);
+ pm.Value = Math.Max(pm.Value, 0);
+ if (pm.Falloff < pm.Value)
+ {
+ pm.Falloff = pm.Value;
+ pm.Speed = this._FalloffSpeed;
+ }
+ this._meterData[i] = pm;
+ }
+ }
+ Monitor.Exit(this._meterData);
+
+ // check that timer should be restarted
+ if (_AnimDelay != Timeout.Infinite)
+ {
+ if (_animationTimer == null)
+ {
+ StartAnimation(_AnimDelay);
+ }
+ }
+ else
+ {
+ Refresh();
+ }
+
+ return isRunning;
+ }
+ #endregion
+
+ ///
+ /// Make a color darker
+ ///
+ /// Color to darken
+ /// Value to decrease by
+ protected virtual Color DarkenColor(Color color, byte darkenBy)
+ {
+ byte red = (byte)(color.R > darkenBy ? (color.R - darkenBy) : 0);
+ byte green = (byte)(color.G > darkenBy ? (color.G - darkenBy) : 0);
+ byte blue = (byte)(color.B > darkenBy ? (color.B - darkenBy) : 0);
+ return Color.FromArgb(red, green, blue);
+ }
+ ///
+ /// Make a color lighter
+ ///
+ ///
+ ///
+ ///
+ protected virtual Color LightenColor(Color color, byte lightenBy)
+ {
+ byte red = (byte)((color.R + lightenBy) <= 255 ? (color.R + lightenBy) : 255);
+ byte green = (byte)((color.G + lightenBy) <= 255 ? (color.G + lightenBy) : 255);
+ byte blue = (byte)((color.B + lightenBy) <= 255 ? (color.B + lightenBy) : 255);
+ return Color.FromArgb(red, green, blue);
+ }
+
+ protected static bool InRange(int value, int rangeMin, int rangeMax)
+ {
+ return (value >= rangeMin && value <= rangeMax);
+ }
+
+ protected void ResetControl()
+ {
+ _meterData = new PeakMeterData[_BandsCount];
+ PeakMeterData pm;
+ pm.Value = _MaxRangeValue;
+ pm.Falloff = _MaxRangeValue;
+ pm.Speed = _FalloffSpeed;
+ for (int i = 0; i < _meterData.Length; i++)
+ {
+ _meterData[i] = pm;
+ }
+ }
+ protected bool StartAnimation(int period)
+ {
+ if ( !IsActive )
+ {
+ TimerCallback timerDelegate =
+ new TimerCallback(TimerCallback);
+ _animationTimer = new System.Threading.Timer(timerDelegate, this, Timeout.Infinite, Timeout.Infinite);
+ }
+ return _animationTimer.Change(period, period);
+ }
+ protected bool StopAnimation()
+ {
+ bool result = false;
+ if ( IsActive )
+ {
+ try
+ {
+ result = _animationTimer.Change(Timeout.Infinite, Timeout.Infinite);
+ _animationTimer.Dispose();
+ _animationTimer = null;
+ result = true;
+ }
+ catch (Exception)
+ {
+ }
+ }
+ return result;
+ }
+
+ protected override void OnHandleDestroyed(EventArgs e)
+ {
+ Stop();
+ base.OnHandleDestroyed(e);
+ }
+ protected override void OnBackColorChanged(EventArgs e)
+ {
+ Refresh();
+ }
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ // Calling the base class OnPaint
+ base.OnPaint(e);
+
+ Graphics g = e.Graphics;
+ Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
+ Brush backColorBrush = new SolidBrush(this.BackColor);
+
+ g.FillRectangle(backColorBrush, rect);
+ //rect.Inflate(-this.Margin.Left, -this.Margin.Top);
+ if (MeterStyle == PeakMeterStyle.PMS_Horizontal)
+ {
+ DrawHorzBand(g, rect);
+ }
+ else
+ {
+ DrawVertBand(g, rect);
+ }
+ }
+
+ protected void TimerCallback(Object thisObject)
+ {
+ try
+ {
+ // refresh now!
+ Control thisControl = thisObject as Control;
+ if (thisControl != null && thisControl.IsHandleCreated)
+ {
+ thisControl.Invoke(new MethodInvoker(Refresh));
+ }
+ else
+ {
+ return;
+ }
+ }
+ catch (Exception)
+ {
+ // just ignore
+ }
+
+ int nDecValue = _MaxRangeValue / _LEDCount;
+ bool noUpdate = true;
+
+ Monitor.Enter(this._meterData);
+ for (int i = 0; i < _meterData.Length; i++)
+ {
+ PeakMeterData pm = _meterData[i];
+
+ if (pm.Value > 0)
+ {
+ pm.Value -= (_LEDCount > 1 ? nDecValue : (_MaxRangeValue * DecrementPercent) / 100);
+ if (pm.Value < 0)
+ pm.Value = 0;
+ noUpdate = false;
+ }
+
+ if (pm.Speed > 0)
+ {
+ pm.Speed -= 1;
+ noUpdate = false;
+ }
+
+ if (pm.Speed == 0 && pm.Falloff > 0)
+ {
+ pm.Falloff -= (_LEDCount > 1 ? nDecValue >> 1 : 5);
+ if (pm.Falloff < 0)
+ pm.Falloff = 0;
+ noUpdate = false;
+ }
+
+ // re-assign PeakMeterData
+ _meterData[i] = pm;
+ }
+ Monitor.Exit(this._meterData);
+
+ if (noUpdate) // Stop timer if no more data but do not reset ID
+ {
+ StopAnimation();
+ }
+ }
+ protected void DrawHorzBand(Graphics g, Rectangle rect)
+ {
+ int nMaxRange = (_MedRangeValue == 0) ? Math.Abs(_MaxRangeValue - _MinRangeValue) : _MaxRangeValue;
+ int nVertBands = (_LEDCount > 1 ? _LEDCount : (nMaxRange * DecrementPercent) / 100);
+ int nMinVertLimit = _MinRangeValue * nVertBands / nMaxRange;
+ int nMedVertLimit = _MedRangeValue * nVertBands / nMaxRange;
+ int nMaxVertLimit = nVertBands;
+
+ if (_MedRangeValue == 0)
+ {
+ nMedVertLimit = Math.Abs(_MinRangeValue) * nVertBands / nMaxRange;
+ nMinVertLimit = 0;
+ }
+ Size size = new Size(rect.Width/_BandsCount, rect.Height/nVertBands);
+ Rectangle rcBand = new Rectangle(rect.Location, size);
+
+ // Draw band from bottom
+ rcBand.Offset(0, rect.Height-size.Height);
+ int xDecal = (_BandsCount>1 ? cxyMargin : 0);
+ //int yDecal = 0;
+
+ Color gridPenColor = (this.ShowGrid ? GridColor : BackColor);
+ Pen gridPen = new Pen(gridPenColor);
+ Pen fallPen = new Pen( this.FalloffColor );
+
+ for(int nHorz=0; nHorz < _BandsCount; nHorz++)
+ {
+ int nValue = _meterData[nHorz].Value;
+ int nVertValue = nValue*nVertBands/nMaxRange;
+ Rectangle rcPrev = rcBand;
+
+ for(int nVert=0; nVert < nVertBands; nVert++)
+ {
+ // Find color based on range value
+ Color colorBand = gridPenColor;
+
+ // Draw grid line (level) bar
+ if ( this.ShowGrid && (nVert == nMinVertLimit || nVert == nMedVertLimit || nVert == (nVertBands-1)))
+ {
+ Point []points = new Point[2];
+ points[0].X = rcBand.Left;
+ points[0].Y = rcBand.Top + (rcBand.Height>>1);
+ points[1].X = rcBand.Right;
+ points[1].Y = points[0].Y;
+ g.DrawPolygon(gridPen, points);
+ }
+
+ if ( _MedRangeValue == 0 )
+ {
+ int nVertStart = nMedVertLimit+nVertValue;
+ if ( InRange(nVert, nVertStart, nMedVertLimit-1) )
+ colorBand = this.ColorNormal;
+ else if ( nVert >= nMedVertLimit && InRange(nVert, nMedVertLimit, nVertStart) )
+ colorBand = this.ColorHigh;
+ else {
+ colorBand = (nVert < nMedVertLimit) ? this.ColorNormalBack : this.ColorHighBack;
+ }
+ }
+ else if ( nVertValue < nVert )
+ {
+ if ( this.ShowGrid && this.ColoredGrid )
+ {
+ if ( InRange(nVert, 0, nMinVertLimit) )
+ colorBand = this.ColorNormalBack;
+ else if ( InRange(nVert, nMinVertLimit+1, nMedVertLimit) )
+ colorBand = this.ColorMediumBack;
+ else if ( InRange(nVert, nMedVertLimit+1, nMaxVertLimit) )
+ colorBand = this.ColorHighBack;
+ }
+ } else {
+ if (nValue == 0)
+ {
+ if (this.ShowGrid && this.ColoredGrid)
+ colorBand = this.ColorNormalBack;
+ }
+ else if ( InRange(nVert, 0, nMinVertLimit) )
+ colorBand = this.ColorNormal;
+ else if ( InRange(nVert, nMinVertLimit+1, nMedVertLimit) )
+ colorBand = this.ColorMedium;
+ else if ( InRange(nVert, nMedVertLimit+1, nMaxVertLimit) )
+ colorBand = this.ColorHigh;
+ }
+
+ if (colorBand != this.BackColor)
+ {
+ SolidBrush fillBrush = new SolidBrush(colorBand);
+ if (this._LEDCount > 1)
+ rcBand.Inflate(-cxyMargin, -cxyMargin);
+ g.FillRectangle(fillBrush, rcBand.Left, rcBand.Top, rcBand.Width+1, rcBand.Height);
+ if (this._LEDCount > 1)
+ rcBand.Inflate(cxyMargin, cxyMargin);
+ }
+ rcBand.Offset(0, -size.Height);
+ }
+
+ // Draw falloff effect
+ if (this.FalloffEffect && this.IsActive)
+ {
+ int nMaxHeight = size.Height*nVertBands;
+ Point []points = new Point[2];
+ points[0].X = rcPrev.Left + xDecal;
+ points[0].Y = rcPrev.Bottom - (_meterData[nHorz].Falloff * nMaxHeight) / _MaxRangeValue;
+ points[1].X = rcPrev.Right - xDecal;
+ points[1].Y = points[0].Y;
+ g.DrawPolygon(fallPen, points);
+ }
+
+ // Move to Next Horizontal band
+ rcBand.Offset(size.Width, size.Height * nVertBands);
+ }
+ }
+ protected void DrawVertBand(Graphics g, Rectangle rect)
+ {
+ int nMaxRange = (_MedRangeValue == 0) ? Math.Abs(_MaxRangeValue - _MinRangeValue) : _MaxRangeValue;
+ int nHorzBands = (_LEDCount > 1 ? _LEDCount : (nMaxRange * DecrementPercent) / 100);
+ int nMinHorzLimit = _MinRangeValue*nHorzBands/nMaxRange;
+ int nMedHorzLimit = _MedRangeValue*nHorzBands/nMaxRange;
+ int nMaxHorzLimit = nHorzBands;
+
+ if ( _MedRangeValue == 0 )
+ {
+ nMedHorzLimit = Math.Abs(_MinRangeValue)*nHorzBands/nMaxRange;
+ nMinHorzLimit = 0;
+ }
+
+ Size size = new Size(rect.Width/nHorzBands, rect.Height/_BandsCount);
+ Rectangle rcBand = new Rectangle(rect.Location, size);
+
+ // Draw band from top
+ rcBand.Offset(0, rect.Height-size.Height*_BandsCount);
+ //int xDecal = 0;
+ int yDecal = (_BandsCount>1 ? cxyMargin : 0);
+
+ Color gridPenColor = (this.ShowGrid ? GridColor : BackColor);
+ Pen gridPen = new Pen(gridPenColor);
+ Pen fallPen = new Pen( this.FalloffColor );
+
+ for(int nVert=0; nVert < _BandsCount; nVert++)
+ {
+ int nValue = _meterData[nVert].Value;
+ int nHorzValue = nValue*nHorzBands/nMaxRange;
+ Rectangle rcPrev = rcBand;
+
+ for(int nHorz=0; nHorz < nHorzBands; nHorz++)
+ {
+ // Find color based on range value
+ Color colorBand = gridPenColor;
+
+ if ( this.ShowGrid && (nHorz == nMinHorzLimit || nHorz == nMedHorzLimit || nHorz == (nHorzBands-1)))
+ {
+ Point []points = new Point[2];
+ points[0].X = rcBand.Left + (rcBand.Width>>1);
+ points[0].Y = rcBand.Top;
+ points[1].X = points[0].X;
+ points[1].Y = rcBand.Bottom;
+ g.DrawPolygon(gridPen, points);
+ }
+
+ if (_MedRangeValue == 0)
+ {
+ int nHorzStart = nMedHorzLimit+nHorzValue;
+ if ( InRange(nHorz, nHorzStart, nMedHorzLimit-1) )
+ colorBand = this.ColorNormal;
+ else if ( nHorz >= nMedHorzLimit && InRange(nHorz, nMedHorzLimit, nHorzStart) )
+ colorBand = this.ColorHigh;
+ else {
+ colorBand = (nHorz < nMedHorzLimit) ? this.ColorNormalBack : this.ColorHighBack;
+ }
+ }
+ else if ( nHorzValue < nHorz )
+ {
+ if ( this.ShowGrid && this.ColoredGrid )
+ {
+ if ( InRange(nHorz, 0, nMinHorzLimit) )
+ colorBand = this.ColorNormalBack;
+ else if ( InRange(nHorz, nMinHorzLimit+1, nMedHorzLimit) )
+ colorBand = this.ColorMediumBack;
+ else if ( InRange(nHorz, nMedHorzLimit+1, nMaxHorzLimit) )
+ colorBand = this.ColorHighBack;
+ }
+ } else {
+ if (nValue == 0)
+ {
+ if (this.ShowGrid && this.ColoredGrid)
+ colorBand = this.ColorNormalBack;
+ }
+ else if (InRange(nHorz, 0, nMinHorzLimit))
+ colorBand = this.ColorNormal;
+ else if ( InRange(nHorz, nMinHorzLimit+1, nMedHorzLimit) )
+ colorBand = this.ColorMedium;
+ else if ( InRange(nHorz, nMedHorzLimit+1, nMaxHorzLimit) )
+ colorBand = this.ColorHigh;
+ }
+
+ if (colorBand != this.BackColor)
+ {
+ SolidBrush fillBrush = new SolidBrush(colorBand);
+ if (this._LEDCount > 1)
+ rcBand.Inflate(-cxyMargin, -cxyMargin);
+ g.FillRectangle(fillBrush, rcBand.Left, rcBand.Top, rcBand.Width, rcBand.Height+1);
+ if (this._LEDCount > 1)
+ rcBand.Inflate(cxyMargin, cxyMargin);
+ }
+ rcBand.Offset(size.Width, 0);
+ }
+
+ // Draw falloff effect
+ if (this.FalloffEffect && this.IsActive)
+ {
+ int nMaxWidth = size.Width * nHorzBands;
+ Point[] points = new Point[2];
+ points[0].X = rcPrev.Left + (_meterData[nVert].Falloff * nMaxWidth) / _MaxRangeValue;
+ points[0].Y = rcPrev.Top + yDecal;
+ points[1].X = points[0].X;
+ points[1].Y = rcPrev.Bottom - yDecal;
+ g.DrawPolygon(fallPen, points);
+ }
+
+ // Move to Next Vertical band
+ rcBand.Offset(-size.Width*nHorzBands, size.Height);
+ }
+ }
+ }
+}
+
+// use this to find resource namespace
+internal class MyResourceNamespace
+{
+}
diff --git a/CUEControls/Properties/Resources.Designer.cs b/CUEControls/Properties/Resources.Designer.cs
index 27d4fe8..af671fe 100644
--- a/CUEControls/Properties/Resources.Designer.cs
+++ b/CUEControls/Properties/Resources.Designer.cs
@@ -66,5 +66,12 @@ namespace CUEControls.Properties {
return ((System.Drawing.Icon)(obj));
}
}
+
+ internal static System.Drawing.Bitmap pmicon {
+ get {
+ object obj = ResourceManager.GetObject("pmicon", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
}
}
diff --git a/CUEControls/Properties/Resources.resx b/CUEControls/Properties/Resources.resx
index fa9cc89..d8636ef 100644
--- a/CUEControls/Properties/Resources.resx
+++ b/CUEControls/Properties/Resources.resx
@@ -121,4 +121,7 @@
..\Resources\folder.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ ..\pmicon.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
\ No newline at end of file
diff --git a/CUEControls/Resources/pmicon.bmp b/CUEControls/Resources/pmicon.bmp
new file mode 100644
index 0000000..4ffc45a
Binary files /dev/null and b/CUEControls/Resources/pmicon.bmp differ
diff --git a/CUEControls/pmicon.bmp b/CUEControls/pmicon.bmp
new file mode 100644
index 0000000..4ffc45a
Binary files /dev/null and b/CUEControls/pmicon.bmp differ