Added DarkScrollBase and DarkScrollView

Abstract classes that can be built on top of for scrollable controls.
Use DarkScrollBase for non-GDI rendering and DarkScrollView for GDI
rendering.
This commit is contained in:
Robin 2015-09-18 12:14:47 +01:00
parent 13c57d8162
commit 431cea92c8
3 changed files with 357 additions and 0 deletions

View File

@ -0,0 +1,294 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace DarkUI
{
public abstract class DarkScrollBase : Control
{
#region Event Region
public event EventHandler ViewportChanged;
public event EventHandler ContentSizeChanged;
#endregion
#region Field Region
protected readonly DarkScrollBar _vScrollBar;
protected readonly DarkScrollBar _hScrollBar;
private Size _visibleSize;
private Size _contentSize;
private Rectangle _viewport;
private Point _offsetMousePosition;
#endregion
#region Property Region
public Rectangle Viewport
{
get { return _viewport; }
private set
{
_viewport = value;
if (ViewportChanged != null)
ViewportChanged(this, null);
}
}
public Size ContentSize
{
get { return _contentSize; }
set
{
_contentSize = value;
UpdateScrollBars();
if (ContentSizeChanged != null)
ContentSizeChanged(this, null);
}
}
public Point OffsetMousePosition
{
get { return _offsetMousePosition; }
}
#endregion
#region Constructor Region
protected DarkScrollBase()
{
SetStyle(ControlStyles.Selectable |
ControlStyles.UserMouse, true);
_vScrollBar = new DarkScrollBar { ScrollOrientation = DarkOrientation.Vertical };
_hScrollBar = new DarkScrollBar { ScrollOrientation = DarkOrientation.Horizontal };
Controls.Add(_vScrollBar);
Controls.Add(_hScrollBar);
_vScrollBar.ValueChanged += delegate { UpdateViewport(); };
_hScrollBar.ValueChanged += delegate { UpdateViewport(); };
_vScrollBar.MouseDown += delegate { Select(); };
_hScrollBar.MouseDown += delegate { Select(); };
}
#endregion
#region Event Handler Region
protected override void OnCreateControl()
{
base.OnCreateControl();
UpdateScrollBars();
}
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
Invalidate();
}
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
Invalidate();
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
UpdateScrollBars();
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
_offsetMousePosition = new Point(e.X + Viewport.Left, e.Y + Viewport.Top);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Right)
Select();
}
protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);
var horizontal = false;
if (_hScrollBar.Visible && ModifierKeys == Keys.Control)
horizontal = true;
if (_hScrollBar.Visible && !_vScrollBar.Visible)
horizontal = true;
if (!horizontal)
{
if (e.Delta > 0)
_vScrollBar.ScrollByPhysical(3);
else if (e.Delta < 0)
_vScrollBar.ScrollByPhysical(-3);
}
else
{
if (e.Delta > 0)
_hScrollBar.ScrollByPhysical(3);
else if (e.Delta < 0)
_hScrollBar.ScrollByPhysical(-3);
}
}
protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
{
base.OnPreviewKeyDown(e);
// Allows arrow keys to trigger OnKeyPress
switch (e.KeyCode)
{
case Keys.Up:
case Keys.Down:
case Keys.Left:
case Keys.Right:
e.IsInputKey = true;
break;
}
}
#endregion
#region Method Region
private void UpdateScrollBars()
{
if (_vScrollBar.Maximum != ContentSize.Height)
_vScrollBar.Maximum = ContentSize.Height;
if (_hScrollBar.Maximum != ContentSize.Width)
_hScrollBar.Maximum = ContentSize.Width;
var scrollSize = Consts.ScrollBarSize;
_vScrollBar.Location = new Point(ClientSize.Width - scrollSize, 0);
_vScrollBar.Size = new Size(scrollSize, ClientSize.Height);
_hScrollBar.Location = new Point(0, ClientSize.Height - scrollSize);
_hScrollBar.Size = new Size(ClientSize.Width, scrollSize);
if (DesignMode)
return;
// Do this twice in case changing the visibility of the scrollbars
// causes the VisibleSize to change in such a way as to require a second scrollbar.
// Probably a better way to detect that scenario...
SetVisibleSize();
SetScrollBarVisibility();
SetVisibleSize();
SetScrollBarVisibility();
if (_vScrollBar.Visible)
_hScrollBar.Width -= scrollSize;
if (_hScrollBar.Visible)
_vScrollBar.Height -= scrollSize;
_vScrollBar.ViewSize = _visibleSize.Height;
_hScrollBar.ViewSize = _visibleSize.Width;
UpdateViewport();
}
private void SetScrollBarVisibility()
{
_vScrollBar.Visible = _visibleSize.Height < ContentSize.Height;
_hScrollBar.Visible = _visibleSize.Width < ContentSize.Width;
}
private void SetVisibleSize()
{
var scrollSize = Consts.ScrollBarSize;
_visibleSize = new Size(ClientSize.Width, ClientSize.Height);
if (_vScrollBar.Visible)
_visibleSize.Width -= scrollSize;
if (_hScrollBar.Visible)
_visibleSize.Height -= scrollSize;
}
private void UpdateViewport()
{
var left = 0;
var top = 0;
var width = ClientSize.Width;
var height = ClientSize.Height;
if (_hScrollBar.Visible)
{
left = _hScrollBar.Value;
height -= _hScrollBar.Height;
}
if (_vScrollBar.Visible)
{
top = _vScrollBar.Value;
width -= _vScrollBar.Width;
}
Viewport = new Rectangle(left, top, width, height);
var pos = PointToClient(MousePosition);
_offsetMousePosition = new Point(pos.X + Viewport.Left, pos.Y + Viewport.Top);
Invalidate();
}
public void ScrollTo(Point point)
{
HScrollTo(point.X);
VScrollTo(point.Y);
}
public void VScrollTo(int value)
{
if (_vScrollBar.Visible)
_vScrollBar.Value = value;
}
public void HScrollTo(int value)
{
if (_hScrollBar.Visible)
_hScrollBar.Value = value;
}
public Point PointToView(Point point)
{
return new Point(point.X - Viewport.Left, point.Y - Viewport.Top);
}
public Rectangle RectangleToView(Rectangle rect)
{
return new Rectangle(new Point(rect.Left - Viewport.Left, rect.Top - Viewport.Top), rect.Size);
}
#endregion
}
}

