Overview

BeepScrollBar provides a modern, fully customizable scrollbar control that can replace the standard Windows scrollbar with a more contemporary appearance. Supporting both horizontal and vertical orientations, it offers smooth dragging, hover effects, and comprehensive theming integration.

Built on the BeepControl foundation, BeepScrollBar features intelligent thumb sizing, proportional movement, keyboard navigation, mouse wheel support, and seamless integration with custom container controls. Perfect for modern interfaces requiring custom scrolling experiences.

Key Features

?? Dual Orientation

Supports both vertical and horizontal scrolling with automatic sizing

??? Smooth Interaction

Drag and drop thumb movement with immediate visual feedback

?? Keyboard Support

Arrow keys, Page Up/Down, and mouse wheel navigation

?? Customizable Colors

Track, thumb, hover, and active state color customization

?? Proportional Sizing

Intelligent thumb sizing based on content ratio and large change values

?? Theme Integration

Full theme support with specialized scrollbar color properties

Visual Preview

Vertical ScrollBar

Value: 30 Range: 0-100 Large Change: 10

Vertical BeepScrollBar with thumb positioned at 30% of range

Horizontal ScrollBar

Value: 45 Range: 0-200 Large Change: 20

Horizontal BeepScrollBar with proportional thumb sizing

Interactive States

Normal

Hover

Active

Different scrollbar states: normal, hover, and active (dragging)

Basic Usage

Vertical ScrollBar

// Create a vertical scrollbar
var verticalScrollBar = new BeepScrollBar
{
    ScrollOrientation = Orientation.Vertical,
    Location = new Point(200, 50),
    Size = new Size(15, 200),
    Minimum = 0,
    Maximum = 100,
    Value = 0,
    LargeChange = 10,
    SmallChange = 1
};

// Handle value changes
verticalScrollBar.ValueChanged += (sender, e) =>
{
    var scrollBar = sender as BeepScrollBar;
  //  Console.WriteLine($"ScrollBar value: {scrollBar.Value}");
    
    // Update content position based on scrollbar value
    UpdateContentPosition(scrollBar.Value);
};

// Handle scroll events (fired on any scroll action)
verticalScrollBar.Scroll += (sender, e) =>
{
    var scrollBar = sender as BeepScrollBar;
    // Perform smooth scrolling or animation
    SmoothScrollToPosition(scrollBar.Value);
};

this.Controls.Add(verticalScrollBar);

Horizontal ScrollBar

// Create a horizontal scrollbar
var horizontalScrollBar = new BeepScrollBar
{
    ScrollOrientation = Orientation.Horizontal,
    Location = new Point(50, 300),
    Size = new Size(200, 15),
    Minimum = 0,
    Maximum = 500,
    Value = 0,
    LargeChange = 50,
    SmallChange = 5
};

// Handle scrolling for horizontal content
horizontalScrollBar.ValueChanged += (sender, e) =>
{
    var scrollBar = sender as BeepScrollBar;
    
    // Update horizontal scroll position
    contentPanel.AutoScrollPosition = new Point(scrollBar.Value, 0);
};

this.Controls.Add(horizontalScrollBar);

Custom Appearance

// Create scrollbar with custom colors
var customScrollBar = new BeepScrollBar
{
    ScrollOrientation = Orientation.Vertical,
    Location = new Point(250, 50),
    Size = new Size(12, 200),
    
    // Custom colors
    TrackColor = Color.FromArgb(240, 240, 240),
    ThumbColor = Color.FromArgb(100, 100, 100),
    ThumbColorHover = Color.FromArgb(80, 80, 80),
    ThumbColorActive = Color.FromArgb(60, 60, 60),
    
    // Range settings
    Minimum = 0,
    Maximum = 1000,
    LargeChange = 100,
    SmallChange = 10
};

// Apply theme colors
customScrollBar.ApplyTheme();

this.Controls.Add(customScrollBar);

