Click here to Skip to main content
15,883,901 members
Articles / Programming Languages / C#

Personal Wave Recorder

Rate me:
Please Sign up or sign in to vote.
4.97/5 (94 votes)
19 Mar 2010CPOL15 min read 140.3K   11.7K   208  
DSP chains, Complex Fourier, ACM, Visualizers, EQ, Custom controls.. the works.
#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();
        public delegate void FlyOutInfoDelegate(ref string data);

        [Description("Callback event for the FlyOut window")]
        public event FlyOutInfoDelegate FlyOutInfo;
        #endregion

        #region Events and Delegates
        public delegate void ValueChangedDelegate(Object sender, EventArgs e);
        public delegate void ScrollDelegate(Object sender, EventArgs e);
        [Description("Raised when the Slider Value property changes")]
        public event ValueChangedDelegate ValueChanged;
        [Description("Raised when the mSlider has scrolled.")]
        public event ScrollDelegate 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 Image BackgroundImage
        {
            get { return base.BackgroundImage; }
            set { base.BackgroundImage = 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
        /// <summary>Run the animation effect when focused</summary>
        [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();
                }
            }
        }

        /// <summary>Animation cycle speed</summary>
        [Browsable(true), Category("Appearence"),
        Description("Animation cycle speed")]
        public AnimateSpeed AnimationSpeed
        {
            get { return _eAnimationSpeed; }
            set { _eAnimationSpeed = value; }
        }

        /// <summary>Percentage of size of sprite height/width to track height/width [min .05 - max .2]</summary>
        [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;
            }
        }

        /// <summary>Use an image for the slider background</summary>
        [Browsable(true), Category("Appearence"),
        Description("Use an image for the slider background")]
        public 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); }
            }
        }

        /// <summary>Modify button accent color</summary>
        [Browsable(true), Category("Appearence"),
        Description("Modify button accent color")]
        public Color ButtonAccentColor
        {
            get { return _clrButtonAccentColor; }
            set
            {
                _clrButtonAccentColor = value;
                PropertyChange();
            }
        }

        /// <summary>Modify button border color</summary>
        [Browsable(true), Category("Appearence"),
        Description("Modify button border color")]
        public Color ButtonBorderColor
        {
            get { return _clrButtonBorderColor; }
            set
            {
                _clrButtonBorderColor = value;
                PropertyChange();
            }
        }

        /// <summary>Modify button base color</summary>
        [Browsable(true), Category("Appearence"),
        Description("Modify button base color")]
        public Color ButtonColor
        {
            get { return _clrButtonColor; }
            set
            {
                _clrButtonColor = value;
                PropertyChange();
            }
        }

        /// <summary>Adjusts the slider buttons corner radius</summary>
        [Browsable(false),
        Description("Adjusts the slider buttons corner radius")]
        public uint ButtonCornerRadius
        {
            get { return (uint)_iButtonCornerRadius; }
            set { _iButtonCornerRadius = (int)value; }
        }

        /// <summary>Modify slider button size</summary>
        [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();
            }
        }

        /// <summary>Set the button style</summary>
        [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();
            }
        }

        /// <summary>Returns the property initiated state</summary>
        [Browsable(false),
        Description("Returns the property initiated state")]
        public bool IsInited
        {
            get { return this.Visible && _bPropInit; }
            private set { _bPropInit = this.Visible && value; }
        }

        /// <summary>The number of clicks the slider moves in response to mouse clicks or pageup/pagedown</summary>
        [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); }
            }
        }

        /// <summary>The maximum value for the position of the slider</summary>
        [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;
                }
            }
        }

        /// <summary>The maximum Size value for the control</summary>
        [Browsable(true), Category("Behavior"),
        Description("The maximum Size value for the control [private set]")]
        public Size MaxSize
        {
            get { return _szMaxSize; }
            private set { _szMaxSize = value; }
        }

        /// <summary>The minimum value for the position of the slider</summary>
        [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); }
            }
        }

        /// <summary>The minimum Size value for the control</summary>
        [Browsable(true), Category("Behavior"),
        Description("The minimum Size value for the control [private set]")]
        public Size MinSize
        {
            get { return _szMinSize; }
            private set { _szMinSize = value; }
        }

        /// <summary>The orientation of the control</summary>
        [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();
            }
        }

        /// <summary>Returns the slider position to a floating point, requires SmoothScrolling set to true</summary>
        [Browsable(false),
        Description("Returns the slider position to a floating point, requires SmoothScrolling set to true")]
        public double PrecisionValue
        {
            get { return IncrementalValue(); }
        }

        /// <summary>Show the slider button only when control is focused or mouse is hovering</summary>
        [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; }
        }

        /// <summary>Enable the flyout caption window</summary>
        [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();
            }
        }

        /// <summary>The number of positions the slider movers in response to arrow keys</summary>
        [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); }
            }
        }

        /// <summary>Run the animation effect when focused</summary>
        [Browsable(true), Category("Behavior"),
        Description("Enable smooth scrolling style")]
        public bool SmoothScrolling
        {
            get { return _bSmoothScrolling; }
            set { _bSmoothScrolling = value; }
        }

        /// <summary>Modify slider tick color</summary>
        [Browsable(true), Category("Appearence"),
        Description("Modify slider tick color")]
        public Color TickColor
        {
            get { return _clrTickColor; }
            set
            {
                _clrTickColor = value;
                PropertyChange();
            }
        }

        /// <summary>Select the tickstyle</summary>
        [Browsable(true), Category("Appearence"),
        Description("Select the tickstyle")]
        public TickStyle TickStyle
        {
            get { return _eTickStyle; }
            set
            {
                _eTickStyle = value;
                PropertyChange();
            }
        }

        /// <summary>Select the tick drawing style</summary>
        [Browsable(true), Category("Appearence"),
        Description("Select the tick drawing style")]
        public TickMode TickType
        {
            get { return _eTickType; }
            set
            {
                _eTickType = value;
                PropertyChange();
            }
        }

        /// <summary>Modify slider border color</summary>
        [Browsable(true), Category("Appearence"),
        Description("Modify slider border color")]
        public Color TrackBorderColor
        {
            get { return _clrTrackBorderColor; }
            set
            {
                _clrTrackBorderColor = value;
                PropertyChange();
            }
        }

        /// <summary>Adjust the slider track depth</summary>
        [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();
            }
        }

        /// <summary>Set the track fill color</summary>
        [Browsable(true), Category("Appearence"),
        Description("Set the track fill color")]
        public Color TrackFillColor
        {
            get { return _clrTrackFillColor; }
            set
            {
                _clrTrackFillColor = value;
                PropertyChange();
            }
        }

        /// <summary>Set the track progress color</summary>
        [Browsable(true), Category("Appearence"),
        Description("Set the track progress color")]
        public Color TrackProgressColor
        {
            get { return _clrTrackProgressColor; }
            set
            {
                _clrTrackProgressColor = value;
                PropertyChange();
            }
        }

        /// <summary>Enable track border shadow</summary>
        [Browsable(true), Category("Appearence"),
        Description("Enable track shadow")]
        public bool TrackShadow
        {
            get { return _bTrackShadow; }
            set
            {
                _bTrackShadow = value;
                PropertyChange();
            }
        }

        /// <summary>Modify track shadow color</summary>
        [Browsable(true), Category("Appearence"),
        Description("Modify track shadow color")]
        public Color TrackShadowColor
        {
            get { return _clrTrackShadowColor; }
            set
            {
                _clrTrackShadowColor = value;
                PropertyChange();
            }
        }

        /// <summary>Modify the display style of track</summary>
        [Browsable(true), Category("Appearence"),
        Description("Modify the display style of track")]
        public TrackType TrackStyle
        {
            get { return _eTrackStyle; }
            set
            {
                _eTrackStyle = value;
                PropertyChange();
            }
        }

        /// <summary>The position of the slider</summary>
        [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)
            {
                if (SliderHitTest() == HitTest.Track)
                {
                    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
        /// <summary>Drawing hub</summary>
        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);
            }
        }

        /// <summary>Backfill the buffer</summary>
        private void DrawBackGround(Graphics g, Rectangle bounds)
        {
            using (Brush br = new SolidBrush(this.BackColor))
                g.FillRectangle(br, bounds);
        }

        /// <summary>Adjust gamma of an image [not used]</summary>
        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);
            }
        }

        /// <summary>Draw a disabled image using the control</summary>
        private void DrawDisabledImage(Graphics g, Image image, Rectangle bounds)
        {
            ControlPaint.DrawImageDisabled(g, image, bounds.X, bounds.Y, Color.Transparent);
        }

        /// <summary>Draw an unaltered image</summary>
        private void DrawImage(Graphics g, Image image, Rectangle bounds)
        {
            g.DrawImage(image, bounds);
        }

        /// <summary>Draw the slider ticks</summary>
        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
            }
        }

        /// <summary>Draw slider and background dc</summary>
        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
        /// <summary>Create the button bitmap</summary>
        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();
        }

        /// <summary>Create graphics objects</summary>
        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();
        }

        /// <summary>create the animations sprite</summary>
        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);
        }

        /// <summary>Create the track dc</summary>
        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);
                    }
                }
            }
        }

        /// <summary>Destroy grahics objects</summary>
        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();
        }

        /// <summary>Destroy animation sprite</summary>
        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);
            }
        }

        /// <summary>Draws the line sprite</summary>
        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;
            string data = "";

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

                        if (FlyOutInfo != null)
                            FlyOutInfo(ref data);
                        if (data.Length == 0)
                            data = 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(data, 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);

                        if (FlyOutInfo != null)
                            FlyOutInfo(ref data);
                        if (data.Length == 0)
                            data = 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(data, ft, Brushes.Black, flyoutRect, sf);
                        }
                    }
                }
            }

        }
        #endregion
        #endregion

        #region Helpers
        /// <summary>AlphaBlend an image, alpha .1-1</summary>
        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);
            }
        }

        /// <summary>Maximun size based on control options</summary>
        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;
            }
        }

        /// <summary>Minimum size based on control options</summary>
        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;
        }

        /// <summary>Create a round GraphicsPath [not used]</summary>
        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;
        }

        /// <summary>Create a rounded rectangle GraphicsPath</summary>
        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;
        }

        /// <summary>Set default button sizes</summary>
        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;
            }
        }

        /// <summary>Return button size and coordinates</summary>
        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);
        }

        /// <summary>Return track size and coordinates</summary>
        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;
        }

        /// <summary>Exact size between ticks</summary>
        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());
        }

        /// <summary>Offset number if Minimum and Maximum are negative to positive integers</summary>
        private double IncrementOffset()
        {
            double center = 0;
            if (this.Minimum < 0 && this.Maximum > 0)
                center = 1;
            return center;
        }

        /// <summary>The total number of tick increments</summary>
        private double IncrementScale()
        {
            return (double)Math.Abs(this.Maximum - this.Minimum);
        }

        /// <summary>The incremental size between the Minimum and Value</summary>
        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)));
        }

        /// <summary>Modulus returns true if divisible with no remainder</summary>
        private bool Mod(int a, int b)
        {
            if (Math.IEEERemainder((double)a, (double)b) == 0)
                return true;
            return false;
        }

        /// <summary>Return position coordinates from value</summary>
        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)));
        }

        /// <summary>Repaint and optionally resize</summary>
        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();
        }

        /// <summary>Repaint the control</summary>
        private void Repaint()
        {
            this.Invalidate();
            this.Update();
        }

        /// <summary>Resize the control via alignments and options</summary>
        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;
                }
            }
        }

        /// <summary>Scroll by large or small change values</summary>
        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;
        }

        /// <summary>Estimate value from position</summary>
        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; }
        }

        /// <summary>Scroll the slider to a position and set value</summary>
        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 (Scrolled != null)
                        Scrolled(this, new EventArgs());
                    if (store != pos)
                    {
                        val = this.Value;
                        _iValue = ValueFromPos(pos);
                        if (_iValue != val)
                        {
                            if (ValueChanged != null)
                                ValueChanged(this, new EventArgs());
                        }
                        DrawSlider();
                    }
                }
                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, new EventArgs());
                    }
                    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, new EventArgs());
                    }
                    if (_iValue != store)
                        this.Value = _iValue;
                    else if (redraw)
                        DrawSlider();
                }

            }
        }

        /// <summary>Mouse Hit test</summary>
        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;
        }

        /// <summary>The value at a provided position</summary>
        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
        /// <summary>Maintains graphic object state</summary>
        internal class GraphicsMode : IDisposable
        {
            #region Fields
            private Graphics _gGraphicCopy;
            private SmoothingMode _eOldMode;
            #endregion

            #region Methods
            /// <summary>
            /// Initialize a new instance of the class.
            /// </summary>
            /// <param name="g">Graphics instance.</param>
            /// <param name="mode">Desired Smoothing mode.</param>
            public GraphicsMode(Graphics g, SmoothingMode mode)
            {
                _gGraphicCopy = g;
                _eOldMode = _gGraphicCopy.SmoothingMode;
                _gGraphicCopy.SmoothingMode = mode;
            }

            /// <summary>
            /// Revert the SmoothingMode to original setting.
            /// </summary>
            public void Dispose()
            {
                _gGraphicCopy.SmoothingMode = _eOldMode;
            }
            #endregion
        }
        #endregion

        #region Effects Timer
        /// <summary>Effect timer class</summary>
        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

        #region StoreDc
        /// <summary>DC buffer class</summary>
        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
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Network Administrator vtdev.com
Canada Canada
Network and programming specialist. Started in C, and have learned about 14 languages since then. Cisco programmer, and lately writing a lot of C# and WPF code, (learning Java too). If I can dream it up, I can probably put it to code. My software company, (VTDev), is on the verge of releasing a couple of very cool things.. keep you posted.

Comments and Discussions