2021-06-03 22:52:47 +12:00
|
|
|
|
// <copyright file="CustomScrollbar.cs" company="PlaceholderCompany">
|
|
|
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
|
|
|
// </copyright>
|
|
|
|
|
|
|
|
|
|
namespace SystemTrayMenu.UserInterface
|
|
|
|
|
{
|
|
|
|
|
using System;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using System.Windows.Forms.Design;
|
|
|
|
|
|
|
|
|
|
[Designer(typeof(ScrollbarControlDesigner))]
|
|
|
|
|
public class CustomScrollbar : UserControl
|
|
|
|
|
{
|
|
|
|
|
private readonly Timer timerMouseStillClicked = new Timer();
|
|
|
|
|
|
|
|
|
|
private float moLargeChange = 10;
|
|
|
|
|
private float moSmallChange = 1;
|
|
|
|
|
private int moMinimum = 0;
|
|
|
|
|
private int moMaximum = 100;
|
|
|
|
|
private int moValue = 0;
|
|
|
|
|
private int nClickPoint;
|
|
|
|
|
|
|
|
|
|
private float moSliderTop = 0;
|
|
|
|
|
private bool moSliderDown = false;
|
|
|
|
|
private bool moSliderDragging = false;
|
|
|
|
|
private bool arrowUpHovered = false;
|
|
|
|
|
private bool sliderHovered = false;
|
|
|
|
|
private bool arrowDownHovered = false;
|
|
|
|
|
private bool mouseStillClickedMoveUp = false;
|
|
|
|
|
private bool mouseStillClickedMoveLarge;
|
|
|
|
|
private int timerMouseStillClickedCounter = 0;
|
|
|
|
|
private int lastValue = 0;
|
|
|
|
|
private bool paintEnabledWasCalled = false;
|
|
|
|
|
private bool paintEnabled = false;
|
|
|
|
|
|
|
|
|
|
public CustomScrollbar()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
SetStyle(ControlStyles.ResizeRedraw, true);
|
|
|
|
|
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
|
|
|
|
SetStyle(ControlStyles.DoubleBuffer, true);
|
|
|
|
|
|
|
|
|
|
int GetScrollbarHeight()
|
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nTrackHeight = Height - (Width + Width);
|
|
|
|
|
float fSliderHeight = (float)LargeChange / Maximum * nTrackHeight;
|
|
|
|
|
int nSliderHeight = (int)fSliderHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
if (nSliderHeight > nTrackHeight)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nSliderHeight = nTrackHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
if (nSliderHeight < 56)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nSliderHeight = 56;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
return nSliderHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
timerMouseStillClicked.Interval = 30;
|
|
|
|
|
timerMouseStillClicked.Tick += TimerMouseStillClicked_Tick;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public new event EventHandler Scroll = null;
|
|
|
|
|
|
|
|
|
|
public event EventHandler ValueChanged = null;
|
|
|
|
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Always)]
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
[DefaultValue(false)]
|
|
|
|
|
[Category("Behavior")]
|
|
|
|
|
[Description("LargeChange")]
|
|
|
|
|
public float LargeChange
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return moLargeChange;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
moLargeChange = value;
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Always)]
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
[DefaultValue(false)]
|
|
|
|
|
[Category("Behavior")]
|
|
|
|
|
[Description("SmallChange")]
|
|
|
|
|
public float SmallChange
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return moSmallChange;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
moSmallChange = value;
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Always)]
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
[DefaultValue(false)]
|
|
|
|
|
[Category("Behavior")]
|
|
|
|
|
[Description("Minimum")]
|
|
|
|
|
public int Minimum
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return moMinimum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
moMinimum = value;
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Always)]
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
[DefaultValue(false)]
|
|
|
|
|
[Category("Behavior")]
|
|
|
|
|
[Description("Maximum")]
|
|
|
|
|
public int Maximum
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return moMaximum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
moMaximum = value;
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Always)]
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
[DefaultValue(false)]
|
|
|
|
|
[Category("Behavior")]
|
|
|
|
|
[Description("Value")]
|
|
|
|
|
public int Value
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return moValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
moValue = value;
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nTrackHeight = Height - (Width + Width);
|
|
|
|
|
float fSliderHeight = (float)LargeChange / Maximum * nTrackHeight;
|
|
|
|
|
int nSliderHeight = (int)fSliderHeight;
|
|
|
|
|
if (nSliderHeight > nTrackHeight)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nSliderHeight = nTrackHeight;
|
|
|
|
|
fSliderHeight = nTrackHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
if (nSliderHeight < 56)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nSliderHeight = 56;
|
|
|
|
|
fSliderHeight = 56;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nPixelRange = nTrackHeight - nSliderHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
int nRealRange = Maximum - Minimum - (int)LargeChange;
|
|
|
|
|
float fPerc = 0.0f;
|
|
|
|
|
if (nRealRange != 0)
|
|
|
|
|
{
|
|
|
|
|
fPerc = moValue / (float)nRealRange;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float fTop = fPerc * nPixelRange;
|
|
|
|
|
moSliderTop = (int)fTop;
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int Delta
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return Value - lastValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool AutoSize
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return base.AutoSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
base.AutoSize = value;
|
|
|
|
|
if (base.AutoSize)
|
|
|
|
|
{
|
2021-06-05 03:21:52 +12:00
|
|
|
|
Width = Width;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CustomScrollbar_MouseWheel(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (e.Delta > 0)
|
|
|
|
|
{
|
|
|
|
|
MoveUp(SmallChange * MenuDefines.Scrollspeed);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MoveDown(SmallChange * MenuDefines.Scrollspeed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void Reset()
|
|
|
|
|
{
|
|
|
|
|
moSliderTop = 0;
|
|
|
|
|
moSliderDown = false;
|
|
|
|
|
moSliderDragging = false;
|
|
|
|
|
arrowUpHovered = false;
|
|
|
|
|
sliderHovered = false;
|
|
|
|
|
arrowDownHovered = false;
|
|
|
|
|
mouseStillClickedMoveUp = false;
|
|
|
|
|
mouseStillClickedMoveLarge = false;
|
|
|
|
|
timerMouseStillClickedCounter = 0;
|
|
|
|
|
lastValue = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Show the control
|
|
|
|
|
/// (workaround, because visible = false, was causing appearing scrollbars).
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal void PaintEnable()
|
|
|
|
|
{
|
|
|
|
|
Enabled = true;
|
|
|
|
|
if (!paintEnabled)
|
|
|
|
|
{
|
|
|
|
|
paintEnabledWasCalled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
paintEnabled = true;
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Hide the control
|
|
|
|
|
/// (workaround, because visible = false, was causing appearing scrollbars).
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal void PaintDisable()
|
|
|
|
|
{
|
|
|
|
|
if (!paintEnabledWasCalled)
|
|
|
|
|
{
|
|
|
|
|
Enabled = false;
|
|
|
|
|
Size = new Size(0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
paintEnabled = false;
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void Dispose(bool disposing)
|
|
|
|
|
{
|
|
|
|
|
timerMouseStillClicked.Dispose();
|
|
|
|
|
base.Dispose(disposing);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnPaint(PaintEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
|
|
|
|
|
|
|
|
|
|
Color colorArrows;
|
|
|
|
|
Color colorArrowsHover;
|
|
|
|
|
Color colorSlider;
|
|
|
|
|
Color colorSliderHover;
|
|
|
|
|
Color colorSliderDragging;
|
2021-06-04 01:00:53 +12:00
|
|
|
|
Color colorBackground;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (Config.IsDarkMode())
|
|
|
|
|
{
|
|
|
|
|
colorArrows = Color.FromArgb(103, 103, 103);
|
|
|
|
|
colorArrowsHover = Color.FromArgb(55, 55, 55);
|
|
|
|
|
colorSlider = Color.FromArgb(77, 77, 77);
|
|
|
|
|
colorSliderHover = Color.FromArgb(122, 122, 122);
|
|
|
|
|
colorSliderDragging = Color.FromArgb(166, 166, 166);
|
2021-06-04 01:00:53 +12:00
|
|
|
|
colorBackground = Color.FromArgb(23, 23, 23);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-06-04 01:00:53 +12:00
|
|
|
|
colorArrows = Color.FromArgb(96, 96, 96);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
colorArrowsHover = Color.FromArgb(0, 0, 0);
|
|
|
|
|
colorSlider = Color.FromArgb(205, 205, 205);
|
|
|
|
|
colorSliderHover = Color.FromArgb(166, 166, 166);
|
|
|
|
|
colorSliderDragging = Color.FromArgb(96, 96, 96);
|
2021-06-04 01:00:53 +12:00
|
|
|
|
colorBackground = Color.FromArgb(240, 240, 240);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paintEnabled)
|
|
|
|
|
{
|
|
|
|
|
e.Graphics.FillRectangle(
|
2021-06-04 01:00:53 +12:00
|
|
|
|
new SolidBrush(colorBackground),
|
2021-06-03 22:52:47 +12:00
|
|
|
|
new Rectangle(0, 0, Width, Height));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Draw background
|
2021-06-04 01:00:53 +12:00
|
|
|
|
Brush brushScrollbarBorder = new SolidBrush(colorBackground);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
e.Graphics.FillRectangle(brushScrollbarBorder, new Rectangle(0, 0, Width, Height));
|
|
|
|
|
|
|
|
|
|
// Draw arrowUp
|
|
|
|
|
Pen penArrowUp;
|
|
|
|
|
if (arrowUpHovered)
|
|
|
|
|
{
|
|
|
|
|
penArrowUp = new Pen(colorArrowsHover, 2.5F);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
penArrowUp = new Pen(colorArrows, 2.5F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int widthDevidedBy2 = Width / 2;
|
|
|
|
|
int widthDevidedBy6 = Width / 6;
|
|
|
|
|
int widthDevidedBy2PluswidthDevidedBy8 = widthDevidedBy2 + (Width / 8);
|
|
|
|
|
PointF pointArrowUp1 = new PointF(widthDevidedBy2 - widthDevidedBy6, widthDevidedBy2PluswidthDevidedBy8);
|
|
|
|
|
PointF pointArrowUp2 = new PointF(widthDevidedBy2 + widthDevidedBy6, widthDevidedBy2PluswidthDevidedBy8);
|
|
|
|
|
PointF pointArrowUp3 = new PointF(widthDevidedBy2, widthDevidedBy2PluswidthDevidedBy8 - widthDevidedBy6);
|
|
|
|
|
PointF pointArrowUp4 = pointArrowUp1;
|
|
|
|
|
PointF[] curvePoints =
|
|
|
|
|
{
|
|
|
|
|
pointArrowUp1,
|
|
|
|
|
pointArrowUp2,
|
|
|
|
|
pointArrowUp3,
|
|
|
|
|
pointArrowUp4,
|
|
|
|
|
};
|
|
|
|
|
e.Graphics.DrawPolygon(penArrowUp, curvePoints);
|
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
// draw slider
|
|
|
|
|
int nTrackHeight = Height - (Width * 2);
|
|
|
|
|
float fSliderHeight = (float)LargeChange / Maximum * nTrackHeight;
|
|
|
|
|
int nSliderHeight = (int)fSliderHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
if (nSliderHeight > nTrackHeight)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nSliderHeight = nTrackHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
if (nSliderHeight < 56)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nSliderHeight = 56;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nTop = (int)moSliderTop;
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nTop += this.Width;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
|
|
|
|
SolidBrush solidBrushSlider;
|
|
|
|
|
if (moSliderDragging)
|
|
|
|
|
{
|
|
|
|
|
solidBrushSlider = new SolidBrush(colorSliderDragging);
|
|
|
|
|
}
|
|
|
|
|
else if (sliderHovered)
|
|
|
|
|
{
|
|
|
|
|
solidBrushSlider = new SolidBrush(colorSliderHover);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
solidBrushSlider = new SolidBrush(colorSlider);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
Rectangle rectangleSlider = new Rectangle(1, nTop + 1, Width - 2, nSliderHeight - 1);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
e.Graphics.FillRectangle(solidBrushSlider, rectangleSlider);
|
|
|
|
|
|
|
|
|
|
// Draw arrowDown
|
|
|
|
|
Pen penArrowDown;
|
|
|
|
|
if (arrowDownHovered)
|
|
|
|
|
{
|
|
|
|
|
penArrowDown = new Pen(colorArrowsHover, 2.5F);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
penArrowDown = new Pen(colorArrows, 2.5F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PointF pointArrowDown1 = new PointF(widthDevidedBy2 - widthDevidedBy6, Height - widthDevidedBy2PluswidthDevidedBy8);
|
|
|
|
|
PointF pointArrowDown2 = new PointF(widthDevidedBy2 + widthDevidedBy6, Height - widthDevidedBy2PluswidthDevidedBy8);
|
|
|
|
|
PointF pointArrowDown3 = new PointF(widthDevidedBy2, Height - widthDevidedBy2PluswidthDevidedBy8 + widthDevidedBy6);
|
|
|
|
|
PointF pointArrowDown4 = pointArrowDown1;
|
|
|
|
|
PointF[] curvePointsArrowDown =
|
|
|
|
|
{
|
|
|
|
|
pointArrowDown1,
|
|
|
|
|
pointArrowDown2,
|
|
|
|
|
pointArrowDown3,
|
|
|
|
|
pointArrowDown4,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
e.Graphics.DrawPolygon(penArrowDown, curvePointsArrowDown);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void TimerMouseStillClicked_Tick(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
timerMouseStillClickedCounter++;
|
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nTrackHeight = Height - (Width + Width);
|
|
|
|
|
float fSliderHeight = (float)LargeChange / Maximum * nTrackHeight;
|
|
|
|
|
int nScrollbarHeight = (int)fSliderHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
|
|
|
|
if (nScrollbarHeight > nTrackHeight)
|
|
|
|
|
{
|
|
|
|
|
nScrollbarHeight = nTrackHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nScrollbarHeight < 56)
|
|
|
|
|
{
|
|
|
|
|
nScrollbarHeight = 56;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nTop = (int)moSliderTop;
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nTop += Width;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
Point ptPoint = PointToClient(Cursor.Position);
|
2021-06-05 03:21:52 +12:00
|
|
|
|
Rectangle thumbrect = new Rectangle(new Point(0, nTop), new Size(Width + 1, nScrollbarHeight));
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (thumbrect.Contains(ptPoint))
|
|
|
|
|
{
|
|
|
|
|
timerMouseStillClicked.Stop();
|
|
|
|
|
}
|
|
|
|
|
else if (timerMouseStillClickedCounter > 6)
|
|
|
|
|
{
|
|
|
|
|
float change;
|
|
|
|
|
if (mouseStillClickedMoveLarge)
|
|
|
|
|
{
|
|
|
|
|
change = SmallChange * MenuDefines.Scrollspeed;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
change = SmallChange;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mouseStillClickedMoveUp)
|
|
|
|
|
{
|
|
|
|
|
MoveUp(change);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MoveDown(change);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitializeComponent()
|
|
|
|
|
{
|
|
|
|
|
SuspendLayout();
|
|
|
|
|
Name = "CustomScrollbar";
|
|
|
|
|
MouseDown += CustomScrollbar_MouseDown;
|
|
|
|
|
MouseMove += CustomScrollbar_MouseMove;
|
|
|
|
|
MouseUp += CustomScrollbar_MouseUp;
|
|
|
|
|
MouseLeave += CustomScrollbar_MouseLeave;
|
|
|
|
|
|
|
|
|
|
// this.MouseWheel += CustomScrollbar_MouseWheel;
|
|
|
|
|
ResumeLayout(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CustomScrollbar_MouseLeave(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
arrowUpHovered = false;
|
|
|
|
|
sliderHovered = false;
|
|
|
|
|
arrowDownHovered = false;
|
|
|
|
|
Refresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CustomScrollbar_MouseDown(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Point ptPoint = PointToClient(Cursor.Position);
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nTrackHeight = Height - (Width + Width);
|
|
|
|
|
float fSliderHeight = (float)LargeChange / Maximum * nTrackHeight;
|
|
|
|
|
int nScrollbarHeight = (int)fSliderHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
|
|
|
|
if (nScrollbarHeight > nTrackHeight)
|
|
|
|
|
{
|
|
|
|
|
nScrollbarHeight = nTrackHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nScrollbarHeight < 56)
|
|
|
|
|
{
|
|
|
|
|
nScrollbarHeight = 56;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nTop = (int)moSliderTop;
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nTop += Width;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
2021-06-05 03:21:52 +12:00
|
|
|
|
Rectangle thumbrect = new Rectangle(new Point(0, nTop), new Size(Width + 1, nScrollbarHeight));
|
|
|
|
|
Rectangle trackRectangle = new Rectangle(new Point(0, Width), new Size(Width + 1, nTrackHeight));
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (thumbrect.Contains(ptPoint))
|
|
|
|
|
{
|
|
|
|
|
nClickPoint = ptPoint.Y - nTop;
|
|
|
|
|
moSliderDown = true;
|
|
|
|
|
}
|
|
|
|
|
else if (trackRectangle.Contains(ptPoint))
|
|
|
|
|
{
|
|
|
|
|
if (e.Y < thumbrect.Y)
|
|
|
|
|
{
|
|
|
|
|
MoveUp(Height);
|
|
|
|
|
mouseStillClickedMoveUp = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MoveDown(Height);
|
|
|
|
|
mouseStillClickedMoveUp = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mouseStillClickedMoveLarge = true;
|
|
|
|
|
timerMouseStillClickedCounter = 0;
|
|
|
|
|
timerMouseStillClicked.Start();
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:21:52 +12:00
|
|
|
|
Rectangle uparrowrect = new Rectangle(new Point(0, 0), new Size(Width + 1, Width));
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (uparrowrect.Contains(ptPoint))
|
|
|
|
|
{
|
|
|
|
|
MoveUp(SmallChange);
|
|
|
|
|
mouseStillClickedMoveUp = true;
|
|
|
|
|
mouseStillClickedMoveLarge = false;
|
|
|
|
|
timerMouseStillClickedCounter = 0;
|
|
|
|
|
timerMouseStillClicked.Start();
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:21:52 +12:00
|
|
|
|
Rectangle downarrowrect = new Rectangle(new Point(0, Width + nTrackHeight), new Size(Width + 1, Width));
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (downarrowrect.Contains(ptPoint))
|
|
|
|
|
{
|
|
|
|
|
MoveDown(SmallChange);
|
|
|
|
|
mouseStillClickedMoveUp = false;
|
|
|
|
|
mouseStillClickedMoveLarge = false;
|
|
|
|
|
timerMouseStillClickedCounter = 0;
|
|
|
|
|
timerMouseStillClicked.Start();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void MoveDown(float change)
|
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nTrackHeight = Height - (Width + Width);
|
|
|
|
|
float fSliderHeight = (float)LargeChange / Maximum * nTrackHeight;
|
|
|
|
|
int nSliderHeight = (int)fSliderHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
if (nSliderHeight > nTrackHeight)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nSliderHeight = nTrackHeight;
|
|
|
|
|
fSliderHeight = nTrackHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
if (nSliderHeight < 56)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nSliderHeight = 56;
|
|
|
|
|
fSliderHeight = 56;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nRealRange = Maximum - Minimum - (int)LargeChange;
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nPixelRange = nTrackHeight - nSliderHeight;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (nRealRange > 0)
|
|
|
|
|
{
|
|
|
|
|
if (nPixelRange > 0)
|
|
|
|
|
{
|
|
|
|
|
float changeForOneItem = (change * nPixelRange) / (Maximum - LargeChange);
|
|
|
|
|
|
|
|
|
|
if ((moSliderTop + changeForOneItem) > nPixelRange)
|
|
|
|
|
{
|
|
|
|
|
moSliderTop = nPixelRange;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
moSliderTop += changeForOneItem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// figure out value
|
|
|
|
|
float fPerc = moSliderTop / nPixelRange;
|
|
|
|
|
float fValue = fPerc * (Maximum - LargeChange);
|
|
|
|
|
|
|
|
|
|
moValue = (int)fValue;
|
|
|
|
|
|
|
|
|
|
if (Value != lastValue)
|
|
|
|
|
{
|
|
|
|
|
ValueChanged?.Invoke(this, new EventArgs());
|
|
|
|
|
Scroll?.Invoke(this, new EventArgs());
|
|
|
|
|
lastValue = Value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void MoveUp(float change)
|
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nTrackHeight = Height - (Width + Width);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
float fSliderHeight = (float)LargeChange / Maximum * nTrackHeight;
|
|
|
|
|
int nSliderHeight = (int)fSliderHeight;
|
|
|
|
|
|
|
|
|
|
if (nSliderHeight > nTrackHeight)
|
|
|
|
|
{
|
|
|
|
|
nSliderHeight = nTrackHeight;
|
|
|
|
|
fSliderHeight = nTrackHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nSliderHeight < 56)
|
|
|
|
|
{
|
|
|
|
|
nSliderHeight = 56;
|
|
|
|
|
fSliderHeight = 56;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nRealRange = Maximum - Minimum - (int)LargeChange;
|
|
|
|
|
int nPixelRange = nTrackHeight - nSliderHeight;
|
|
|
|
|
if (nRealRange > 0)
|
|
|
|
|
{
|
|
|
|
|
if (nPixelRange > 0)
|
|
|
|
|
{
|
|
|
|
|
float changeForOneItem = (change * nPixelRange) / (Maximum - LargeChange);
|
|
|
|
|
|
|
|
|
|
if ((moSliderTop - changeForOneItem) < 0)
|
|
|
|
|
{
|
|
|
|
|
moSliderTop = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
moSliderTop -= changeForOneItem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// figure out value
|
|
|
|
|
float fPerc = moSliderTop / nPixelRange;
|
|
|
|
|
float fValue = fPerc * (Maximum - LargeChange);
|
|
|
|
|
|
|
|
|
|
moValue = (int)fValue;
|
|
|
|
|
|
|
|
|
|
if (Value != lastValue)
|
|
|
|
|
{
|
|
|
|
|
ValueChanged?.Invoke(this, new EventArgs());
|
|
|
|
|
Scroll?.Invoke(this, new EventArgs());
|
|
|
|
|
lastValue = Value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CustomScrollbar_MouseUp(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
moSliderDown = false;
|
|
|
|
|
moSliderDragging = false;
|
|
|
|
|
timerMouseStillClicked.Stop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CustomScrollbar_MouseMove(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (moSliderDown == true)
|
|
|
|
|
{
|
|
|
|
|
moSliderDragging = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (moSliderDragging)
|
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
MoveSlider(e.Y);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Value != lastValue)
|
|
|
|
|
{
|
|
|
|
|
ValueChanged?.Invoke(this, new EventArgs());
|
|
|
|
|
Scroll?.Invoke(this, new EventArgs());
|
|
|
|
|
lastValue = Value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remember hovered control
|
|
|
|
|
Point ptPoint = PointToClient(Cursor.Position);
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nTrackHeight = Height - (Width + Width);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
float fSliderHeight = (float)LargeChange / Maximum * nTrackHeight;
|
|
|
|
|
int nSliderHeight = (int)fSliderHeight;
|
|
|
|
|
|
|
|
|
|
if (nSliderHeight > nTrackHeight)
|
|
|
|
|
{
|
|
|
|
|
nSliderHeight = nTrackHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nSliderHeight < 56)
|
|
|
|
|
{
|
|
|
|
|
nSliderHeight = 56;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nTop = (int)moSliderTop;
|
2021-06-05 03:15:18 +12:00
|
|
|
|
nTop += Width;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
2021-06-05 03:21:52 +12:00
|
|
|
|
Rectangle scrollbarbrect = new Rectangle(new Point(0, nTop), new Size(Width + 1, nSliderHeight));
|
|
|
|
|
Rectangle trackRectangle = new Rectangle(new Point(0, Width), new Size(Width + 1, nTrackHeight));
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (scrollbarbrect.Contains(ptPoint))
|
|
|
|
|
{
|
|
|
|
|
if (e.Button != MouseButtons.Left)
|
|
|
|
|
{
|
|
|
|
|
arrowUpHovered = false;
|
|
|
|
|
sliderHovered = true;
|
|
|
|
|
arrowDownHovered = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (trackRectangle.Contains(ptPoint))
|
|
|
|
|
{
|
|
|
|
|
if (e.Y < scrollbarbrect.Y)
|
|
|
|
|
{
|
|
|
|
|
arrowUpHovered = false;
|
|
|
|
|
sliderHovered = false;
|
|
|
|
|
arrowDownHovered = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
arrowUpHovered = false;
|
|
|
|
|
sliderHovered = false;
|
|
|
|
|
arrowDownHovered = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:21:52 +12:00
|
|
|
|
Rectangle uparrowrect = new Rectangle(new Point(0, 0), new Size(Width + 1, Width));
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (uparrowrect.Contains(ptPoint))
|
|
|
|
|
{
|
|
|
|
|
arrowUpHovered = true;
|
|
|
|
|
sliderHovered = false;
|
|
|
|
|
arrowDownHovered = false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:21:52 +12:00
|
|
|
|
Rectangle downarrowrect = new Rectangle(new Point(0, Width + nTrackHeight), new Size(Width + 1, Width));
|
2021-06-03 22:52:47 +12:00
|
|
|
|
if (downarrowrect.Contains(ptPoint))
|
|
|
|
|
{
|
|
|
|
|
arrowUpHovered = false;
|
|
|
|
|
sliderHovered = false;
|
|
|
|
|
arrowDownHovered = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
private void MoveSlider(int y)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
|
|
|
|
int nRealRange = Maximum - Minimum;
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nTrackHeight = Height - (Width + Width);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
float fSliderHeight = (float)LargeChange / Maximum * nTrackHeight;
|
|
|
|
|
int nSliderHeight = (int)fSliderHeight;
|
|
|
|
|
|
|
|
|
|
if (nSliderHeight > nTrackHeight)
|
|
|
|
|
{
|
|
|
|
|
nSliderHeight = nTrackHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nSliderHeight < 56)
|
|
|
|
|
{
|
|
|
|
|
nSliderHeight = 56;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nSpot = nClickPoint;
|
|
|
|
|
|
|
|
|
|
int nPixelRange = nTrackHeight - nSliderHeight;
|
|
|
|
|
if (moSliderDown && nRealRange > 0)
|
|
|
|
|
{
|
|
|
|
|
if (nPixelRange > 0)
|
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
int nNewSliderTop = y - (Width + nSpot);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
|
2021-06-05 03:15:18 +12:00
|
|
|
|
if (nNewSliderTop < 0)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
moSliderTop = nNewSliderTop = 0;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
2021-06-05 03:15:18 +12:00
|
|
|
|
else if (nNewSliderTop > nPixelRange)
|
2021-06-03 22:52:47 +12:00
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
moSliderTop = nNewSliderTop = nPixelRange;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-06-05 03:15:18 +12:00
|
|
|
|
moSliderTop = y - (Width + nSpot);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// figure out value
|
|
|
|
|
float fPerc = moSliderTop / nPixelRange;
|
|
|
|
|
float fValue = fPerc * (Maximum - LargeChange);
|
|
|
|
|
moValue = (int)fValue;
|
|
|
|
|
|
|
|
|
|
Application.DoEvents();
|
|
|
|
|
|
|
|
|
|
Invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|