Properties

Behavior Properties

Property Type Default Description
ScrollOrientation Orientation Vertical Orientation of the scrollbar (Vertical or Horizontal)
Value int 0 Current scroll position value
Minimum int 0 Minimum scroll value
Maximum int 100 Maximum scroll value
LargeChange int 10 Value change for page up/down and track clicks
SmallChange int 1 Value change for arrow keys and mouse wheel

Appearance Properties

Property Type Default Description
TrackColor Color ControlDark Color of the scrollbar track (background)
ThumbColor Color ControlDarkDark Color of the scrollbar thumb (normal state)
ThumbColorHover Color ControlDark Color of the scrollbar thumb when hovering
ThumbColorActive Color ControlDarkDark Color of the scrollbar thumb when dragging

Size Guidelines

Orientation Recommended Width Recommended Height Minimum Length
Vertical 10-20 pixels 100+ pixels 50 pixels
Horizontal 100+ pixels 10-20 pixels 50 pixels

Events

Event Event Args Description
ValueChanged EventHandler Fired when the Value property changes
Scroll EventHandler Fired on any scroll action (drag, click, keyboard)

Event Handling

var scrollBar = new BeepScrollBar();

// Handle value changes for precise positioning
scrollBar.ValueChanged += (sender, e) =>
{
    var sb = sender as BeepScrollBar;
    
    // Calculate percentage
    double percentage = (double)(sb.Value - sb.Minimum) / (sb.Maximum - sb.Minimum);
    
    // Update content position
    UpdateContentPosition(percentage);
    
    // Update status
    statusLabel.Text = $"Position: {sb.Value}/{sb.Maximum} ({percentage:P0})";
};

// Handle scroll events for animation or feedback
scrollBar.Scroll += (sender, e) =>
{
    var sb = sender as BeepScrollBar;
    
    // Trigger scroll animation
    if (enableSmoothScrolling)
    {
        AnimateToPosition(sb.Value);
    }
    
    // Update scroll indicators
    UpdateScrollIndicators(sb.Value, sb.Maximum);
    
    // Log scroll activity
    LogScrollActivity(sb.Value);
};

Examples

Custom Scrollable Panel

public class CustomScrollablePanel : Panel
{
    private BeepScrollBar verticalScrollBar;
    private BeepScrollBar horizontalScrollBar;
    private Panel contentPanel;
    private Size contentSize;

    public CustomScrollablePanel()
    {
        SetupScrollablePanelContent();
        SetupScrollBars();
        UpdateScrollBars();
    }

    private void SetupScrollablePanelContent()
    {
        // Content panel that can be larger than visible area
        contentPanel = new Panel
        {
            Location = new Point(0, 0),
            BackColor = Color.White,
            BorderStyle = BorderStyle.None
        };

        // Set initial content size
        contentSize = new Size(800, 600);
        contentPanel.Size = contentSize;

        this.Controls.Add(contentPanel);
    }

    private void SetupScrollBars()
    {
        // Vertical scrollbar
        verticalScrollBar = new BeepScrollBar
        {
            ScrollOrientation = Orientation.Vertical,
            Dock = DockStyle.Right,
            Width = 16,
            Visible = false
        };

        verticalScrollBar.ValueChanged += OnVerticalScroll;

        // Horizontal scrollbar  
        horizontalScrollBar = new BeepScrollBar
        {
            ScrollOrientation = Orientation.Horizontal,
            Dock = DockStyle.Bottom,
            Height = 16,
            Visible = false
        };

        horizontalScrollBar.ValueChanged += OnHorizontalScroll;

        this.Controls.AddRange(new Control[] { verticalScrollBar, horizontalScrollBar });
    }

    private void OnVerticalScroll(object sender, EventArgs e)
    {
        var scrollBar = sender as BeepScrollBar;
        
        // Update content panel position
        int newY = -scrollBar.Value;
        contentPanel.Location = new Point(contentPanel.Location.X, newY);
    }

