就为long类型属性,写了个水平滚动条。
public partial public partial class HScrollbar : UserControl
{
public HScrollbar()
{
InitializeComponent();
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
MouseLeave += HScrollbar_MouseLeave;
}
#region 属性
public long Maximum = 0;
#endregion
public long BarOffset = 0;
public event System.Windows.Forms.ScrollEventHandler Scroll;
private bool IsShowBar = true;
private void HScrollbar_Paint(object sender, PaintEventArgs e)
{
AutoSize(Width, Height, ref IsShowBar);
Graphics g = e.Graphics;
g.Clear(Color.White);
SmoothingMode sm = g.SmoothingMode;
g.SmoothingMode = SmoothingMode.HighQuality;
g.FillRectangle(new SolidBrush(ColorBackground), rectBackground.Rectangle);
if (IsShowBar)
{
DrawBar(g);
}
g.FillRectangle(new SolidBrush(GetColorButtonBackgrond(rectLeft, IsBegin)), rectLeft.Rectangle);
g.FillRectangle(new SolidBrush(GetColorButtonBackgrond(rectRight, IsEnd)), rectRight.Rectangle);
DrawLeftArrow(g, GetColorArrow(true));
DrawRightArrow(g, GetColorArrow(false));
g.SmoothingMode = sm;
}
private bool IsBegin
{
get
{
long begin = 0;
bool bRet = begin == BarOffset;
return bRet;
}
}
private bool IsEnd
{
get
{
long end = (long)(MaxBarWidth - rectBar.Width);
bool bRet = end == BarOffset;
return bRet;
}
}
private Color GetColorArrow(bool isLeft)
{
if (IsShowBar && !IsBegin && isLeft && enumHitObject == EnumHitObject.HO_Left)
{
return ColorArrowButtonDown;
}
if (IsShowBar && !IsEnd && !isLeft && enumHitObject == EnumHitObject.HO_Right)
{
return ColorArrowButtonDown;
}
return ColorArrow;
}
private Color GetColorButtonBackgrond(Rect2 rect, bool stopFlag)
{
if (IsShowBar && !stopFlag && !IsMouseLevel && rect.Rectangle.Contains(PointMouse))
{
return ColorButtonMoveOn;
}
else
{
return ColorBackground;
}
}
private int SpaceWidth = 3;
private void AutoSize(int barWidth, int barHeight, ref bool showBar)
{
showBar = false;
int rectWidth = 12 + SpaceWidth;
//
rectBackground.Left = 0;
rectBackground.Top = 0;
rectBackground.Width = barWidth;
rectBackground.Height = barHeight;
//
rectLeft.Left = 0;
rectLeft.Top = 0;
rectLeft.Width = rectWidth;
rectLeft.Height = barHeight;
//
rectRight.Left = Right - rectWidth;
rectRight.Width = rectWidth;
rectRight.Top = 0;
rectRight.Height = barHeight;
//
rectCetner.Top = 0;
rectCetner.Height = barHeight;
rectCetner.Left = rectLeft.Right;
rectCetner.Width = rectRight.Left - rectCetner.Left;
double maxBarWidth = MaxBarWidth;
if (BarOffset > Maximum)
BarOffset = Maximum;
if (maxBarWidth > 0 && Maximum > maxBarWidth)
{
showBar = true;
}
double movemax = Maximum - rectBackground.Width;
float width = 20;
if (movemax >= 0 && movemax < maxBarWidth)
{
width = (float)(maxBarWidth - movemax);
}
float left = rectLeft.Right + PaddingBar + BarOffset;//(float)((double)Value / (double)Maximum * (rectBackground.Width));
rectBar.Top = Top + PaddingBar;
rectBar.Left = left;
rectBar.Width = width;
rectBar.Height = barHeight - 2 * PaddingBar - 1;
}
private Rect2 rectLeft = new Rect2();
private Rect2 rectRight = new Rect2();
private Rect2 rectCetner = new Rect2();
private Rect2 rectBackground = new Rect2();
private Rect2 rectBar = new Rect2();
private int PaddingBar = 2;
private int PaddingArrowX = 4;
private int PaddingArrowY = 4;
//配色
private Color ColorArrow = Color.FromArgb(163, 163, 163);
private Color ColorArrowButtonDown = Color.White;
private Color ColorBackground = Color.FromArgb(241, 241, 241);
private Color ColorButtonMoveOn = Color.FromArgb(210, 210, 210);
private Color ColorButtonDown = Color.FromArgb(120, 120, 120);
private Color ColorBar = Color.FromArgb(170, 170, 171);
private Color ColorBarButtonDown = Color.FromArgb(141, 141, 142);
private Color ColorBarBorder = Color.FromArgb(154, 154, 154);
private Brush brDebug = new SolidBrush(Color.Red);
private double MaxBarWidth
{
get
{
double maxBarWidth = rectBackground.Width - 2 * PaddingBar - rectLeft.Width - rectRight.Width;
return maxBarWidth;
}
}
private void DrawLeftArrow(Graphics g, Color color)
{
Rect2 rectArrow = new Rect2();
rectLeft.Copy(ref rectArrow);
rectArrow.InflateRect(-PaddingArrowX, -PaddingArrowY);
rectArrow.Height -= 1;
PointF pt0 = rectArrow.TopRight;
PointF pt1 = rectArrow.BottomRight;
PointF pt2 = rectArrow.LeftCenter;
pt0.X -= SpaceWidth;
pt1.X -= SpaceWidth;
GraphicsPath gPath = new GraphicsPath();
gPath.AddLine(pt0, pt1);
gPath.AddLine(pt1, pt2);
gPath.AddLine(pt2, pt0);
g.FillPath(new SolidBrush(color), gPath);
}
private void DrawRightArrow(Graphics g, Color color)
{
Rect2 rectArrow = new Rect2();
rectRight.Copy(ref rectArrow);
rectArrow.InflateRect(-PaddingArrowX, -PaddingArrowY);
rectArrow.Height -= 1;
//g.FillRectangle(brDebug, rectArrow.Rectangle);
PointF pt0 = rectArrow.TopLeft;
PointF pt1 = rectArrow.BottomLeft;
PointF pt2 = rectArrow.RightCenter;
pt0.X += SpaceWidth;
pt1.X += SpaceWidth;
GraphicsPath gPath = new GraphicsPath();
gPath.AddLine(pt0, pt1);
gPath.AddLine(pt1, pt2);
gPath.AddLine(pt2, pt0);
g.FillPath(new SolidBrush(color), gPath);
}
private void DrawBar(Graphics g)
{
g.FillRectangle(new SolidBrush(GetColorBar()), rectBar.Rectangle);
g.DrawRectangle(new Pen(new SolidBrush(ColorBarBorder)), rectBar.Rectangle);
}
private Color GetColorBar()
{
if (enumHitObject == EnumHitObject.HO_Bar)
{
return ColorBarButtonDown;
}
else
{
return ColorBar;
}
}
private enum EnumHitObject
{
HO_None,
HO_Left,
HO_Right,
HO_Bar,
HO_BarSpace
}
private EnumHitObject enumHitObject = EnumHitObject.HO_None;
private EnumHitObject HitTest(Point pointMouse)
{
EnumHitObject ho = EnumHitObject.HO_None;
if (rectLeft.Rectangle.Contains(pointMouse))
{
ho = EnumHitObject.HO_Left;
}
else if (rectRight.Rectangle.Contains(pointMouse))
{
ho = EnumHitObject.HO_Right;
}
else if (rectBar.Rectangle.Contains(pointMouse))
{
ho = EnumHitObject.HO_Bar;
}
else if (rectBackground.Rectangle.Contains(pointMouse))
{
ho = EnumHitObject.HO_BarSpace;
}
return ho;
}
private DateTime LButtonDownTime = DateTime.Now;
private Point LButtonDownMousePoint = new Point();
private void HScrollbar_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Point ptMouse = new Point(e.X, e.Y);
enumHitObject = HitTest(ptMouse);
LButtonDownMousePoint.X = e.X;
LButtonDownMousePoint.Y = e.Y;
LButtonDownTime = DateTime.Now;
switch (enumHitObject)
{
case EnumHitObject.HO_BarSpace:
{
SetBarOffset(e.X);
}
break;
}
}
}
private void SetBarOffset(long screenPixcel)
{
screenPixcel = (long)(screenPixcel - rectLeft.Right - PaddingBar);
if (screenPixcel <= 0)
{
screenPixcel = 0;
}
if (screenPixcel >= (MaxBarWidth - rectBar.Width))
{
screenPixcel = (long)(MaxBarWidth - rectBar.Width);
}
BarOffset = screenPixcel;
}
private Point PointMouse = new Point();
private bool IsMouseLevel = true;
private void HScrollbar_MouseLeave(object sender, EventArgs e)
{
IsMouseLevel = true;
}
private void HScrollbar_MouseMove(object sender, MouseEventArgs e)
{
PointMouse.X = e.X;
PointMouse.Y = e.Y;
IsMouseLevel = false;
if (enumHitObject == EnumHitObject.HO_Bar
|| enumHitObject == EnumHitObject.HO_BarSpace && e.Button == System.Windows.Forms.MouseButtons.Left)
{
SetBarOffset(e.X);
Debug();
}
}
private void HScrollbar_MouseUp(object sender, MouseEventArgs e)
{
enumHitObject = EnumHitObject.HO_None;
}
private void timer1_Tick(object sender, EventArgs e)
{
long step = Maximum / 20;
double ms = (DateTime.Now - LButtonDownTime).TotalMilliseconds;
if (ms > 200)
{
step = Maximum / 10;
}
long newValue = Value;
if (enumHitObject == EnumHitObject.HO_Left)
{
newValue -= step;
Value = newValue;
}
else if (enumHitObject == EnumHitObject.HO_Right)
{
newValue += step;
Value = newValue;
}
Invalidate();
}
public int SliderWidth//滑块宽度
{
get
{
return (int)rectBar.Width;
}
}
private double MaxValue
{
get
{
double maxValue = (double)(Maximum - rectBackground.Width);
if (maxValue < 0)
maxValue = 0;
return maxValue;
}
}
public long Value
{
get
{
double maxPixcel = (double)(MaxBarWidth - rectBar.Width);
double maxValue = MaxValue;
//像素转值
long value = (long)((double)BarOffset * maxValue / maxPixcel + 0.5d);
return value;
}
set
{
double maxPixcel = (double)(MaxBarWidth - rectBar.Width);
double maxValue = MaxValue;
double v = value;
if (v < 0)
{
v = 0;
}
if (v > maxValue && maxValue >= 0)
v = maxValue;
//值转像素
BarOffset = (long)(v * maxPixcel / maxValue + 0.5d);
if (BarOffset < 0)
BarOffset = 0;
Debug();
}
}
private void Debug()
{
System.Console.WriteLine(string.Format("Begin:{0},End:{1}", Value, Value + rectBackground.Width));
}
private int PrevWidth = 0;
private int PrevHeight = 0;
private void HScrollbar_Resize(object sender, EventArgs e)
{
bool isShowbar = false;
AutoSize(PrevWidth, PrevHeight, ref isShowbar);
double prevMaxBarWidth = MaxBarWidth - rectBar.Width;
AutoSize(Width, Height, ref isShowbar);
double maxBarWidth = MaxBarWidth - rectBar.Width;
double xscale = BarOffset / (double)prevMaxBarWidth;
double screenPixcel = xscale * maxBarWidth + rectLeft.Right + PaddingBar;
if (double.IsNaN(screenPixcel))
{
SetBarOffset(0);
}
else
{
SetBarOffset((long)screenPixcel);
}
PrevWidth = Width;
PrevHeight = Height;
Debug();
}
}
public class Rect2
{
public float Left = 0;
public float Width = 0;
public float Top = 0;
public float Height = 0;
public Rect2()
{
}
public static void TestDraw(Graphics g, RectangleF rect)
{
g.FillRectangle(new SolidBrush(Color.Gray), rect);
}
public Rect2(float Left, float Top, float Width, float Height)
{
this.Left = Left;
this.Width = Width;
this.Top = Top;
this.Height = Height;
}
#region 点
public float Right
{
get
{
return Left + Width;
}
}
public float Bottom
{
get
{
return Top + Height;
}
}
public PointF TopLeft
{
get
{
PointF pt = new PointF(Left, Top);
return pt;
}
}
public PointF TopRight
{
get
{
PointF pt = new PointF(Right, Top);
return pt;
}
}
public PointF BottomLeft
{
get
{
PointF pt = new PointF(Left, Bottom);
return pt;
}
}
public PointF BottomRight
{
get
{
PointF pt = new PointF(Right, Bottom);
return pt;
}
}
public PointF Center
{
get
{
PointF pt = new PointF(Left + Width / 2.0f, Top + Height / 2.0f);
return pt;
}
}
public PointF LeftCenter
{
get
{
PointF pt = new PointF(Left, Top + Height / 2.0f);
return pt;
}
}
public PointF RightCenter
{
get
{
PointF pt = new PointF(Right, Top + Height / 2.0f);
return pt;
}
}
public PointF TopCenter
{
get
{
PointF pt = new PointF(Left + Width / 2.0f, Top);
return pt;
}
}
public PointF BottomCenter
{
get
{
PointF pt = new PointF(Left + Width / 2.0f, Bottom);
return pt;
}
}
public RectangleF RectangleF
{
get
{
RectangleF rect = new RectangleF(Left, Top, Width, Height);
return rect;
}
}
public Rectangle Rectangle
{
get
{
Rectangle rect = new Rectangle((int)Left, (int)Top, (int)Width, (int)Height);
return rect;
}
}
public void Set(RectangleF rect)
{
this.Left = rect.X;
this.Width = rect.Width;
this.Top = rect.Y;
this.Height = rect.Height;
}
public void InflateRect(float x, float y)
{
Left -= x;
Width += 2 * x;
Top -= y;
Height += 2 * y;
}
public void Copy(ref Rect2 rect)
{
rect.Left = Left;
rect.Top = Top;
rect.Width = Width;
rect.Height = Height;
}
#endregion
#region 计算矩形位置
public enum EnumPosition
{
EnumPosition_Center,
EnumPosition_LeftCenter,
EnumPosition_RightCenter,
EnumPosition_TopCenter,
EnumPosition_BottomCenter
}
public static Rect2 Postion(PointF point, SizeF sz, EnumPosition enumPostion)
{
Rect2 rect = new Rect2();
switch (enumPostion)
{
case EnumPosition.EnumPosition_LeftCenter:
rect = new Rect2(point.X - sz.Width, point.Y - sz.Height / 2.0f, sz.Width, sz.Height);
break;
case EnumPosition.EnumPosition_RightCenter:
rect = new Rect2(point.X, point.Y - sz.Height / 2.0f, sz.Width, sz.Height);
break;
case EnumPosition.EnumPosition_TopCenter:
rect = new Rect2(point.X - sz.Width / 2.0f, point.Y - sz.Height, sz.Width, sz.Height);
break;
case EnumPosition.EnumPosition_BottomCenter:
rect = new Rect2(point.X - sz.Width / 2.0f, point.Y, sz.Width, sz.Height);
break;
case EnumPosition.EnumPosition_Center:
rect = new Rect2(point.X - sz.Width / 2.0f, point.Y - sz.Height / 2.0f, sz.Width, sz.Height);
break;
}
return rect;
}
#endregion
}