/*
* 本代码受中华人民共和国著作权法保护,作者仅授权下载代码之人在学习和交流范围内
* 自由使用与修改代码;欲将代码用于商业用途的,请与作者联系。
* 使用本代码请保留此处信息。作者联系方式:ping3108@163.com, 欢迎进行技术交流
*/
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
//忽略没有注释警告
#pragma warning disable 1591
namespace MGdu.WinFormUI
{
[ToolboxItem(false), DefaultEvent("ValueChanged")]
public abstract class GMScrollBarBase: GMBarControlBase, IGMControl
{
#region 类内部专用变量
const int MIN_MIDDLEBUTTON_LENGTH = 10;
const int TIMER_INTERVAL_SLOW = 400;
const int TIMER_INTERVAL_FAST = 50;
bool isMouseDownInMiddleButton;
CutePointAndValuePresenter presenter;
bool isMouseDownInSideButton;
LocationResult sideButtonDownWhere;
Point sideButtonDownPoint;
Point middleButtonMovePoint;
Timer mouseDownTimer;
bool middleButtonVisible;
WLButton wlSideButton1;
WLButton wlSideButton2;
WLButton wlMiddleButton;
private static readonly object EVENT_VALUECHANGED;
private static readonly object EVENT_THEMECHANGED;
#endregion
#region 内部专用属性
private int BlankSpaceLength
{
get
{
int sideBtnLen = ShowSideButtons ? SideButtonLength * 2 : 0;
return ScrollBarLength - InnerPaddingWidth * 2 - sideBtnLen -
MiddleButtonOutterSpace1 * 2;
}
}
private int ActualMovableSpaceLength
{
get
{
return BlankSpaceLength - MiddleButtonLength + 1;
}
}
#endregion
#region 内部私有方法
private LocationResult CheckLocation(Point p)
{
if(SideButton1Rect.Contains(p))
{
return LocationResult.SideButton1;
}
if(SideButton2Rect.Contains(p))
{
return LocationResult.SideButton2;
}
if(MiddleButtonRect.Contains(p) && middleButtonVisible)
{
return LocationResult.MiddleButton;
}
if(BeforeMdlBtnRect.Contains(p))
{
return LocationResult.BeforeMiddleButton;
}
if (AfterMdlBtnRect.Contains(p))
{
return LocationResult.AfterMiddleButton;
}
return LocationResult.NoWhere;
}
private void DoOnMouseDown(Point p)
{
LocationResult where = CheckLocation(p);
if (where == LocationResult.MiddleButton)
{
isMouseDownInMiddleButton = true;
middleButtonMovePoint = p;
wlMiddleButton.State = GMButtonState.Pressed;
}
else if (where != LocationResult.NoWhere)
{
isMouseDownInSideButton = true;
sideButtonDownWhere = where;
sideButtonDownPoint = p;
MouseDownSideButton(where);
mouseDownTimer.Enabled = true;
}
}
private void MouseDownSideButton(LocationResult where)
{
int delta = 0;
switch (where)
{
case LocationResult.SideButton1:
delta = - SmallChange;
wlSideButton1.State = GMButtonState.Pressed;
break;
case LocationResult.SideButton2:
wlSideButton2.State = GMButtonState.Pressed;
delta = SmallChange;
break;
case LocationResult.AfterMiddleButton:
delta = LargeChange;
break;
case LocationResult.BeforeMiddleButton:
delta = - LargeChange;
break;
}
if (delta != 0)
{
ValueAdd(delta);
}
}
private void DealMouseMoveWhenDownInSideButton(Point p)
{
sideButtonDownPoint = p;
}
private void DealMouseMoveWhenDownInMiddleButton(Point p)
{
if (IsVerticalBar)
{
if (p.Y < MiddleButtonBeginPositionDot || p.Y > (MiddleButtonMaxPositionDot + MiddleButtonLength))
return;
int delta = p.Y - middleButtonMovePoint.Y;
if (delta != 0)
this.DealMiddleButtonMove(delta);
middleButtonMovePoint = p;
}
else
{
if (p.X < MiddleButtonBeginPositionDot || p.X > (MiddleButtonMaxPositionDot + MiddleButtonLength))
return;
int delta = p.X - middleButtonMovePoint.X;
if (delta != 0)
this.DealMiddleButtonMove(delta);
middleButtonMovePoint = p;
}
}
private void MouseDownTimerHandler(object sender, EventArgs e)
{
if (mouseDownTimer.Interval != TIMER_INTERVAL_FAST)
mouseDownTimer.Interval = TIMER_INTERVAL_FAST;
if (sideButtonDownWhere == CheckLocation(sideButtonDownPoint))
{
MouseDownSideButton(sideButtonDownWhere);
}
}
private void ValueAdd(int amount)
{
int value = Value;
value += amount;
if (value < Minimum)
value = Minimum;
if (value > Maximum)
value = Maximum;
Value = value;
}
private void UpdateScrollInfo()
{
if (presenter == null)
return;
int valueCount = Maximum - Minimum + 1;
int pointCount = ActualMovableSpaceLength;
if (valueCount != presenter.ValueCount || pointCount != presenter.PointCount)
{
presenter.SetPointAndValueCount(pointCount, valueCount);
ResetMiddleButtonPosition();
base.Invalidate();
}
}
private void ResetMiddleButtonPosition()
{
int beginDot = MiddleButtonBeginPositionDot;
int p1, p2;
presenter.GetPointIndexFromValueIndex(Value - Minimum, out p1, out p2);
p1 += beginDot;
p2 += beginDot;
if (MiddleButtonCurrentPositionDot >= p1 && MiddleButtonCurrentPositionDot <= p2)
return;
if (Value == Maximum)
MiddleButtonCurrentPositionDot = p2;
else
MiddleButtonCurrentPositionDot = p1;
Invalidate();
}
private bool HasEnoughRoomForMiddleButton()
{
int lenForMBtn = ScrollBarLength - InnerPaddingWidth * 2 -
MiddleButtonOutterSpace1 * 2;
if (ShowSideButtons)
lenForMBtn -= SideButtonLength * 2;
return (lenForMBtn > MIN_MIDDLEBUTTON_LENGTH);
}
private void DoOnResize()
{
middleButtonVisible = HasEnoughRoomForMiddleButton() && base.Enabled;
wlSideButton1.Bounds = SideButton1Rect;
wlSideButton2.Bounds = SideButton2Rect;
wlMiddleButton.Bounds = MiddleButtonRect;
this.UpdateScrollInfo();
}
private void UpdateInfoToSideMiddleButton()
{
SetSideMdlBtnInfo();
DoOnResize();
Invalidate();
}
private void SetSideMdlBtnInfo()
{
wlSideButton1.ColorTable = SideButtonColorTable;
wlSideButton2.ColorTable = SideButtonColorTable;
wlMiddleButton.ColorTable = MiddleButtonColorTable;
wlSideButton1.ForePathGetter = SideButtonForePathGetter;
wlSideButton2.ForePathGetter = SideButtonForePathGetter;
wlSideButton1.ForePathSize = SideButtonForePathSize;
wlSideButton2.ForePathSize = SideButtonForePathSize;
wlSideButton1.HowForePathRender = HowSideButtonForePathDraw;
wlSideButton2.HowForePathRender = HowSideButtonForePathDraw;
wlSideButton1.BorderType = wlSideButton2.BorderType =
(_xtheme == null ? ButtonBorderType.Rectangle : _xtheme.SideButtonBorderType);
wlSideButton1.Radius = wlSideButton2.Radius =
(_xtheme == null ? 0 : _xtheme.SideButtonRadius);
wlMiddleButton.Radius = (_xtheme == null ? 0 : _xtheme.MiddleButtonRadius);
}
private void SetButtonState(Point p, GMButtonState newState)
{
wlMiddleButton.State = wlSideButton2.State = wlSideButton1.State = GMButtonState.Normal;
switch (CheckLocation(p))
{
case LocationResult.MiddleButton:
wlMiddleButton.State = newState;
break;
case LocationResult.SideButton1:
wlSideButton1.State = newState;
break;
case LocationResult.SideButton2:
wlSideButton2.State = newState;
break;
}
}
private void DealMiddleButtonMove(int moveDelta)
{
MiddleButtonCurrentPositionDot += moveDelta;
int v1, v2;
int locIndex = MiddleButtonCurrentPositionDot - MiddleButtonBeginPositionDot;
presenter.GetValueIndexFromPointIndex(locIndex, out v1, out v2);
if (MiddleButtonCurrentPositionDot == MiddleButtonMaxPositionDot)
{
Value = Minimum + v2;
}
else if (MiddleButtonCurrentPositionDot == MiddleButtonBeginPositionDot)
{
Value = Minimum + v1;
}
else
{
Value = Minimum + v1 + (v2 - v1) / 2;
}
}
#endregion
#region 内部绘图
private void PaintScrollBar(Graphics g)
{
if (DrawBackground)
{
RenderBackground(g);
}
if (middleButtonVisible)
{
wlMiddleButton.Bounds = MiddleButtonRect;
wlMiddleButton.DrawButton(g);
}
if (ShowSideButtons)
{
wlSideButton1.DrawButton(g);
wlSideButton2.DrawButton(g);
}
if (DrawBorder)
{
RenderBorders(g);
}
}
private void RenderBackground(Graphics g)
{
using (SolidBrush sb = new SolidBrush(GMBackColor))
{
g.FillRectangle(sb, ClientRectangle);
}
}
private void RenderMiddleButton(Graphics g)
{
Rectangle rect = MiddleButtonRect;
rect.Width--; rect.Height--;
g.DrawRectangle(Pens.Black, rect);
}
private void RenderBorders(Graphics g)
{
Rectangle rect = ClientRectangle;
rect.Width--;
rect.Height--;
using (Pen p = new Pen(BorderColor))
{
g.DrawRectangle(p, rect);
}
}
private void MiddleButtonExtraPaint(object sender, PaintEventArgs e)
{
if (!DrawLinesInMiddleButton)
return;
int linesLen = 8;
if (MiddleButtonLength < (linesLen + MiddleBtnLineOutterSpace1 * 2))
return;
Pen p1 = new Pen(MiddleButtonLine1Color);
Pen p2 = new Pen(MiddleButtonLine2Color);
Rectangle rect = e.ClipRectangle;
if (IsVerticalBar)
{
int x1 = rect.Left + MiddleBtnLineOutterSpace2;
int x2 = rect.Right - MiddleBtnLineOutterSpace2 - 1;
int y = rect.Top + (rect.Height - linesLen) / 2;
for (int i = 0; i < 3; i++)
{
e.Graphics.DrawLine(p1, x1, y, x2, y);
e.Graphics.DrawLine(p2, x1, y+1, x2, y+1);
y += 3;
}
}
else
{
int x = rect.Left + (rect.Width - linesLen) / 2;
int y1 = rect.Top + MiddleBtnLineOutterSpace2;
int y2 = rect.Bottom - MiddleBtnLineOutterSpace2 - 1;
for (int i = 0; i < 3; i++)
{
e.Graphics.DrawLine(p1, x, y1, x, y2);
e.Graphics.DrawLine(p2, x+1, y1, x+1, y2);
x += 3;
}
}
p1.Dispose();
p2.Dispose();
}
#endregion
#region 可通过XTheme配置的属性
protected int InnerPaddingWidth
{
get
{
if (_xtheme == null)
return 0;
else
return _xtheme.InnerPaddingWidth;
}
}
protected int MiddleButtonOutterSpace1
{
get
{
if (_xtheme == null)
return 1;
else
return _xtheme.MiddleButtonOutterSpace1;
}
}
protected int MiddleButtonOutterSpace2
{
get
{
if (_xtheme == null)
return 0;
else
return _xtheme.MiddleButtonOutterSpace2;
}
}
protected int SideButtonLength
{
get
{
if (_xtheme == null)
return 16;
else
return _xtheme.SideButtonLength;
}
}
protected bool DrawBackground
{
get
{
if (_xtheme == null)
return true;
else
return _xtheme.DrawBackground;
}
}
protected bool DrawBorder
{
get
{
if (_xtheme == null)
return false;
else
return _xtheme.DrawBorder;
}
}
protected bool DrawInnerBorder
{
get
{
if (_xtheme == null)
return false;
else
return _xtheme.DrawInnerBorder;
}
}
protected bool ShowSideButtons
{
get
{
if (_xtheme == null)
return true;
else
return _xtheme.ShowSideButtons;
}
}
protected Color GMBackColor
{
get
{
if (_xtheme == null)
return Color.FromArgb(227, 227, 227);
else
return _xtheme.BackColor;
}
}
protected Color BorderColor
{
get
{
if (_xtheme == null)
return Color.FromArgb(248, 248, 248);
else
return _xtheme.BorderColor;
}
}
protected Color InnerBorderColor
{
get
{
if (_xtheme == null)
return Color.Empty;
else
return _xtheme.InnerBorderColor;
}
}
protected Size SideButtonForePathSize
{
get
{
if (_xtheme == null)
return new Size(7, 7);
else
return _xtheme.SideButtonForePathSize;
}
}
protected ButtonForePathGetter SideButtonForePathGetter
{
get
{
if (_xtheme == null)
return new ButtonForePathGetter(
MGdu.WinFormUI.MyGraphics.GraphicsPathHelper.Create7x4In7x7DownTriangleFlag);
else
return _xtheme.SideButtonForePathGetter;
}
}
protected ButtonColorTable SideButtonColorTable
{
get
{
if (_xtheme == null)
return GetDefaultSideMdlBtnColor();
else
return _xtheme.SideButtonColorTable;
}
}
protected ButtonColorTable MiddleButtonColorTable
{
get
{
if (_xtheme == null)
return GetDefaultSideMdlBtnColor();
else
return _xtheme.MiddleButtonColorTable;
}
}
protected ForePathRenderMode HowSideButtonForePathDraw
{
get
{
if (_xtheme == null)
return ForePathRenderMode.Draw ;
else
return _xtheme.HowSideButtonForePathDraw;
}
}
protected bool DrawLinesInMiddleButton
{
get
{
if (_xtheme == null)
return true;
else
return _xtheme.DrawLinesInMiddleButton;
}
}
protected Color MiddleButtonLine1Color
{
get
{
if (_xtheme == null)
return Color.FromArgb(89, 89, 89);
else
return _xtheme.MiddleButtonLine1Color;
}
}
protected Color MiddleButtonLine2Color
{
get
{
if (_xtheme == null)
return Color.FromArgb(182, 182, 182);
else
return _xtheme.MiddleButtonLine2Color;
}
}
protected int MiddleBtnLineOutterSpace1
{
get
{
if (_xtheme == null)
return 4;
else
return _xtheme.MiddleBtnLineOutterSpace1;
}
}
protected int MiddleBtnLineOutterSpace2
{
get
{
if (_xtheme == null)
return 4;
else
return _xtheme.MiddleBtnLineOutterSpace2;
}
}
private ButtonColorTable GetDefaultSideMdlBtnColor()
{
ButtonColorTable table = new ButtonColorTable();
table.BorderColorNormal = Color.FromArgb(151, 151, 151);
table.BorderColorHover = Color.FromArgb(53, 111, 155);
table.BorderColorPressed = Color.FromArgb(60, 127, 177);
table.BackColorNormal = Color.FromArgb(217, 218, 219);
table.BackColorHover = Color.FromArgb(169, 219, 246);
table.BackColorPressed = Color.FromArgb(111, 202, 240);
table.ForeColorNormal = Color.FromArgb(73, 73, 73);
table.ForeColorHover = Color.FromArgb(32, 106, 145);
table.ForeColorPressed = Color.FromArgb(15, 38, 50);
table.ForeColorDisabled = SystemColors.ControlDarkDark;
table.BackColorDisabled = SystemColors.ControlDark;
return table;
}
#endregion
#region 子类可访问的Protected属性, 可重写的protected方法
protected int MiddleButtonLength
{
get
{
return Math.Max(MIN_MIDDLEBUTTON_LENGTH,
BlankSpaceLength * MiddleButtonLengthPercentage / 100);
}
}
protected int MiddleButtonMaxPositionDot
{
get
{
return MiddleButtonBeginPositionDot + ActualMovableSpaceLength - 1;
}
}
int _middleButtonCurrentPositionDot;
protected int MiddleButtonCurrentPositionDot
{
get
{
return _middleButtonCurrentPositionDot;
}
set
{
if (_middleButtonCurrentPositionDot == value)
return;
if (value > MiddleButtonMaxPositionDot)
_middleButtonCurrentPositionDot = MiddleButtonMaxPositionDot;
else if (value < MiddleButtonBeginPositionDot)
_middleButtonCurrentPositionDot = MiddleButtonBeginPositionDot;
else
_middleButtonCurrentPositionDot = value;
Invalidate();
}
}
///
/// 引发 ValueChanged 事件
///
///
protected virtual void OnValueChanged(EventArgs e)
{
EventHandler handler = (EventHandler)base.Events[EVENT_VALUECHANGED];
if (handler != null)
{
handler(this, e);
}
}
///
/// 引发 ThemeChanged 事件
///
///
protected virtual void OnThemeChanged(EventArgs e)
{
EventHandler handler = (EventHandler)base.Events[EVENT_THEMECHANGED];
if (handler != null)
{
handler(this, e);
}
}
#endregion
#region 留给子类(HScrollBar, VScrollBar)重写的属性
protected abstract int ScrollBarLength { get; }
protected abstract int MiddleButtonBeginPositionDot { get; }
protected abstract Rectangle SideButton1Rect { get; }
protected abstract Rectangle SideButton2Rect { get; }
protected abstract Rectangle MiddleButtonRect { get; }
protected abstract Rectangle BeforeMdlBtnRect { get; }
protected abstract Rectangle AfterMdlBtnRect { get; }
protected abstract ForePathRatoteDirection SideButton1RotateInfo { get; }
protected abstract ForePathRatoteDirection SideButton2RotateInfo { get; }
protected abstract bool IsVerticalBar { get; }
#endregion
#region IGMControl接口实现
[Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
public GMControlType ControlType
{
get { return GMControlType.ScrollBar; }
}
#endregion
#region 控件事件
public event EventHandler ValueChanged
{
add
{
base.Events.AddHandler(EVENT_VALUECHANGED, value);
}
remove
{
base.Events.RemoveHandler(EVENT_VALUECHANGED, value);
}
}
public event EventHandler ThemeChanged
{
add
{
base.Events.AddHandler(EVENT_THEMECHANGED, value);
}
remove
{
base.Events.RemoveHandler(EVENT_THEMECHANGED, value);
}
}
#endregion
#region 辅助公开属性的内部变量
int _maximum = 100;
int _minimum = 0;
int _value = 0;
int _smallChange = 1;
int _largeChange = 10;
int _middleButtonLengthPercentage = 10;
GMScrollBarThemeBase _xtheme;
#endregion
#region 公开属性
[Browsable(false),EditorBrowsable(EditorBrowsableState.Never)]
public GMScrollBarThemeBase XTheme
{
get
{
return this._xtheme;
}
set
{
if (this._xtheme == value)
return;
this._xtheme = value;
UpdateInfoToSideMiddleButton();
OnThemeChanged(EventArgs.Empty);
}
}
[DefaultValue(0)]
public int Value
{
get
{
return this._value;
}
set
{
if (this._value == value)
return;
if (value < Minimum || value > Maximum)
throw new ArgumentOutOfRangeException("Value");
this._value = value;
ResetMiddleButtonPosition();
OnValueChanged(EventArgs.Empty);
}
}
[DefaultValue(0), RefreshProperties(System.ComponentModel.RefreshProperties.Repaint)]
public int Minimum
{
get
{
return this._minimum;
}
set
{
if (this._minimum == value)
return;
if (value > this._maximum)
this._maximum = value;
if (this.Value < value)
this.Value = value;
this._minimum = value;
this.UpdateScrollInfo();
}
}
[DefaultValue(100), RefreshProperties(System.ComponentModel.RefreshProperties.Repaint)]
public int Maximum
{
get
{
return this._maximum;
}
set
{
if (this._maximum == value)
return;
if (value < this._minimum)
this._minimum = value;
if (this.Value > value)
this.Value = value;
this._maximum = value;
this.UpdateScrollInfo();
}
}
public int SmallChange
{
get
{
return _smallChange;
}
set
{
_smallChange = value < 1 ? 1 : value;
}
}
public int LargeChange
{
get
{
return _largeChange;
}
set
{
_largeChange = value < 1 ? 1 : value;
}
}
public int MiddleButtonLengthPercentage
{
get
{
return this._middleButtonLengthPercentage;
}
set
{
if (this._middleButtonLengthPercentage == value)
return;
if (value >= 5 && value <= 90)
{
this._middleButtonLengthPercentage = value;
}
else
{
if (value < 5)
this._middleButtonLengthPercentage = 5;
if (value > 90)
this._middleButtonLengthPercentage = 90;
}
this.UpdateScrollInfo();
}
}
#endregion
#region 构造函数及初始化
static GMScrollBarBase()
{
EVENT_VALUECHANGED = new object();
EVENT_THEMECHANGED = new object();
}
public GMScrollBarBase()
: base()
{
presenter = new CutePointAndValuePresenter();
ButtonsIni();
mouseDownTimer = new Timer();
mouseDownTimer.Enabled = false;
mouseDownTimer.Interval = TIMER_INTERVAL_SLOW;
mouseDownTimer.Tick += new EventHandler(MouseDownTimerHandler);
}
private void ButtonsIni()
{
wlSideButton1 = new WLButton(this);
wlSideButton2 = new WLButton(this);
wlMiddleButton = new WLButton(this);
wlSideButton1.RotateDirection = SideButton1RotateInfo;
wlSideButton2.RotateDirection = SideButton2RotateInfo;
wlSideButton1.RoundedType = wlSideButton2.RoundedType = MyGraphics.RoundStyle.All;
wlMiddleButton.RoundedType = MyGraphics.RoundStyle.All;
SetSideMdlBtnInfo();
wlMiddleButton.Paint += new PaintEventHandler(MiddleButtonExtraPaint);
}
#endregion
#region 重写方法
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
PaintScrollBar(e.Graphics);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
DoOnResize();
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
DoOnMouseDown(e.Location);
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
isMouseDownInMiddleButton = false;
isMouseDownInSideButton = false;
sideButtonDownWhere = LocationResult.NoWhere;
mouseDownTimer.Enabled = false;
mouseDownTimer.Interval = TIMER_INTERVAL_SLOW;
SetButtonState(e.Location, GMButtonState.Hover);
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (isMouseDownInSideButton)
{
DealMouseMoveWhenDownInSideButton(e.Location);
}
if (isMouseDownInMiddleButton)
{
DealMouseMoveWhenDownInMiddleButton(e.Location);
}
if (!isMouseDownInMiddleButton && !isMouseDownInSideButton)
{
SetButtonState(e.Location, GMButtonState.Hover);
}
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
wlMiddleButton.State = wlSideButton2.State = wlSideButton1.State = GMButtonState.Normal;
}
protected override void OnEnabledChanged(EventArgs e)
{
base.OnEnabledChanged(e);
wlSideButton2.Enabled = base.Enabled;
wlSideButton1.Enabled = base.Enabled;
middleButtonVisible = HasEnoughRoomForMiddleButton() && base.Enabled;
Invalidate();
}
#endregion
#region debug
//debuggggggggggggggggggggggggggggggggg
//ccccccccccccccccccccccccccccccccccccc
public void DebugEntry()
{
Console.WriteLine("BlankSpaceLength: " + BlankSpaceLength.ToString());
Console.WriteLine("MiddleButtonLength: " + MiddleButtonLength.ToString());
Console.WriteLine("MiddleButtonRect: " + MiddleButtonRect.ToString());
Console.WriteLine("ActualMovableSpaceLength: " + ActualMovableSpaceLength.ToString());
//XTheme.MiddleButtonOutterSpace1 = 2;
Console.WriteLine("MiddleButtonOutterSpace1: " + XTheme.MiddleButtonOutterSpace1.ToString());
Console.WriteLine("InnerPaddingWidth: " + XTheme.InnerPaddingWidth.ToString());
}
//debuggggggggggggggggggggggggggggggggggggggggggg
public CutePointAndValuePresenter GetPresenter()
{
return presenter;
}
#endregion
///
/// 指示鼠标位于哪个区域
///
private enum LocationResult
{
NoWhere,
SideButton1,
SideButton2,
MiddleButton,
BeforeMiddleButton,
AfterMiddleButton
}
}
}