    private void OnHorizontalScroll(object sender, EventArgs e)
    {
        var scrollBar = sender as BeepScrollBar;
        
        // Update content panel position
        int newX = -scrollBar.Value;
        contentPanel.Location = new Point(newX, contentPanel.Location.Y);
    }

    protected override void OnResize(EventArgs e)
    {
        base.OnResize(e);
        UpdateScrollBars();
    }

    private void UpdateScrollBars()
    {
        if (contentPanel == null) return;

        // Calculate available area (excluding scrollbar space)
        int availableWidth = this.Width - (verticalScrollBar.Visible ? verticalScrollBar.Width : 0);
        int availableHeight = this.Height - (horizontalScrollBar.Visible ? horizontalScrollBar.Height : 0);

        // Determine if scrollbars are needed
        bool needVertical = contentSize.Height > availableHeight;
        bool needHorizontal = contentSize.Width > availableWidth;

        // Adjust available area if scrollbars are needed
        if (needVertical) availableWidth -= verticalScrollBar.Width;
        if (needHorizontal) availableHeight -= horizontalScrollBar.Height;

        // Re-check in case adding one scrollbar affects the other
        needVertical = contentSize.Height > availableHeight;
        needHorizontal = contentSize.Width > availableWidth;

        // Configure vertical scrollbar
        verticalScrollBar.Visible = needVertical;
        if (needVertical)
        {
            verticalScrollBar.Minimum = 0;
            verticalScrollBar.Maximum = contentSize.Height - availableHeight;
            verticalScrollBar.LargeChange = Math.Max(1, availableHeight / 10);
            verticalScrollBar.SmallChange = 20;
        }

        // Configure horizontal scrollbar
        horizontalScrollBar.Visible = needHorizontal;
        if (needHorizontal)
        {
            horizontalScrollBar.Minimum = 0;
            horizontalScrollBar.Maximum = contentSize.Width - availableWidth;
            horizontalScrollBar.LargeChange = Math.Max(1, availableWidth / 10);
            horizontalScrollBar.SmallChange = 20;
        }
    }

    public void SetContentSize(Size newSize)
    {
        contentSize = newSize;
        contentPanel.Size = contentSize;
        UpdateScrollBars();
    }

    public void ScrollToPosition(Point position)
    {
        if (verticalScrollBar.Visible)
        {
            verticalScrollBar.Value = Math.Max(verticalScrollBar.Minimum, 
                                               Math.Min(position.Y, verticalScrollBar.Maximum));
        }

        if (horizontalScrollBar.Visible)
        {
            horizontalScrollBar.Value = Math.Max(horizontalScrollBar.Minimum, 
                                                  Math.Min(position.X, horizontalScrollBar.Maximum));
        }
    }

    public void ScrollToTop()
    {
        if (verticalScrollBar.Visible)
            verticalScrollBar.Value = verticalScrollBar.Minimum;
    }

    public void ScrollToBottom()
    {
        if (verticalScrollBar.Visible)
            verticalScrollBar.Value = verticalScrollBar.Maximum;
    }
}

Image Viewer with Custom Scrollbars

public class ImageViewerControl : UserControl
{
    private BeepScrollBar vScrollBar;
    private BeepScrollBar hScrollBar;
    private PictureBox pictureBox;
    private Image currentImage;
    private float zoomFactor = 1.0f;

    public ImageViewerControl()
    {
        SetupImageViewer();
    }

    private void SetupImageViewer()
    {
        this.BackColor = Color.Gray;

        // Picture box for image display
        pictureBox = new PictureBox
        {
            SizeMode = PictureBoxSizeMode.Normal,
            Location = new Point(0, 0),
            BackColor = Color.Transparent
        };

        // Vertical scrollbar
        vScrollBar = new BeepScrollBar
        {
            ScrollOrientation = Orientation.Vertical,
            Dock = DockStyle.Right,
            Width = 18,
            Visible = false
        };
        vScrollBar.ValueChanged += OnVerticalScroll;

        // Horizontal scrollbar
        hScrollBar = new BeepScrollBar
        {
            ScrollOrientation = Orientation.Horizontal,
            Dock = DockStyle.Bottom,
            Height = 18,
            Visible = false
        };
        hScrollBar.ValueChanged += OnHorizontalScroll;

        this.Controls.AddRange(new Control[] { pictureBox, vScrollBar, hScrollBar });

        // Handle mouse wheel for zooming
        this.MouseWheel += OnMouseWheel;
    }

    public void LoadImage(Image image)
    {
        currentImage = image;
        UpdateImageDisplay();
    }

    private void UpdateImageDisplay()
    {
        if (currentImage == null) return;

        // Calculate scaled image size
        int scaledWidth = (int)(currentImage.Width * zoomFactor);
        int scaledHeight = (int)(currentImage.Height * zoomFactor);

        pictureBox.Size = new Size(scaledWidth, scaledHeight);
        pictureBox.Image = currentImage;

        UpdateScrollBars();
    }

    private void UpdateScrollBars()
    {
        if (currentImage == null) return;

        // Calculate available viewing area
        int viewWidth = this.Width - (vScrollBar.Visible ? vScrollBar.Width : 0);
        int viewHeight = this.Height - (hScrollBar.Visible ? hScrollBar.Height : 0);

        // Check if scrollbars are needed
        bool needVScroll = pictureBox.Height > viewHeight;
        bool needHScroll = pictureBox.Width > viewWidth;

        // Update available area if scrollbars will be shown
        if (needVScroll) viewWidth -= vScrollBar.Width;
        if (needHScroll) viewHeight -= hScrollBar.Height;

        // Re-check after accounting for scrollbar space
        needVScroll = pictureBox.Height > viewHeight;
        needHScroll = pictureBox.Width > viewWidth;

        // Configure vertical scrollbar
        vScrollBar.Visible = needVScroll;
        if (needVScroll)
        {
            vScrollBar.Minimum = 0;
            vScrollBar.Maximum = pictureBox.Height - viewHeight;
            vScrollBar.LargeChange = Math.Max(1, viewHeight);
            vScrollBar.SmallChange = 20;
        }

        // Configure horizontal scrollbar
        hScrollBar.Visible = needHScroll;
        if (needHScroll)
        {
            hScrollBar.Minimum = 0;
            hScrollBar.Maximum = pictureBox.Width - viewWidth;
            hScrollBar.LargeChange = Math.Max(1, viewWidth);
            hScrollBar.SmallChange = 20;
        }

        // Center image if smaller than view area
        if (!needVScroll && !needHScroll)
        {
            pictureBox.Location = new Point(
                (viewWidth - pictureBox.Width) / 2,
                (viewHeight - pictureBox.Height) / 2
            );
        }
    }

    private void OnVerticalScroll(object sender, EventArgs e)
    {
        var scrollBar = sender as BeepScrollBar;
        pictureBox.Location = new Point(pictureBox.Location.X, -scrollBar.Value);
    }

    private void OnHorizontalScroll(object sender, EventArgs e)
    {
        var scrollBar = sender as BeepScrollBar;
        pictureBox.Location = new Point(-scrollBar.Value, pictureBox.Location.Y);
    }

    protected override void OnResize(EventArgs e)
    {
        base.OnResize(e);
        UpdateScrollBars();
    }

    private void OnMouseWheel(object sender, MouseEventArgs e)
    {
        // Zoom in/out with mouse wheel
        float zoomDelta = e.Delta > 0 ? 1.1f : 0.9f;
        SetZoom(zoomFactor * zoomDelta);
    }

    public void SetZoom(float newZoom)
    {
        zoomFactor = Math.Max(0.1f, Math.Min(newZoom, 10.0f));
        UpdateImageDisplay();
    }

    public void ZoomToFit()
    {
        if (currentImage == null) return;

        float scaleX = (float)this.Width / currentImage.Width;
        float scaleY = (float)this.Height / currentImage.Height;
        SetZoom(Math.Min(scaleX, scaleY));
    }

    public void ZoomActualSize()
    {
        SetZoom(1.0f);
    }
}

Theming

BeepScrollBar provides specialized theming with dedicated scrollbar color properties:

Theme Application

var scrollBar = new BeepScrollBar
{
    ScrollOrientation = Orientation.Vertical,
    Size = new Size(15, 200)
};

// Apply theme - automatically sets scrollbar-specific colors
scrollBar.Theme = "DarkTheme";
scrollBar.ApplyTheme();

// Theme sets these properties automatically:
// - BackColor: ScrollBarBackColor
// - TrackColor: ScrollBarTrackColor  
// - ThumbColor: ScrollBarThumbColor
// - ThumbColorHover: ScrollBarHoverThumbColor
// - ThumbColorActive: ScrollBarActiveThumbColor

ScrollBar Theme Properties

  • ScrollBarBackColor - Overall scrollbar background
  • ScrollBarTrackColor - Track (groove) background color
  • ScrollBarThumbColor - Thumb (slider) normal color
  • ScrollBarHoverThumbColor - Thumb color when hovering
  • ScrollBarActiveThumbColor - Thumb color when dragging

Custom ScrollBar Styling

// Create custom theme for scrollbars
var customTheme = new BeepTheme
{
    ScrollBarBackColor = Color.FromArgb(248, 250, 252),
    ScrollBarTrackColor = Color.FromArgb(226, 232, 240),
    ScrollBarThumbColor = Color.FromArgb(148, 163, 184),
    ScrollBarHoverThumbColor = Color.FromArgb(100, 116, 139),
    ScrollBarActiveThumbColor = Color.FromArgb(71, 85, 105)
};

// Apply to scrollbar
BeepThemesManager.AddTheme("CustomScrollBar", customTheme);
scrollBar.Theme = "CustomScrollBar";
scrollBar.ApplyTheme();

// Or set colors directly
scrollBar.TrackColor = Color.LightGray;
scrollBar.ThumbColor = Color.DarkGray;
scrollBar.ThumbColorHover = Color.Gray;
scrollBar.ThumbColorActive = Color.Black;

Best Practices

?? Sizing Guidelines

  • Width/Height: Use 12-20 pixels for scrollbar thickness
  • Minimum length: Ensure at least 50 pixels of length for usability
  • Proportional thumbs: Set LargeChange to match visible content ratio
  • Auto-sizing: Update scrollbar ranges when content changes

?? User Experience

  • Visual feedback: Use distinct hover and active states
  • Smooth movement: Ensure responsive thumb dragging
  • Keyboard support: Test arrow key and page up/down navigation
  • Mouse wheel: Implement mouse wheel scrolling for convenience

?? Implementation

  • Range validation: Ensure Maximum > Minimum + LargeChange
  • Change values: Set appropriate SmallChange and LargeChange values
  • Event handling: Use ValueChanged for position updates, Scroll for animations
  • Performance: Minimize redraws during continuous scrolling

?? Visual Design

  • Color contrast: Ensure sufficient contrast between track and thumb
  • State indication: Make hover and active states clearly visible
  • Theme consistency: Use theme colors for brand consistency
  • Modern appearance: Consider rounded corners and subtle shadows
?? Performance Tip

For large content, use virtual scrolling techniques and update only visible portions during scroll events to maintain smooth performance.

? Best Practice

Set LargeChange to approximately the size of the visible content area for intuitive page-up/page-down behavior.

?? Range Warning

Ensure Maximum is always greater than Minimum + LargeChange, or the scrollbar may not function correctly.