View File

@ -0,0 +1,60 @@
using System.Drawing;
using System.Windows.Forms;
namespace DarkUI
{
public abstract class DarkScrollView : DarkScrollBase
{
#region Constructor Region
protected DarkScrollView()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw |
ControlStyles.UserPaint, true);
}
#endregion
#region Paint Region
protected abstract void PaintContent(Graphics g);
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
// Draw background
using (var b = new SolidBrush(BackColor))
{
g.FillRectangle(b, ClientRectangle);
}
// Offset the graphics based on the viewport, render the control contents, then reset it.
g.TranslateTransform(Viewport.Left * -1, Viewport.Top * -1);
PaintContent(g);
g.TranslateTransform(Viewport.Left, Viewport.Top);
// Draw the bit where the scrollbars meet
if (_vScrollBar.Visible && _hScrollBar.Visible)
{
using (var b = new SolidBrush(BackColor))
{
var rect = new Rectangle(_hScrollBar.Right, _vScrollBar.Bottom, _vScrollBar.Width,
_hScrollBar.Height);
g.FillRectangle(b, rect);
}
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// Absorb event
}
#endregion
}
}

View File

@ -41,6 +41,9 @@
<Compile Include="Config\Colors.cs" />
<Compile Include="Config\Consts.cs" />
<Compile Include="Config\Enums.cs" />
<Compile Include="Controls\DarkScrollBase.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Controls\DarkButton.cs">
<SubType>Component</SubType>
</Compile>