| File: System\Windows\Forms\Scrolling\ScrollProperties.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms\System.Windows.Forms.csproj (System.Windows.Forms) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; namespace System.Windows.Forms; /// <summary> /// Basic Properties for Scrollbars. /// </summary> public abstract class ScrollProperties { internal int _minimum; internal int _maximum = 100; internal int _smallChange = 1; internal int _largeChange = 10; internal int _value; internal bool _maximumSetExternally; internal bool _smallChangeSetExternally; internal bool _largeChangeSetExternally; private readonly ScrollableControl? _parent; protected ScrollableControl? ParentControl => _parent; internal bool _visible; private bool _enabled = true; protected ScrollProperties(ScrollableControl? container) { _parent = container; } /// <summary> /// Gets or sets a bool value controlling whether the scrollbar is enabled. /// </summary> [SRCategory(nameof(SR.CatBehavior))] [DefaultValue(true)] [SRDescription(nameof(SR.ScrollBarEnableDescr))] public bool Enabled { get => _enabled; set { if (_parent is not null && _parent.AutoScroll) { return; } if (value != _enabled) { _enabled = value; if (_parent is not null) { PInvoke.EnableScrollBar( _parent, Orientation, value ? ENABLE_SCROLL_BAR_ARROWS.ESB_ENABLE_BOTH : ENABLE_SCROLL_BAR_ARROWS.ESB_DISABLE_BOTH); } } } } /// <summary> /// Gets or sets a value to be added or subtracted to the <see cref="LargeChange"/> /// property when the scroll box is moved a large distance. /// </summary> [SRCategory(nameof(SR.CatBehavior))] [DefaultValue(10)] [SRDescription(nameof(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) { ArgumentOutOfRangeException.ThrowIfNegative(value); _largeChange = value; _largeChangeSetExternally = true; UpdateScrollInfo(); } } } /// <summary> /// Gets or sets the upper limit of values of the scrollable range. /// </summary> [SRCategory(nameof(SR.CatBehavior))] [DefaultValue(100)] [SRDescription(nameof(SR.ScrollBarMaximumDescr))] [RefreshProperties(RefreshProperties.Repaint)] public int Maximum { get => _maximum; set { if (_parent is not null && _parent.AutoScroll) { return; } if (_maximum != value) { if (_minimum > value) { _minimum = value; } if (value < _value) { Value = value; } _maximum = value; _maximumSetExternally = true; UpdateScrollInfo(); } } } /// <summary> /// Gets or sets the lower limit of values of the scrollable range. /// </summary> [SRCategory(nameof(SR.CatBehavior))] [DefaultValue(0)] [SRDescription(nameof(SR.ScrollBarMinimumDescr))] [RefreshProperties(RefreshProperties.Repaint)] public int Minimum { get => _minimum; set { if (_parent is not null && _parent.AutoScroll) { return; } if (_minimum != value) { ArgumentOutOfRangeException.ThrowIfNegative(value); if (_maximum < value) { _maximum = value; } if (value > _value) { _value = value; } _minimum = value; UpdateScrollInfo(); } } } private protected abstract int GetPageSize(ScrollableControl parent); private protected abstract SCROLLBAR_CONSTANTS Orientation { get; } private protected abstract int GetHorizontalDisplayPosition(ScrollableControl parent); private protected abstract int GetVerticalDisplayPosition(ScrollableControl parent); /// <summary> /// Gets or sets the value to be added or subtracted to the <see cref="ScrollBar.Value"/> /// property when the scroll box is moved a small distance. /// </summary> [SRCategory(nameof(SR.CatBehavior))] [DefaultValue(1)] [SRDescription(nameof(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) { ArgumentOutOfRangeException.ThrowIfNegative(value); _smallChange = value; _smallChangeSetExternally = true; UpdateScrollInfo(); } } } /// <summary> /// Gets or sets a numeric value that represents the current position of the scroll box /// on the scroll bar control. /// </summary> [SRCategory(nameof(SR.CatBehavior))] [DefaultValue(0)] [Bindable(true)] [SRDescription(nameof(SR.ScrollBarValueDescr))] public int Value { get => _value; set { if (_value != value) { if (value < _minimum || value > _maximum) { throw new ArgumentOutOfRangeException(nameof(value), string.Format(SR.InvalidBoundArgument, nameof(Value), value, $"'{nameof(Minimum)}'", $"'{nameof(Maximum)}'")); } _value = value; UpdateScrollInfo(); UpdateDisplayPosition(); } } } /// <summary> /// Gets or sets a bool value controlling whether the scrollbar is showing. /// </summary> [SRCategory(nameof(SR.CatBehavior))] [DefaultValue(false)] [SRDescription(nameof(SR.ScrollBarVisibleDescr))] public bool Visible { get => _visible; set { if (_parent is not null && _parent.AutoScroll) { return; } if (value != _visible) { _visible = value; _parent?.UpdateStylesCore(); UpdateScrollInfo(); UpdateDisplayPosition(); } } } internal unsafe void UpdateScrollInfo() { if (_parent is not null && _parent.IsHandleCreated && _visible) { SCROLLINFO si = new() { cbSize = (uint)sizeof(SCROLLINFO), fMask = SCROLLINFO_MASK.SIF_ALL, nMin = _minimum, nMax = _maximum, nPage = _parent.AutoScroll ? (uint)GetPageSize(_parent) : (uint)LargeChange, nPos = _value, nTrackPos = 0 }; PInvoke.SetScrollInfo(_parent, Orientation, ref si, true); } } private void UpdateDisplayPosition() { if (_parent is null) { return; } int horizontal = GetHorizontalDisplayPosition(_parent); int vertical = GetVerticalDisplayPosition(_parent); _parent.SetDisplayFromScrollProps(horizontal, vertical); } }