ScrollBar.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / ScrollBar.cs / 1305376 / ScrollBar.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Windows.Forms { 
    using System.Runtime.Serialization.Formatters; 
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting; 
    using System.Diagnostics;

    using System;
    using System.Security.Permissions; 

    using System.Windows.Forms; 
    using System.ComponentModel; 
    using System.Drawing;
    using Microsoft.Win32; 
    using System.Globalization;


    ///  
    /// 
    ///     
    ///       Implements the basic functionality of a scroll bar control. 
    ///    
    ///  
    [
    ComVisible(true),
    ClassInterface(ClassInterfaceType.AutoDispatch),
    DefaultProperty("Value"), 
    DefaultEvent("Scroll"),
    System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors") // Shipped in Everett 
    ] 
    public abstract class ScrollBar : Control {
 
        private static readonly object EVENT_SCROLL = new object();
        private static readonly object EVENT_VALUECHANGED = new object();

        private int minimum = 0; 
        private int maximum = 100;
        private int smallChange = 1; 
        private int largeChange = 10; 
        private int value = 0;
        private ScrollOrientation scrollOrientation; 
        private int wheelDelta = 0;

        /// 
        ///  
        ///    
        ///       Initializes a new instance of the  
        ///       class. 
        ///
        ///     
        /// 
        public ScrollBar()
        : base() {
            SetStyle(ControlStyles.UserPaint, false); 
            SetStyle(ControlStyles.StandardClick, false);
            SetStyle(ControlStyles.UseTextForAccessibility, false); 
 
            TabStop = false;
 
            if ((this.CreateParams.Style & NativeMethods.SBS_VERT) != 0)
            {
                scrollOrientation = ScrollOrientation.VerticalScroll;
            } 
            else
            { 
                scrollOrientation = ScrollOrientation.HorizontalScroll; 
            }
        } 

        /// 
        ///     Hide AutoSize: it doesn't make sense for this control
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public override bool AutoSize 
        {
            get 
            {
                return base.AutoSize;
            }
            set 
            {
                base.AutoSize = value; 
            } 
        }
 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler AutoSizeChanged {
            add { 
                base.AutoSizeChanged += value;
            } 
            remove { 
                base.AutoSizeChanged -= value;
            } 
        }

        /// 
        ///  
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public override Color BackColor {
            get { 
                return base.BackColor;
            }
            set {
                base.BackColor = value; 
            }
        } 
 
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler BackColorChanged {
            add {
                base.BackColorChanged += value; 
            }
            remove { 
                base.BackColorChanged -= value; 
            }
        } 

        /// 
        /// 
        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public override Image BackgroundImage { 
            get {
                return base.BackgroundImage; 
            }
            set {
                base.BackgroundImage = value;
            } 
        }
 
        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        new public event EventHandler BackgroundImageChanged {
            add {
                base.BackgroundImageChanged += value;
            } 
            remove {
                base.BackgroundImageChanged -= value; 
            } 
        }
 
        /// 
        /// 
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override ImageLayout BackgroundImageLayout { 
            get { 
                return base.BackgroundImageLayout;
            } 
            set {
                base.BackgroundImageLayout = value;
            }
        } 

        ///  
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler BackgroundImageLayoutChanged { 
            add {
                base.BackgroundImageLayoutChanged += value;
            }
            remove { 
                base.BackgroundImageLayoutChanged -= value;
            } 
        } 

        ///  
        /// 
        ///     Retrieves the parameters needed to create the handle.  Inheriting classes
        ///     can override this to provide extra functionality.  They should not,
        ///     however, forget to call base.getCreateParams() first to get the struct 
        ///     filled up with the basic info.
        ///  
        ///  
        protected override CreateParams CreateParams {
            [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
            get {
                CreateParams cp = base.CreateParams;
                cp.ClassName = "SCROLLBAR";
                cp.Style &= (~NativeMethods.WS_BORDER); 
                return cp;
            } 
        } 

        ///  
        protected override ImeMode DefaultImeMode {
            get {
                return ImeMode.Disable;
            } 
        }
 
        protected override Padding DefaultMargin { 
            get {
                return Padding.Empty; 
            }
        }

        ///  
        /// 
        ///  
        ///     
        ///       Gets or sets the foreground color of the scroll bar control.
        ///     
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override Color ForeColor {
            get { 
                return base.ForeColor;
            } 
            set { 
                base.ForeColor = value;
            } 
        }

        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler ForeColorChanged { 
            add { 
                base.ForeColorChanged += value;
            } 
            remove {
                base.ForeColorChanged -= value;
            }
        } 

        ///  
        ///  
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override Font Font {
            get {
                return base.Font; 
            }
            set { 
                base.Font = value; 
            }
        } 

        /// 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        new public event EventHandler FontChanged {
            add { 
                base.FontChanged += value; 
            }
            remove { 
                base.FontChanged -= value;
            }
        }
 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        new public ImeMode ImeMode { 
            get {
                return base.ImeMode; 
            }
            set {
                base.ImeMode = value;
            } 
        }
 
        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event EventHandler ImeModeChanged {
            add {
                base.ImeModeChanged += value;
            } 
            remove {
                base.ImeModeChanged -= value; 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Gets or sets a value to be added or subtracted to the  
        ///       property when the scroll box is moved a large distance.
        ///     
        ///  
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(10),
        SRDescription(SR.ScrollBarLargeChangeDescr),
        RefreshProperties(RefreshProperties.Repaint)
        ] 
        public int LargeChange {
            get { 
                // We preserve the actual large change value that has been set, but when we come to 
                // get the value of this property, make sure it's within the maximum allowable value.
                // This way we ensure that we don't depend on the order of property sets when 
                // code is generated at design-time.
                //
                return Math.Min(largeChange, maximum - minimum + 1);
            } 
            set {
                if (largeChange != value) { 
 
                    if (value < 0) {
                        throw new ArgumentOutOfRangeException("LargeChange", SR.GetString(SR.InvalidLowBoundArgumentEx, "LargeChange", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); 
                    }

                    largeChange = value;
                    UpdateScrollInfo(); 
                }
            } 
        } 

        ///  
        /// 
        ///    
        ///       Gets or sets the upper limit of values of the scrollable range.
        ///     
        /// 
        [ 
        SRCategory(SR.CatBehavior), 
        DefaultValue(100),
        SRDescription(SR.ScrollBarMaximumDescr), 
        RefreshProperties(RefreshProperties.Repaint)
        ]
        public int Maximum {
            get { 
                return maximum;
            } 
            set { 
                if (maximum != value) {
                    if (minimum > value) 
                        minimum = value;
                    // bring this.value in line.
                    if (value < this.value)
                        Value = value; 
                    maximum = value;
                    UpdateScrollInfo(); 
                } 
            }
        } 

        /// 
        /// 
        ///     
        ///       Gets or sets the lower limit of values of the scrollable range.
        ///     
        ///  
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(0),
        SRDescription(SR.ScrollBarMinimumDescr),
        RefreshProperties(RefreshProperties.Repaint)
        ] 
        public int Minimum {
            get { 
                return minimum; 
            }
            set { 
                if (minimum != value) {
                    if (maximum < value)
                        maximum = value;
                    // bring this.value in line. 
                    if (value > this.value)
                        this.value = value; 
                    minimum = value; 
                    UpdateScrollInfo();
                } 
            }
        }

        ///  
        /// 
        ///     
        ///       Gets or sets the value to be added or subtracted to the 
        ///    
        ///    property when the scroll box is 
        ///    moved a small distance.
        /// 
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(1), 
        SRDescription(SR.ScrollBarSmallChangeDescr) 
        ]
        public int SmallChange { 
            get {
                // We can't have SmallChange > LargeChange, but we shouldn't manipulate
                // the set values for these properties, so we just return the smaller
                // value here. 
                //
                return Math.Min(smallChange, LargeChange); 
            } 
            set {
                if (smallChange != value) { 

                    if (value < 0) {
                        throw new ArgumentOutOfRangeException("SmallChange", SR.GetString(SR.InvalidLowBoundArgumentEx, "SmallChange", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture)));
                    } 

                    smallChange = value; 
                    UpdateScrollInfo(); 
                }
            } 
        }

        /// 
        ///  
        /// 
        ///  
        [DefaultValue(false)] 
        new public bool TabStop {
            get { 
                return base.TabStop;
            }
            set {
                base.TabStop = value; 
            }
        } 
 
        /// 
        ///  
        /// 
        /// 
        [
        Browsable(false), EditorBrowsable(EditorBrowsableState.Never), 
        Bindable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) 
        ] 
        public override string Text {
            get { 
                return base.Text;
            }
            set {
                base.Text = value; 
            }
        } 
 
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler TextChanged {
            add {
                base.TextChanged += value; 
            }
            remove { 
                base.TextChanged -= value; 
            }
        } 

        /// 
        /// 
        ///     
        ///       Gets or sets a numeric value that represents the current
        ///       position of the scroll box 
        ///       on 
        ///       the scroll bar control.
        ///     
        /// 
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(0), 
        Bindable(true),
        SRDescription(SR.ScrollBarValueDescr) 
        ] 
        public int Value {
            get { 
                return value;
            }
            set {
                if (this.value != value) { 
                    if (value < minimum || value > maximum) {
                        throw new ArgumentOutOfRangeException("Value", SR.GetString(SR.InvalidBoundArgument, "Value", (value).ToString(CultureInfo.CurrentCulture), "'minimum'", "'maximum'")); 
                    } 
                    this.value = value;
                    UpdateScrollInfo(); 
                    OnValueChanged(EventArgs.Empty);
                }
            }
        } 

        ///  
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler Click { 
            add {
                base.Click += value;
            }
            remove { 
                base.Click -= value;
            } 
        } 

        ///  
        /// 
        ///     ScrollBar Onpaint.
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event PaintEventHandler Paint { 
            add { 
                base.Paint += value;
            } 
            remove {
                base.Paint -= value;
            }
        } 

        ///  
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler DoubleClick { 
            add {
                base.DoubleClick += value;
            }
            remove { 
                base.DoubleClick -= value;
            } 
        } 

        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseClick {
            add { 
                base.MouseClick += value;
            } 
            remove { 
                base.MouseClick -= value;
            } 
        }


        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event MouseEventHandler MouseDoubleClick { 
            add {
                base.MouseDoubleClick += value; 
            }
            remove {
                base.MouseDoubleClick -= value;
            } 
        }
 
        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event MouseEventHandler MouseDown {
            add {
                base.MouseDown += value;
            } 
            remove {
                base.MouseDown -= value; 
            } 
        }
 
        /// 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseUp { 
            add {
                base.MouseUp += value; 
            } 
            remove {
                base.MouseUp -= value; 
            }
        }

        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event MouseEventHandler MouseMove { 
            add {
                base.MouseMove += value; 
            }
            remove {
                base.MouseMove -= value;
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Occurs when the scroll box has
        ///       been
        ///       moved by either a mouse or keyboard action.
        ///     
        /// 
        [SRCategory(SR.CatAction), SRDescription(SR.ScrollBarOnScrollDescr)] 
        public event ScrollEventHandler Scroll { 
            add {
                Events.AddHandler(EVENT_SCROLL, value); 
            }
            remove {
                Events.RemoveHandler(EVENT_SCROLL, value);
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Occurs when the  property has changed, either by a
        ///     event or programatically.
        ///    
        ///  
        [SRCategory(SR.CatAction), SRDescription(SR.valueChangedEventDescr)]
        public event EventHandler ValueChanged { 
            add { 
                Events.AddHandler(EVENT_VALUECHANGED, value);
            } 
            remove {
                Events.RemoveHandler(EVENT_VALUECHANGED, value);
            }
        } 

 
        ///  
        ///     This is a helper method that is called by ScaleControl to retrieve the bounds
        ///     that the control should be scaled by.  You may override this method if you 
        ///     wish to reuse ScaleControl's scaling logic but you need to supply your own
        ///     bounds.  The default implementation returns scaled bounds that take into
        ///     account the BoundsSpecified, whether the control is top level, and whether
        ///     the control is fixed width or auto size, and any adornments the control may have. 
        /// 
        protected override Rectangle GetScaledBounds(Rectangle bounds, SizeF factor, BoundsSpecified specified) { 
 
            // Adjust Specified for vertical or horizontal scaling
            if (scrollOrientation == ScrollOrientation.VerticalScroll) { 
                specified &= ~BoundsSpecified.Width;
            }
            else {
                specified &= ~BoundsSpecified.Height; 
            }
 
            return base.GetScaledBounds(bounds, factor, specified); 
        }
 
        internal override IntPtr InitializeDCForWmCtlColor (IntPtr dc, int msg)
        {
            return IntPtr.Zero;
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected override void OnEnabledChanged(EventArgs e) {
            if (Enabled) {
                UpdateScrollInfo();
            } 
            base.OnEnabledChanged(e);
        } 
 
        /// 
        ///  
        ///     Creates the handle.  overridden to help set up scrollbar information.
        /// 
        /// 
        protected override void OnHandleCreated(EventArgs e) { 
            base.OnHandleCreated(e);
            UpdateScrollInfo(); 
        } 

        ///  
        /// 
        ///    
        ///       Raises the  event.
        ///     
        /// 
        protected virtual void OnScroll(ScrollEventArgs se) { 
            ScrollEventHandler handler = (ScrollEventHandler)Events[EVENT_SCROLL]; 
            if (handler != null) handler(this,se);
        } 

        /// 
        /// 
        ///     Converts mouse wheel movements into scrolling, when scrollbar has the focus. 
        ///     Typically one wheel step will cause one small scroll increment, in either
        ///     direction. A single wheel message could represent either one wheel step, multiple 
        ///     wheel steps (fast wheeling), or even a fraction of a step (smooth-wheeled mice). 
        ///     So we accumulate the total wheel delta, and consume it in whole numbers of steps.
        ///  
        protected override void OnMouseWheel(MouseEventArgs e) {
            wheelDelta += e.Delta;

            bool scrolled = false; 

            while (Math.Abs(wheelDelta) >= NativeMethods.WHEEL_DELTA) { 
                if (wheelDelta > 0) { 
                    wheelDelta -= NativeMethods.WHEEL_DELTA;
                    DoScroll(ScrollEventType.SmallDecrement); 
                    scrolled = true;
                }
                else {
                    wheelDelta += NativeMethods.WHEEL_DELTA; 
                    DoScroll(ScrollEventType.SmallIncrement);
                    scrolled = true; 
                } 
            }
 
            if (scrolled) {
                DoScroll(ScrollEventType.EndScroll);
            }
 
            if (e is HandledMouseEventArgs) {
                ((HandledMouseEventArgs) e).Handled = true; 
            } 

            // The base implementation should be called before the implementation above, 
            // but changing the order in Whidbey would be too much of a breaking change
            // for this particular class.
            base.OnMouseWheel(e);
        } 

        ///  
        ///  
        ///    
        ///       Raises the  event. 
        ///    
        /// 
        protected virtual void OnValueChanged(EventArgs e) {
            EventHandler handler = (EventHandler)Events[EVENT_VALUECHANGED]; 
            if (handler != null) handler(this,e);
        } 
 
        // Reflects the position of the scrollbar
        private int ReflectPosition(int position) { 
            if (this is HScrollBar) {
                return minimum + (maximum - LargeChange + 1) - position;
            }
            return position; 
        }
 
        ///  
        /// 
        ///  
        /// 
        public override string ToString() {
            string s = base.ToString();
            return s + ", Minimum: " + Minimum.ToString(CultureInfo.CurrentCulture) + ", Maximum: " + Maximum.ToString(CultureInfo.CurrentCulture) + ", Value: " + Value.ToString(CultureInfo.CurrentCulture); 
        }
 
        ///  
        /// 
        ///     Internal helper method 
        /// 
        /// 
        protected void UpdateScrollInfo() {
            if (IsHandleCreated && Enabled) { 

                NativeMethods.SCROLLINFO si = new NativeMethods.SCROLLINFO(); 
                si.cbSize = Marshal.SizeOf(typeof(NativeMethods.SCROLLINFO)); 
                si.fMask = NativeMethods.SIF_ALL;
                si.nMin = minimum; 
                si.nMax = maximum;
                si.nPage = LargeChange;

                if (RightToLeft == RightToLeft.Yes) { 
                    // Reflect the scrollbar position horizontally on an Rtl system
                    si.nPos = ReflectPosition(value); 
                } 
                else {
                    si.nPos = value; 
                }

                si.nTrackPos = 0;
 
                UnsafeNativeMethods.SetScrollInfo(new HandleRef(this, Handle), NativeMethods.SB_CTL, si, true);
            } 
        } 

        ///  
        /// 
        /// 
        /// 
        private void WmReflectScroll(ref Message m) { 
            ScrollEventType type = (ScrollEventType)NativeMethods.Util.LOWORD(m.WParam);
            DoScroll(type); 
        } 

        ///  
        /// 
        /// 
        /// 
        private void DoScroll(ScrollEventType type) { 

            // For Rtl systems we need to swap increment and decrement 
            // 
            if (RightToLeft == RightToLeft.Yes) {
                switch (type) { 
                    case ScrollEventType.First:
                        type = ScrollEventType.Last;
                        break;
 
                    case ScrollEventType.Last:
                        type = ScrollEventType.First; 
                        break; 

                    case ScrollEventType.SmallDecrement: 
                        type = ScrollEventType.SmallIncrement;
                        break;

                    case ScrollEventType.SmallIncrement: 
                        type = ScrollEventType.SmallDecrement;
                        break; 
 
                    case ScrollEventType.LargeDecrement:
                        type = ScrollEventType.LargeIncrement; 
                        break;

                    case ScrollEventType.LargeIncrement:
                        type = ScrollEventType.LargeDecrement; 
                        break;
                } 
            } 

            int newValue = value; 
            int oldValue = value;

            // The ScrollEventArgs constants are defined in terms of the windows
            // messages..  this eliminates confusion between the VSCROLL and 
            // HSCROLL constants, which are identical.
            // 
            switch (type) { 
                case ScrollEventType.First:
                    newValue = minimum; 
                    break;

                case ScrollEventType.Last:
                    newValue = maximum - LargeChange + 1; // si.nMax - si.nPage + 1; 
                    break;
 
                case ScrollEventType.SmallDecrement: 
                    newValue = Math.Max(value - SmallChange, minimum);
                    break; 

                case ScrollEventType.SmallIncrement:
                    newValue = Math.Min(value + SmallChange, maximum - LargeChange + 1); // max - lChange + 1);
                    break; 

                case ScrollEventType.LargeDecrement: 
                    newValue = Math.Max(value - LargeChange, minimum); 
                    break;
 
                case ScrollEventType.LargeIncrement:
                    newValue = Math.Min(value + LargeChange, maximum - LargeChange + 1); // si.nPos + si.nPage,si.nMax - si.nPage + 1);
                    break;
 
                case ScrollEventType.ThumbPosition:
                case ScrollEventType.ThumbTrack: 
                    NativeMethods.SCROLLINFO si = new NativeMethods.SCROLLINFO(); 
                    si.fMask = NativeMethods.SIF_TRACKPOS;
                    SafeNativeMethods.GetScrollInfo(new HandleRef(this, Handle), NativeMethods.SB_CTL, si); 

                    if (RightToLeft == RightToLeft.Yes) {
                        newValue = ReflectPosition(si.nTrackPos);
                    } 
                    else {
                        newValue = si.nTrackPos; 
                    } 

                    break; 
            }

            ScrollEventArgs se = new ScrollEventArgs(type, oldValue, newValue, this.scrollOrientation);
            OnScroll(se); 
            Value = se.NewValue;
        } 
 
        /// 
        ///  
        /// 
        /// 
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        protected override void WndProc(ref Message m) { 
            switch (m.Msg) {
                case NativeMethods.WM_REFLECT + NativeMethods.WM_HSCROLL: 
                case NativeMethods.WM_REFLECT + NativeMethods.WM_VSCROLL: 
                    WmReflectScroll(ref m);
                    break; 
                case NativeMethods.WM_ERASEBKGND:
                    break;

                case NativeMethods.WM_SIZE: 
                    //VS7#13707 : [....], 4/26/1999 - Fixes the scrollbar focus rect
                    if (UnsafeNativeMethods.GetFocus() == this.Handle) { 
                        DefWndProc(ref m); 
                        SendMessage(NativeMethods.WM_KILLFOCUS, 0, 0);
                        SendMessage(NativeMethods.WM_SETFOCUS, 0, 0); 
                    }
                    break;

                default: 
                    base.WndProc(ref m);
                    break; 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Windows.Forms { 
    using System.Runtime.Serialization.Formatters; 
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting; 
    using System.Diagnostics;

    using System;
    using System.Security.Permissions; 

    using System.Windows.Forms; 
    using System.ComponentModel; 
    using System.Drawing;
    using Microsoft.Win32; 
    using System.Globalization;


    ///  
    /// 
    ///     
    ///       Implements the basic functionality of a scroll bar control. 
    ///    
    ///  
    [
    ComVisible(true),
    ClassInterface(ClassInterfaceType.AutoDispatch),
    DefaultProperty("Value"), 
    DefaultEvent("Scroll"),
    System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors") // Shipped in Everett 
    ] 
    public abstract class ScrollBar : Control {
 
        private static readonly object EVENT_SCROLL = new object();
        private static readonly object EVENT_VALUECHANGED = new object();

        private int minimum = 0; 
        private int maximum = 100;
        private int smallChange = 1; 
        private int largeChange = 10; 
        private int value = 0;
        private ScrollOrientation scrollOrientation; 
        private int wheelDelta = 0;

        /// 
        ///  
        ///    
        ///       Initializes a new instance of the  
        ///       class. 
        ///
        ///     
        /// 
        public ScrollBar()
        : base() {
            SetStyle(ControlStyles.UserPaint, false); 
            SetStyle(ControlStyles.StandardClick, false);
            SetStyle(ControlStyles.UseTextForAccessibility, false); 
 
            TabStop = false;
 
            if ((this.CreateParams.Style & NativeMethods.SBS_VERT) != 0)
            {
                scrollOrientation = ScrollOrientation.VerticalScroll;
            } 
            else
            { 
                scrollOrientation = ScrollOrientation.HorizontalScroll; 
            }
        } 

        /// 
        ///     Hide AutoSize: it doesn't make sense for this control
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public override bool AutoSize 
        {
            get 
            {
                return base.AutoSize;
            }
            set 
            {
                base.AutoSize = value; 
            } 
        }
 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler AutoSizeChanged {
            add { 
                base.AutoSizeChanged += value;
            } 
            remove { 
                base.AutoSizeChanged -= value;
            } 
        }

        /// 
        ///  
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public override Color BackColor {
            get { 
                return base.BackColor;
            }
            set {
                base.BackColor = value; 
            }
        } 
 
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler BackColorChanged {
            add {
                base.BackColorChanged += value; 
            }
            remove { 
                base.BackColorChanged -= value; 
            }
        } 

        /// 
        /// 
        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public override Image BackgroundImage { 
            get {
                return base.BackgroundImage; 
            }
            set {
                base.BackgroundImage = value;
            } 
        }
 
        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        new public event EventHandler BackgroundImageChanged {
            add {
                base.BackgroundImageChanged += value;
            } 
            remove {
                base.BackgroundImageChanged -= value; 
            } 
        }
 
        /// 
        /// 
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override ImageLayout BackgroundImageLayout { 
            get { 
                return base.BackgroundImageLayout;
            } 
            set {
                base.BackgroundImageLayout = value;
            }
        } 

        ///  
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler BackgroundImageLayoutChanged { 
            add {
                base.BackgroundImageLayoutChanged += value;
            }
            remove { 
                base.BackgroundImageLayoutChanged -= value;
            } 
        } 

        ///  
        /// 
        ///     Retrieves the parameters needed to create the handle.  Inheriting classes
        ///     can override this to provide extra functionality.  They should not,
        ///     however, forget to call base.getCreateParams() first to get the struct 
        ///     filled up with the basic info.
        ///  
        ///  
        protected override CreateParams CreateParams {
            [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
            get {
                CreateParams cp = base.CreateParams;
                cp.ClassName = "SCROLLBAR";
                cp.Style &= (~NativeMethods.WS_BORDER); 
                return cp;
            } 
        } 

        ///  
        protected override ImeMode DefaultImeMode {
            get {
                return ImeMode.Disable;
            } 
        }
 
        protected override Padding DefaultMargin { 
            get {
                return Padding.Empty; 
            }
        }

        ///  
        /// 
        ///  
        ///     
        ///       Gets or sets the foreground color of the scroll bar control.
        ///     
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override Color ForeColor {
            get { 
                return base.ForeColor;
            } 
            set { 
                base.ForeColor = value;
            } 
        }

        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler ForeColorChanged { 
            add { 
                base.ForeColorChanged += value;
            } 
            remove {
                base.ForeColorChanged -= value;
            }
        } 

        ///  
        ///  
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override Font Font {
            get {
                return base.Font; 
            }
            set { 
                base.Font = value; 
            }
        } 

        /// 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        new public event EventHandler FontChanged {
            add { 
                base.FontChanged += value; 
            }
            remove { 
                base.FontChanged -= value;
            }
        }
 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        new public ImeMode ImeMode { 
            get {
                return base.ImeMode; 
            }
            set {
                base.ImeMode = value;
            } 
        }
 
        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event EventHandler ImeModeChanged {
            add {
                base.ImeModeChanged += value;
            } 
            remove {
                base.ImeModeChanged -= value; 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Gets or sets a value to be added or subtracted to the  
        ///       property when the scroll box is moved a large distance.
        ///     
        ///  
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(10),
        SRDescription(SR.ScrollBarLargeChangeDescr),
        RefreshProperties(RefreshProperties.Repaint)
        ] 
        public int LargeChange {
            get { 
                // We preserve the actual large change value that has been set, but when we come to 
                // get the value of this property, make sure it's within the maximum allowable value.
                // This way we ensure that we don't depend on the order of property sets when 
                // code is generated at design-time.
                //
                return Math.Min(largeChange, maximum - minimum + 1);
            } 
            set {
                if (largeChange != value) { 
 
                    if (value < 0) {
                        throw new ArgumentOutOfRangeException("LargeChange", SR.GetString(SR.InvalidLowBoundArgumentEx, "LargeChange", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture))); 
                    }

                    largeChange = value;
                    UpdateScrollInfo(); 
                }
            } 
        } 

        ///  
        /// 
        ///    
        ///       Gets or sets the upper limit of values of the scrollable range.
        ///     
        /// 
        [ 
        SRCategory(SR.CatBehavior), 
        DefaultValue(100),
        SRDescription(SR.ScrollBarMaximumDescr), 
        RefreshProperties(RefreshProperties.Repaint)
        ]
        public int Maximum {
            get { 
                return maximum;
            } 
            set { 
                if (maximum != value) {
                    if (minimum > value) 
                        minimum = value;
                    // bring this.value in line.
                    if (value < this.value)
                        Value = value; 
                    maximum = value;
                    UpdateScrollInfo(); 
                } 
            }
        } 

        /// 
        /// 
        ///     
        ///       Gets or sets the lower limit of values of the scrollable range.
        ///     
        ///  
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(0),
        SRDescription(SR.ScrollBarMinimumDescr),
        RefreshProperties(RefreshProperties.Repaint)
        ] 
        public int Minimum {
            get { 
                return minimum; 
            }
            set { 
                if (minimum != value) {
                    if (maximum < value)
                        maximum = value;
                    // bring this.value in line. 
                    if (value > this.value)
                        this.value = value; 
                    minimum = value; 
                    UpdateScrollInfo();
                } 
            }
        }

        ///  
        /// 
        ///     
        ///       Gets or sets the value to be added or subtracted to the 
        ///    
        ///    property when the scroll box is 
        ///    moved a small distance.
        /// 
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(1), 
        SRDescription(SR.ScrollBarSmallChangeDescr) 
        ]
        public int SmallChange { 
            get {
                // We can't have SmallChange > LargeChange, but we shouldn't manipulate
                // the set values for these properties, so we just return the smaller
                // value here. 
                //
                return Math.Min(smallChange, LargeChange); 
            } 
            set {
                if (smallChange != value) { 

                    if (value < 0) {
                        throw new ArgumentOutOfRangeException("SmallChange", SR.GetString(SR.InvalidLowBoundArgumentEx, "SmallChange", (value).ToString(CultureInfo.CurrentCulture), (0).ToString(CultureInfo.CurrentCulture)));
                    } 

                    smallChange = value; 
                    UpdateScrollInfo(); 
                }
            } 
        }

        /// 
        ///  
        /// 
        ///  
        [DefaultValue(false)] 
        new public bool TabStop {
            get { 
                return base.TabStop;
            }
            set {
                base.TabStop = value; 
            }
        } 
 
        /// 
        ///  
        /// 
        /// 
        [
        Browsable(false), EditorBrowsable(EditorBrowsableState.Never), 
        Bindable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) 
        ] 
        public override string Text {
            get { 
                return base.Text;
            }
            set {
                base.Text = value; 
            }
        } 
 
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        new public event EventHandler TextChanged {
            add {
                base.TextChanged += value; 
            }
            remove { 
                base.TextChanged -= value; 
            }
        } 

        /// 
        /// 
        ///     
        ///       Gets or sets a numeric value that represents the current
        ///       position of the scroll box 
        ///       on 
        ///       the scroll bar control.
        ///     
        /// 
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(0), 
        Bindable(true),
        SRDescription(SR.ScrollBarValueDescr) 
        ] 
        public int Value {
            get { 
                return value;
            }
            set {
                if (this.value != value) { 
                    if (value < minimum || value > maximum) {
                        throw new ArgumentOutOfRangeException("Value", SR.GetString(SR.InvalidBoundArgument, "Value", (value).ToString(CultureInfo.CurrentCulture), "'minimum'", "'maximum'")); 
                    } 
                    this.value = value;
                    UpdateScrollInfo(); 
                    OnValueChanged(EventArgs.Empty);
                }
            }
        } 

        ///  
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler Click { 
            add {
                base.Click += value;
            }
            remove { 
                base.Click -= value;
            } 
        } 

        ///  
        /// 
        ///     ScrollBar Onpaint.
        /// 
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event PaintEventHandler Paint { 
            add { 
                base.Paint += value;
            } 
            remove {
                base.Paint -= value;
            }
        } 

        ///  
        ///  
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler DoubleClick { 
            add {
                base.DoubleClick += value;
            }
            remove { 
                base.DoubleClick -= value;
            } 
        } 

        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseClick {
            add { 
                base.MouseClick += value;
            } 
            remove { 
                base.MouseClick -= value;
            } 
        }


        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event MouseEventHandler MouseDoubleClick { 
            add {
                base.MouseDoubleClick += value; 
            }
            remove {
                base.MouseDoubleClick -= value;
            } 
        }
 
        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event MouseEventHandler MouseDown {
            add {
                base.MouseDown += value;
            } 
            remove {
                base.MouseDown -= value; 
            } 
        }
 
        /// 
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseUp { 
            add {
                base.MouseUp += value; 
            } 
            remove {
                base.MouseUp -= value; 
            }
        }

        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event MouseEventHandler MouseMove { 
            add {
                base.MouseMove += value; 
            }
            remove {
                base.MouseMove -= value;
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Occurs when the scroll box has
        ///       been
        ///       moved by either a mouse or keyboard action.
        ///     
        /// 
        [SRCategory(SR.CatAction), SRDescription(SR.ScrollBarOnScrollDescr)] 
        public event ScrollEventHandler Scroll { 
            add {
                Events.AddHandler(EVENT_SCROLL, value); 
            }
            remove {
                Events.RemoveHandler(EVENT_SCROLL, value);
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Occurs when the  property has changed, either by a
        ///     event or programatically.
        ///    
        ///  
        [SRCategory(SR.CatAction), SRDescription(SR.valueChangedEventDescr)]
        public event EventHandler ValueChanged { 
            add { 
                Events.AddHandler(EVENT_VALUECHANGED, value);
            } 
            remove {
                Events.RemoveHandler(EVENT_VALUECHANGED, value);
            }
        } 

 
        ///  
        ///     This is a helper method that is called by ScaleControl to retrieve the bounds
        ///     that the control should be scaled by.  You may override this method if you 
        ///     wish to reuse ScaleControl's scaling logic but you need to supply your own
        ///     bounds.  The default implementation returns scaled bounds that take into
        ///     account the BoundsSpecified, whether the control is top level, and whether
        ///     the control is fixed width or auto size, and any adornments the control may have. 
        /// 
        protected override Rectangle GetScaledBounds(Rectangle bounds, SizeF factor, BoundsSpecified specified) { 
 
            // Adjust Specified for vertical or horizontal scaling
            if (scrollOrientation == ScrollOrientation.VerticalScroll) { 
                specified &= ~BoundsSpecified.Width;
            }
            else {
                specified &= ~BoundsSpecified.Height; 
            }
 
            return base.GetScaledBounds(bounds, factor, specified); 
        }
 
        internal override IntPtr InitializeDCForWmCtlColor (IntPtr dc, int msg)
        {
            return IntPtr.Zero;
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected override void OnEnabledChanged(EventArgs e) {
            if (Enabled) {
                UpdateScrollInfo();
            } 
            base.OnEnabledChanged(e);
        } 
 
        /// 
        ///  
        ///     Creates the handle.  overridden to help set up scrollbar information.
        /// 
        /// 
        protected override void OnHandleCreated(EventArgs e) { 
            base.OnHandleCreated(e);
            UpdateScrollInfo(); 
        } 

        ///  
        /// 
        ///    
        ///       Raises the  event.
        ///     
        /// 
        protected virtual void OnScroll(ScrollEventArgs se) { 
            ScrollEventHandler handler = (ScrollEventHandler)Events[EVENT_SCROLL]; 
            if (handler != null) handler(this,se);
        } 

        /// 
        /// 
        ///     Converts mouse wheel movements into scrolling, when scrollbar has the focus. 
        ///     Typically one wheel step will cause one small scroll increment, in either
        ///     direction. A single wheel message could represent either one wheel step, multiple 
        ///     wheel steps (fast wheeling), or even a fraction of a step (smooth-wheeled mice). 
        ///     So we accumulate the total wheel delta, and consume it in whole numbers of steps.
        ///  
        protected override void OnMouseWheel(MouseEventArgs e) {
            wheelDelta += e.Delta;

            bool scrolled = false; 

            while (Math.Abs(wheelDelta) >= NativeMethods.WHEEL_DELTA) { 
                if (wheelDelta > 0) { 
                    wheelDelta -= NativeMethods.WHEEL_DELTA;
                    DoScroll(ScrollEventType.SmallDecrement); 
                    scrolled = true;
                }
                else {
                    wheelDelta += NativeMethods.WHEEL_DELTA; 
                    DoScroll(ScrollEventType.SmallIncrement);
                    scrolled = true; 
                } 
            }
 
            if (scrolled) {
                DoScroll(ScrollEventType.EndScroll);
            }
 
            if (e is HandledMouseEventArgs) {
                ((HandledMouseEventArgs) e).Handled = true; 
            } 

            // The base implementation should be called before the implementation above, 
            // but changing the order in Whidbey would be too much of a breaking change
            // for this particular class.
            base.OnMouseWheel(e);
        } 

        ///  
        ///  
        ///    
        ///       Raises the  event. 
        ///    
        /// 
        protected virtual void OnValueChanged(EventArgs e) {
            EventHandler handler = (EventHandler)Events[EVENT_VALUECHANGED]; 
            if (handler != null) handler(this,e);
        } 
 
        // Reflects the position of the scrollbar
        private int ReflectPosition(int position) { 
            if (this is HScrollBar) {
                return minimum + (maximum - LargeChange + 1) - position;
            }
            return position; 
        }
 
        ///  
        /// 
        ///  
        /// 
        public override string ToString() {
            string s = base.ToString();
            return s + ", Minimum: " + Minimum.ToString(CultureInfo.CurrentCulture) + ", Maximum: " + Maximum.ToString(CultureInfo.CurrentCulture) + ", Value: " + Value.ToString(CultureInfo.CurrentCulture); 
        }
 
        ///  
        /// 
        ///     Internal helper method 
        /// 
        /// 
        protected void UpdateScrollInfo() {
            if (IsHandleCreated && Enabled) { 

                NativeMethods.SCROLLINFO si = new NativeMethods.SCROLLINFO(); 
                si.cbSize = Marshal.SizeOf(typeof(NativeMethods.SCROLLINFO)); 
                si.fMask = NativeMethods.SIF_ALL;
                si.nMin = minimum; 
                si.nMax = maximum;
                si.nPage = LargeChange;

                if (RightToLeft == RightToLeft.Yes) { 
                    // Reflect the scrollbar position horizontally on an Rtl system
                    si.nPos = ReflectPosition(value); 
                } 
                else {
                    si.nPos = value; 
                }

                si.nTrackPos = 0;
 
                UnsafeNativeMethods.SetScrollInfo(new HandleRef(this, Handle), NativeMethods.SB_CTL, si, true);
            } 
        } 

        ///  
        /// 
        /// 
        /// 
        private void WmReflectScroll(ref Message m) { 
            ScrollEventType type = (ScrollEventType)NativeMethods.Util.LOWORD(m.WParam);
            DoScroll(type); 
        } 

        ///  
        /// 
        /// 
        /// 
        private void DoScroll(ScrollEventType type) { 

            // For Rtl systems we need to swap increment and decrement 
            // 
            if (RightToLeft == RightToLeft.Yes) {
                switch (type) { 
                    case ScrollEventType.First:
                        type = ScrollEventType.Last;
                        break;
 
                    case ScrollEventType.Last:
                        type = ScrollEventType.First; 
                        break; 

                    case ScrollEventType.SmallDecrement: 
                        type = ScrollEventType.SmallIncrement;
                        break;

                    case ScrollEventType.SmallIncrement: 
                        type = ScrollEventType.SmallDecrement;
                        break; 
 
                    case ScrollEventType.LargeDecrement:
                        type = ScrollEventType.LargeIncrement; 
                        break;

                    case ScrollEventType.LargeIncrement:
                        type = ScrollEventType.LargeDecrement; 
                        break;
                } 
            } 

            int newValue = value; 
            int oldValue = value;

            // The ScrollEventArgs constants are defined in terms of the windows
            // messages..  this eliminates confusion between the VSCROLL and 
            // HSCROLL constants, which are identical.
            // 
            switch (type) { 
                case ScrollEventType.First:
                    newValue = minimum; 
                    break;

                case ScrollEventType.Last:
                    newValue = maximum - LargeChange + 1; // si.nMax - si.nPage + 1; 
                    break;
 
                case ScrollEventType.SmallDecrement: 
                    newValue = Math.Max(value - SmallChange, minimum);
                    break; 

                case ScrollEventType.SmallIncrement:
                    newValue = Math.Min(value + SmallChange, maximum - LargeChange + 1); // max - lChange + 1);
                    break; 

                case ScrollEventType.LargeDecrement: 
                    newValue = Math.Max(value - LargeChange, minimum); 
                    break;
 
                case ScrollEventType.LargeIncrement:
                    newValue = Math.Min(value + LargeChange, maximum - LargeChange + 1); // si.nPos + si.nPage,si.nMax - si.nPage + 1);
                    break;
 
                case ScrollEventType.ThumbPosition:
                case ScrollEventType.ThumbTrack: 
                    NativeMethods.SCROLLINFO si = new NativeMethods.SCROLLINFO(); 
                    si.fMask = NativeMethods.SIF_TRACKPOS;
                    SafeNativeMethods.GetScrollInfo(new HandleRef(this, Handle), NativeMethods.SB_CTL, si); 

                    if (RightToLeft == RightToLeft.Yes) {
                        newValue = ReflectPosition(si.nTrackPos);
                    } 
                    else {
                        newValue = si.nTrackPos; 
                    } 

                    break; 
            }

            ScrollEventArgs se = new ScrollEventArgs(type, oldValue, newValue, this.scrollOrientation);
            OnScroll(se); 
            Value = se.NewValue;
        } 
 
        /// 
        ///  
        /// 
        /// 
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        protected override void WndProc(ref Message m) { 
            switch (m.Msg) {
                case NativeMethods.WM_REFLECT + NativeMethods.WM_HSCROLL: 
                case NativeMethods.WM_REFLECT + NativeMethods.WM_VSCROLL: 
                    WmReflectScroll(ref m);
                    break; 
                case NativeMethods.WM_ERASEBKGND:
                    break;

                case NativeMethods.WM_SIZE: 
                    //VS7#13707 : [....], 4/26/1999 - Fixes the scrollbar focus rect
                    if (UnsafeNativeMethods.GetFocus() == this.Handle) { 
                        DefWndProc(ref m); 
                        SendMessage(NativeMethods.WM_KILLFOCUS, 0, 0);
                        SendMessage(NativeMethods.WM_SETFOCUS, 0, 0); 
                    }
                    break;

                default: 
                    base.WndProc(ref m);
                    break; 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK