目录
预览
1,使用Graphics绘制Toggle。
效果:
测试代码:
private void toggle3_Click(object sender, EventArgs e)
{
toggle3.Checked = !toggle3.Checked;
}
private void toggle2_Click(object sender, EventArgs e)
{
toggle2.Checked = !toggle2.Checked;
}
private void toggle1_Click(object sender, EventArgs e)
{
toggle1.Checked = !toggle1.Checked;
}
Toggle控件代码:
[DefaultEvent("Click")]//指定默认事件
public partial class Toggle : UserControl
{
public Toggle()
{
InitializeComponent();
设置控件样式
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
string falseText = "关闭";
[Browsable(true), Category("自定义属性"), Description("false时文本")]
public string FalseText
{
get
{
return falseText;
}
set
{
falseText = value;
this.Invalidate();
}
}
string trueText = "打开";
[Browsable(true), Category("自定义属性"), Description("true时文本")]
public string TrueText
{
get
{
return trueText;
}
set
{
trueText = value;
this.Invalidate();
}
}
bool _checked = false;
[Browsable(true), Category("自定义属性"), Description("是否确认,Ture表示ON,False表示OFF")]
public bool Checked
{
get
{
return _checked;
}
set
{
_checked = value;
this.Invalidate();
}
}
bool isShowWord = false;
[Browsable(true), Category("自定义属性"), Description("是否显示文字,如果否则显示形状")]
public bool IsShowWord
{
get
{
return isShowWord;
}
set
{
isShowWord = value;
this.Invalidate();
}
}
Color falseColor = Color.LightGray;
[Browsable(true), Category("自定义属性"), Description("False状态时填充色")]
public Color FalseColor
{
get
{
return falseColor;
}
set
{
falseColor = value;
this.Invalidate();
}
}
Color trueColor = Color.CadetBlue;
[Browsable(true), Category("自定义属性"), Description("True状态时填充色")]
public Color TrueColor
{
get
{
return trueColor;
}
set
{
trueColor = value;
this.Invalidate();
}
}
[Browsable(true), Category("自定义属性"), Description("若为非文字模式时,圆点的半径")]
public int EmbellishRadius
{
get
{
return (int)(EmbellishRadiusFactor * Height);
}
}
float _embellishRadiusFactor = 0.15f;
[Browsable(true), Category("自定义属性"), Description("若为非文字模式时,圆点的比例因子")]
public float EmbellishRadiusFactor
{
set
{
if (value >= 1 || value <= 0)
{
_embellishRadiusFactor = 0.3f;
}
else
{
_embellishRadiusFactor = value;
}
this.Invalidate();
}
get
{
return _embellishRadiusFactor;
}
}
bool _embellishPointAuto = true;
[Browsable(true), Category("自定义属性"), Description("修饰文字或者图形的起点是否自动获取")]
public bool EmbellishPointAuto
{
get
{
return _embellishPointAuto;
}
set
{
_embellishPointAuto = value;
this.Invalidate();
}
}
PointF _embellishPoint;
[Browsable(true), Category("自定义属性"), Description("绘制修饰文字或者图形所需的起点")]
public PointF EmbellishPoint
{
get
{
return _embellishPoint;
}
set
{
_embellishPoint = value;
if (!EmbellishPointAuto)
{
this.Invalidate();
}
}
}
Color _embellishColor = Color.White;
[Browsable(true), Category("自定义属性"), Description("绘制修饰文字或者图形所需的颜色")]
public Color EmbellishColor
{
get
{
return _embellishColor;
}
set
{
_embellishColor = value;
this.Invalidate();
}
}
ToggleType _toggleType = ToggleType.Rectangle;
[Browsable(true), Category("自定义属性"), Description("Toggle的样式")]
public ToggleType ToggleStyle
{
get
{
return _toggleType;
}
set
{
_toggleType = value;
this.Invalidate();
}
}
Padding _borderRadius = new Padding(3);
[Browsable(true), Category("自定义属性"), Description("Rectangle风格时采用的倒角半径")]
public Padding BorderRadius
{
get
{
return _borderRadius;
}
set
{
_borderRadius = value;
if (ToggleStyle == ToggleType.Rectangle)
{
this.Invalidate();
}
}
}
int _innerGap = 3;
[Browsable(true), Category("自定义属性"), Description("内部间隙")]
public int InnerGap
{
get
{
return _innerGap;
}
set
{
_innerGap = value;
this.Invalidate();
}
}
Color _slidingColor = Color.White;
[Browsable(true), Category("自定义属性"), Description("滑动块颜色")]
public Color SlidingColor
{
get
{
return _slidingColor;
}
set
{
_slidingColor = value;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
GraphicsPath path = new GraphicsPath();
Padding drawingRadius;
if (ToggleStyle == ToggleType.Ellipse)
{
drawingRadius = new Padding(Height / 2);
}
else
{
drawingRadius = BorderRadius;
}
//绘制矩形
//左上角
path.AddArc(0, 0, drawingRadius.Left * 2, drawingRadius.Left * 2, 180, 90);
//右上角
path.AddArc(Width - drawingRadius.Top * 2, 0, drawingRadius.Top * 2, drawingRadius.Top * 2, 270, 90);
//右下角
path.AddArc(Width - drawingRadius.Right * 2, Height - drawingRadius.Right * 2, drawingRadius.Right * 2, drawingRadius.Right * 2, 0, 90);
//左下角
path.AddArc(0, Height - 2 * drawingRadius.Bottom, 2 * drawingRadius.Bottom, 2 * drawingRadius.Bottom, 90, 90);
//滑动块起点
Point slidingPoint;
if (Checked)
{
g.FillPath(new SolidBrush(TrueColor), path);
slidingPoint = new Point(Width - Height + InnerGap, InnerGap);
//如果是文字模式
if (IsShowWord && EmbellishPointAuto)
{
SizeF trueTextSize = g.MeasureString(TrueText, this.Font);
EmbellishPoint = new PointF(((Width - trueTextSize.Width - Height)) / 2, ((Height - trueTextSize.Height)) / 2);
}
//如果是非文字模式
if (!IsShowWord && EmbellishPointAuto)
{
EmbellishPoint = new PointF(Height / 2 - EmbellishRadius, Height / 2 - EmbellishRadius);
}
}
else
{
g.FillPath(new SolidBrush(FalseColor), path);
slidingPoint = new Point(InnerGap, InnerGap);
//如果是文字模式
if (IsShowWord && EmbellishPointAuto)
{
SizeF falseTextSize = g.MeasureString(FalseText, this.Font);
EmbellishPoint = new PointF(Height + (Width - Height - falseTextSize.Width) / 2, ((Height - falseTextSize.Height)) / 2);
}
//如果是非文字模式
if (!IsShowWord && EmbellishPointAuto)
{
EmbellishPoint = new Point(Width - (Height / 2 + EmbellishRadius / 2), Height / 2 - EmbellishRadius);
}
}
int slidingWidth = Height - 2 * InnerGap;
GraphicsPath path2 = new GraphicsPath(FillMode.Alternate);
int slidingHeight = slidingWidth;
float scale = slidingWidth * 1.0f / Width;
if (ToggleStyle == ToggleType.Rectangle)
{
//左上角
path2.AddArc(slidingPoint.X, slidingPoint.Y, drawingRadius.Left * 2, drawingRadius.Left * 2, 180, 90);
//右上角
path2.AddArc(slidingPoint.X + slidingWidth - drawingRadius.Top * 2, slidingPoint.Y, drawingRadius.Top * 2, drawingRadius.Top * 2, 270, 90);
//右下角
path2.AddArc(slidingPoint.X + slidingWidth - drawingRadius.Right * 2, slidingPoint.Y + slidingHeight - drawingRadius.Right * 2, drawingRadius.Right * 2, drawingRadius.Right * 2, 0, 90);
//左下角
path2.AddArc(slidingPoint.X, slidingPoint.Y + slidingHeight - 2 * drawingRadius.Bottom, 2 * drawingRadius.Bottom, 2 * drawingRadius.Bottom, 90, 90);
}
else
{
path2.AddEllipse(slidingPoint.X, slidingPoint.Y, Height - 2 * InnerGap, Height - 2 * InnerGap);
}
g.FillPath(new SolidBrush(SlidingColor), path2);
if (IsShowWord)
{
if (Checked)
{
g.DrawString(TrueText, this.Font, new SolidBrush(this.EmbellishColor), EmbellishPoint);
}
else
{
g.DrawString(FalseText, this.Font, new SolidBrush(this.EmbellishColor), EmbellishPoint);
}
}
else
{
g.DrawEllipse(new Pen(EmbellishColor, 2), new RectangleF(EmbellishPoint, new SizeF(EmbellishRadius * 2, EmbellishRadius * 2)));
}
}
}
public enum ToggleType
{
/// <summary>
/// 矩形形状
/// </summary>
Rectangle,
/// <summary>
/// 椭圆形状
/// </summary>
Ellipse
}
2,使用Graphics绘制Switch。
效果:
测试代码:
private void switchControl1_Click(object sender, EventArgs e)
{
switchControl1.SwitchStatus = !switchControl1.SwitchStatus;
}
Switch控件代码:
[DefaultEvent("Click")]
public partial class SwitchControl : UserControl
{
public SwitchControl()
{
InitializeComponent();
设置控件样式
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
int _outGap = 20;
/// <summary>
/// 外间隙
/// </summary>
[Browsable(true),Category("自定义属性"),Description("外间隙")]
public int OutCap
{
get
{
return _outGap;
}
set
{
if (_outGap < 0)
{
_outGap = 0;
}
else
{
_outGap = value;
}
this.Invalidate();
}
}
int _innerGap = 3;
/// <summary>
/// 内间隙
/// </summary>
[Browsable(true), Category("自定义属性"), Description("内间隙")]
public int InnerCap
{
get
{
return _innerGap;
}
set
{
if (_innerGap < 0)
{
_innerGap = 0;
}
else
{
_innerGap = value;
}
this.Invalidate();
}
}
bool _switchStatus = false;
/// <summary>
/// 开关状态
/// </summary>
[Browsable(true), Category("自定义属性"), Description("开关状态")]
public bool SwitchStatus
{
get
{
return _switchStatus;
}
set
{
_switchStatus = value;
this.Invalidate();
}
}
int _outCircleWidth = 4;
/// <summary>
/// 外圆宽度
/// </summary>
[Browsable(true), Category("自定义属性"), Description("外圆宽度")]
public int OutCircleWidth
{
get
{
return _outCircleWidth;
}
set
{
if (_outCircleWidth < 0)
{
_outCircleWidth = 2;
}
else
{
_outCircleWidth = value;
}
this.Invalidate();
}
}
Color _outCircleColor = Color.Gray;
/// <summary>
/// 外圆颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("外圆颜色")]
public Color OutCircleColor
{
get
{
return _outCircleColor;
}
set
{
_outCircleColor = value;
this.Invalidate();
}
}
Color _innerCircleColor = Color.Gray;
/// <summary>
/// 外圆颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("内圆颜色")]
public Color InnerCircleColor
{
get
{
return _innerCircleColor;
}
set
{
_innerCircleColor = value;
this.Invalidate();
}
}
/// <summary>
///旋转手柄宽度
/// </summary>
[Browsable(true), Category("自定义属性"), Description("旋转手柄宽度")]
public float HandleWidth
{
get
{
return Dimensions*HandleWidthFactor;
}
}
float _handleWidthFactor = 0.1f;
/// <summary>
///旋转手柄宽度比例因子
/// </summary>
[Browsable(true), Category("自定义属性"), Description("旋转手柄宽度比例因子")]
public float HandleWidthFactor
{
get
{
return _handleWidthFactor;
}
set
{
if (_handleWidthFactor < 0)
{
_handleWidthFactor = 0.15f;
}
else
{
_handleWidthFactor = value;
}
this.Invalidate();
}
}
Color _embellishColor = Color.Orange;
/// <summary>
/// 手柄标记颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("手柄标记颜色")]
public Color EmbellishColor
{
get
{
return _embellishColor;
}
set
{
_embellishColor = value;
this.Invalidate();
}
}
Color _handleColor = Color.Black;
/// <summary>
/// 手柄颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("手柄颜色")]
public Color HandleColor
{
get
{
return _handleColor;
}
set
{
_handleColor = value;
this.Invalidate();
}
}
/// <summary>
/// 绘图的标准尺寸
/// </summary>
private int Dimensions
{
get
{
if (Width > Height)
{
return Height;
}
else
{
return Width;
}
}
}
float _sweep = 36;
/// <summary>
/// 手柄旋转角度
/// </summary>
[Browsable(true), Category("自定义属性"), Description("手柄旋转角度")]
public float Sweep
{
get
{
return _sweep;
}
set
{
_sweep = value;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
//绘制外圆
g.DrawEllipse(new Pen(OutCircleColor, OutCircleWidth), OutCap, OutCap, this.Dimensions - 2 * OutCap, Dimensions - 2 * OutCap);
//绘制内圆
Point innerPoint = new Point(OutCap + OutCircleWidth + InnerCap, OutCap + OutCircleWidth + InnerCap);
int innerWidth = Dimensions - 2 * innerPoint.X ;
g.FillEllipse(new SolidBrush(InnerCircleColor), innerPoint.X, innerPoint.Y, innerWidth, innerWidth);
//偏移原点
g.TranslateTransform(Dimensions / 2, Dimensions / 2);
//旋转角度
if (SwitchStatus)
{
g.RotateTransform(Sweep);
}
else
{
g.RotateTransform(-Sweep);
}
//绘制手柄
g.FillRectangle(new SolidBrush(HandleColor), -HandleWidth/2, (-Dimensions + OutCap)/2, HandleWidth, Dimensions - OutCap);
//绘制手柄标志
float embellishWidth = HandleWidth / 2;
float embellishHeight = HandleWidth * 1.5f;
g.FillEllipse(new SolidBrush(EmbellishColor), -embellishWidth / 2, (-Dimensions + OutCap) / 2 + embellishWidth / 2, embellishWidth, embellishHeight);
}
}
3,使用Graphics绘制PanelHead。
效果
可设置边框颜色,有无,Header文字,Header高度,背景色等,以及Dock类型
PanelHead控件代码:
public partial class PanelHead : Panel
{
public PanelHead()
{
InitializeComponent();
// 设置控件样式
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
private Color _headerBackgroundColor = Color.SkyBlue;
[Browsable(true), Category("自定义属性"), Description("Header背景色")]
public Color HeaderBackgroundColor
{
get { return _headerBackgroundColor; }
set
{
_headerBackgroundColor = value;
this.Invalidate();
}
}
private int _headerHeight = 40;
[Browsable(true), Category("自定义属性"), Description("Header高度")]
public int HeaderHeight
{
get { return _headerHeight; }
set
{
_headerHeight = value;
this.Invalidate();
}
}
private Color _headerForeColor = Color.Black;
[Browsable(true), Category("自定义属性"), Description("Header前景色")]
public Color HeaderForeColor
{
get { return _headerForeColor; }
set
{
_headerForeColor = value;
this.Invalidate();
}
}
private string _headerText="标题";
[Browsable(true), Category("自定义属性"), Description("Header前景色")]
public string HeaderText
{
get { return _headerText; }
set
{
_headerText = value;
this.Invalidate();
}
}
private Font _headerFont = DefaultFont;
[Browsable(true), Category("自定义属性"), Description("Header文字字体")]
public Font HeaderFont
{
get { return _headerFont; }
set
{
_headerFont = value;
this.Invalidate();
}
}
private StringAlignment _headerTextAlignment = StringAlignment.Center;
[Browsable(true), Category("自定义属性"), Description("Header文字水平对齐方式")]
public StringAlignment HeaderTextAlignment
{
get { return _headerTextAlignment; }
set
{
_headerTextAlignment = value;
this.Invalidate();
}
}
private StringAlignment _headerTextLineAlignment = StringAlignment.Center;
[Browsable(true), Category("自定义属性"), Description("Header文字垂直对齐方式")]
public StringAlignment HeaderTextLineAlignment
{
get { return _headerTextLineAlignment; }
set
{
_headerTextLineAlignment = value;
this.Invalidate();
}
}
private bool _hasBorder = true;
[Browsable(true), Category("自定义属性"), Description("是否有外边框")]
public bool HasBorder
{
get { return _hasBorder; }
set
{
_hasBorder = value;
this.Invalidate();
}
}
private Color _borderColor = Color.Black;
[Browsable(true), Category("自定义属性"), Description("外边框颜色")]
public Color BorderColor
{
get { return _borderColor; }
set
{
_borderColor = value;
this.Invalidate();
}
}
private int _borderWidth = 1;
[Browsable(true), Category("自定义属性"), Description("外边框的宽度")]
public int BorderWidth
{
get { return _borderWidth; }
set
{
_borderWidth = value;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias; //使绘图质量最高,即消除锯齿
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.FillRectangle(new SolidBrush(HeaderBackgroundColor), OriginPoint.X, OriginPoint.Y, DimensionsWidth, HeaderHeight);
StringFormat format = new StringFormat()
{
Alignment = this.HeaderTextAlignment,
LineAlignment = HeaderTextLineAlignment
};
g.DrawString(HeaderText, HeaderFont, new SolidBrush(HeaderForeColor), new RectangleF(OriginPoint.X, OriginPoint.Y, DimensionsWidth, HeaderHeight), format);
//绘制边框
if (HasBorder)
{
g.DrawRectangle(new Pen(BorderColor, BorderWidth), BorderWidth / 2, BorderWidth / 2, Width - BorderWidth, Height - BorderWidth);
}
}
int DimensionsWidth
{
get
{
if (HasBorder)
{
return Width - BorderWidth-2;
}
return Width;
}
}
int DimensionsHeight
{
get
{
if (HasBorder)
{
return Height - BorderWidth-2;
}
return Height;
}
}
Point OriginPoint
{
get
{
if (HasBorder)
{
return new Point(BorderWidth, BorderWidth);
}
return new Point(0, 0);
}
}
Dictionary<Control, Rectangle> dic = new Dictionary<Control, Rectangle>();
int flag = 0xff;
protected override void OnLayout(LayoutEventArgs e)
{
if (HasChildren)
{
foreach (Control item in this.Controls)
{
switch (item.Dock)
{
case DockStyle.None:
item.SuspendLayout();
if (dic.ContainsKey(item) && !((flag & 0x1) == 1))
{
item.Bounds = dic[item];
flag = 0xff;
}
item.ResumeLayout();
// base.OnLayout(e);
break;
case DockStyle.Top:
if ((flag & 0x1) == 1)
{
dic[item] = item.Bounds;
flag = flag & 0xfe;
}
if ((flag & 0x2) == 2)
{
item.Bounds = dic[item];
flag = flag & 0xfd;
}
item.SuspendLayout();
if (item.Height <= DimensionsHeight - HeaderHeight)
{
item.SetBounds(OriginPoint.X, OriginPoint.Y + HeaderHeight, DimensionsWidth, item.Height);
}
else
{
item.SetBounds(OriginPoint.X, OriginPoint.Y + HeaderHeight, DimensionsWidth, DimensionsHeight - HeaderHeight);
}
break;
case DockStyle.Bottom:
if ((flag & 0x1) == 1)
{
dic[item] = item.Bounds;
flag = flag & 0xfe;
}
if ((flag & 0x4) == 4)
{
item.Bounds = dic[item];
flag = flag & 0xfb;
}
item.SuspendLayout();
if (item.Height <= DimensionsHeight - HeaderHeight)
{
item.SetBounds(OriginPoint.X,OriginPoint.Y+ DimensionsHeight -item.Height, DimensionsWidth, item.Height);
}
else
{
item.SetBounds(OriginPoint.X, OriginPoint.Y + HeaderHeight, DimensionsWidth, DimensionsHeight - HeaderHeight);
}
break;
case DockStyle.Left:
if ((flag & 0x1) == 1)
{
dic[item] = item.Bounds;
flag = flag & 0xfe;
}
if ((flag & 0x8) == 8)
{
item.Bounds = dic[item];
flag = flag & 0xf7;
}
item.SuspendLayout();
if (item.Width <= DimensionsWidth)
{
item.SetBounds(OriginPoint.X, OriginPoint.Y + HeaderHeight, item.Width, DimensionsHeight - HeaderHeight);
}
else
{
item.SetBounds(OriginPoint.X, OriginPoint.Y + HeaderHeight, DimensionsWidth, Height - HeaderHeight);
}
break;
case DockStyle.Right:
if ((flag & 0x1) == 1)
{
dic[item] = item.Bounds;
flag = flag & 0xfe;
}
if ((flag & 0x10) == 16)
{
item.Bounds = dic[item];
flag = flag & 0xef;
}
item.SuspendLayout();
if (item.Width <= DimensionsWidth)
{
item.SetBounds(OriginPoint.X + DimensionsWidth - item.Width, OriginPoint.Y + HeaderHeight, item.Width, DimensionsHeight - HeaderHeight);
}
else
{
item.SetBounds(OriginPoint.X, OriginPoint.Y + HeaderHeight, DimensionsWidth, Height - HeaderHeight);
}
break;
case DockStyle.Fill:
if ((flag & 0x1) == 1)
{
dic[item] = item.Bounds;
flag = flag & 0xfe;
}
item.SuspendLayout();
item.SetBounds(OriginPoint.X, OriginPoint.Y + HeaderHeight, DimensionsWidth, DimensionsHeight - HeaderHeight);
break;
default:
break;
}
}
}
}
}
4,自定义数字键盘NumberKeyBoard。
效果:
测试代码:
public Form2()
{
InitializeComponent();
//接收输入完成的数据
numKeyBoard1.InputCompleted += NumKeyBoard1_InputCompleted1;
//Esc事件
numKeyBoard1.InputCancel += NumKeyBoard1_InputCancel;
}
private void Form2_Load(object sender, EventArgs e)
{
//注册哪些控件使用数字键盘,通过控件名进行注册,如果不注册将无数字键盘弹出
numKeyBoard1.RegisterNumberKeyBoard(new string[] { "textBox1", "textBox2", "textBox3" });
}
private void NumKeyBoard1_InputCancel(object sender, EventArgs e)
{
//键盘的打开是通过目的控件的GotFocus事件完成如果不将焦点转移到其他控件,将影响在该目的控件上重复打开键盘
this.ActiveControl = button1;
}
private void NumKeyBoard1_InputCompleted1(object sender, CustomControl.NumKeyBoardEventArgs e)
{
Control control = e.TargetControl;
float value = e.Value;
if(control is TextBox)
{
control.Text = value.ToString();
}
this.ActiveControl=button1;
}
NumberKeyBoard控件代码
public partial class NumKeyBoard : UserControl
{
public NumKeyBoard()
{
InitializeComponent();
InitLoad();
}
/// <summary>
/// 数字键盘输入完成
/// </summary>
public event EventHandler<NumKeyBoardEventArgs> InputCompleted;
/// <summary>
/// 输入取消事件
/// </summary>
public event EventHandler InputCancel;
List<Control> targetControls = new List<Control>();
void InitLoad()
{
lblTitle.MouseMove += NumKeyBoard_MouseMove;
lblTitle.MouseDown += NumKeyBoard_MouseDown;
lblTitle.MouseUp += NumKeyBoard_MouseUp;
foreach (Control item in tableLayoutKeyBoard.Controls)
{
if (item is Button)
{
(item as Button).Click += NumKeyBoard_Click;
}
}
}
Control curControl;
private void TargetControl_GotFocus(object sender, EventArgs e)
{
this.Visible = true;
this.BringToFront();
curControl = sender as Control;
if (sender is TextBox)
{
TextBox tb = sender as TextBox;
lblDisplay.Text = tb.Text;
//设置键盘出现位置
Point tbPoint = tb.Location;
Point p = new Point();
if (tbPoint.Y + this.Height < tb.TopLevelControl.Height || tbPoint.Y < this.Height)
{
p.Y = tbPoint.Y + 2 + tb.Height;
}
else
{
p.Y = tbPoint.Y - this.Height - 2;
}
if (this.Width > tb.TopLevelControl.Width - tbPoint.X)
{
p.X = tbPoint.X + tb.Width - this.Width;
}
else
{
p.X = tbPoint.X + 2;
}
this.Location = p;
}
}
#region 键盘移动
Point offsetPoint;
bool canMove = false;
private void NumKeyBoard_MouseUp(object sender, MouseEventArgs e)
{
canMove = false;
}
private void NumKeyBoard_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
canMove = true;
offsetPoint = new Point(-e.X, -e.Y);
}
}
private void NumKeyBoard_MouseMove(object sender, MouseEventArgs e)
{
if (canMove)
{
Point curPoint = this.Parent.PointToClient(Control.MousePosition);
curPoint.Offset(offsetPoint);
this.Location = curPoint;
}
}
#endregion
private void NumKeyBoard_Click(object sender, EventArgs e)
{
string key = (sender as Button).Text.Trim().ToLower();
lblTitle.Text = "";
switch (key)
{
case "-":
if (lblDisplay.Text.StartsWith("-"))
{
lblDisplay.Text = lblDisplay.Text.Remove(0, 1);
}
else
{
lblDisplay.Text = lblDisplay.Text.Insert(0, "-");
}
break;
case "del":
if (lblDisplay.Text.Length > 0)
{
lblDisplay.Text = lblDisplay.Text.Remove(lblDisplay.Text.Length - 1, 1);
}
break;
case "esc":
lblDisplay.Text = "";
InputCancel?.Invoke(this, null);
this.Visible = false;
break;
case ".":
if (lblDisplay.Text.IndexOf('.') != -1)
{
return;
}
if (string.IsNullOrEmpty(lblDisplay.Text))
{
lblDisplay.Text = "0.";
return;
}
lblDisplay.Text += ".";
break;
case "0":
if (lblDisplay.Text.Equals("0"))
{
return;
}
lblDisplay.Text += "0";
break;
case "enter":
try
{
float value = float.Parse(lblDisplay.Text.Trim());
if (value < MinNum || value > MaxNum)
{
lblTitle.Text = $"数值只能位于 {MinNum}~{MaxNum} 之间";
System.Media.SystemSounds.Hand.Play();
return;
}
lblDisplay.Text = "";
InputCompleted?.Invoke(this, new NumKeyBoardEventArgs(curControl, value));
this.Visible = false;
}
catch (Exception ex)
{
lblTitle.Text = ex.Message;
}
break;
default:
if (lblDisplay.Text.Equals("0"))
{
lblDisplay.Text = "";
}
lblDisplay.Text += key;
break;
}
}
float _minNum = 0;
[Browsable(true), Category("自定义属性"), Description("最小值")]
public float MinNum
{
get
{
return _minNum;
}
set
{
if (_minNum > MaxNum)
{
_minNum = MaxNum;
}
else
{
_minNum = value;
}
lblMinNum.Text = _minNum.ToString();
this.Invalidate();
}
}
float _maxNum = 1000;
[Browsable(true), Category("自定义属性"), Description("最小值")]
public float MaxNum
{
get
{
return _maxNum;
}
set
{
if (_maxNum < MinNum)
{
_maxNum = MinNum;
}
else
{
_maxNum = value;
}
lblMaxNum.Text = _maxNum.ToString();
this.Invalidate();
}
}
/// <summary>
/// 为指定控件添加数字键盘
/// </summary>
/// <param name="targetControlNames">需要添加数字键盘的控件名集合</param>
public void RegisterNumberKeyBoard(string[] targetControlNames)
{
if (targetControlNames != null && targetControlNames.Length != 0)
{
GetControlByControlName(this.TopLevelControl, targetControlNames);
}
foreach (var item in targetControls)
{
if (item is TextBox)
{
//给该控件注册获取光标事件
(item as TextBox).GotFocus += TargetControl_GotFocus;
}
}
}
/// <summary>
///根据目标控件名获取控件集合
/// </summary>
/// <param name="control"></param>
void GetControlByControlName(Control control, string[] targetNames)
{
if (targetNames.FirstOrDefault(item => item.Equals(control.Name)) != null)
{
targetControls.Add(control);
}
if (control.HasChildren)
{
foreach (Control c in control.Controls)
{
GetControlByControlName(c, targetNames);
}
}
}
}
public class NumKeyBoardEventArgs : EventArgs
{
public NumKeyBoardEventArgs(Control targetControl, float val)
{
this.TargetControl = targetControl;
this.Value = val;
}
/// <summary>
/// 目标控件
/// </summary>
public Control TargetControl { get; private set; }
/// <summary>
/// 数字键盘输入的值
/// </summary>
public float Value { get; private set; }
}
5,使用Graphics绘制LED。
效果:
LED控件代码:
public partial class LED : UserControl
{
public LED()
{
InitializeComponent();
设置控件样式
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
float outEllipseWidth = 5;
[Browsable(true), Category("自定义属性"), Description("外圆的宽度")]
public float OutEllipseWidth
{
get
{
return outEllipseWidth;
}
set
{
if (value < 0)
{
outEllipseWidth = 2;
}
else
{
outEllipseWidth = value;
}
this.Invalidate();
}
}
Color outEllipseColor = Color.Lime;
[Browsable(true), Category("自定义属性"), Description("外圆的颜色")]
public Color OutEllipseColor
{
get
{
return outEllipseColor;
}
set
{
outEllipseColor = value;
this.Invalidate();
}
}
float outGapWidth = 3;
[Browsable(true), Category("自定义属性"), Description("外间隙宽度")]
public float OutCapWidth
{
get
{
return outGapWidth;
}
set
{
if (value < 0)
{
outGapWidth = 2;
}
else
{
outGapWidth = value;
}
this.Invalidate();
}
}
Color centerEllipseColor = Color.Lime;
[Browsable(true), Category("自定义属性"), Description("中心圆的颜色")]
public Color CenterEllipseColor
{
get
{
return centerEllipseColor;
}
set
{
centerEllipseColor = value;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
//绘制外圆
g.DrawEllipse(new Pen(OutEllipseColor, OutEllipseWidth), OutEllipseWidth, OutEllipseWidth, Width - OutEllipseWidth * 2, Height - OutEllipseWidth * 2);
//绘制内圆
PointF p = new PointF((float)(1.5 * OutEllipseWidth) + OutCapWidth, (float)(1.5 * OutEllipseWidth) + OutCapWidth);
float centerWidth = Width - (float)(2 * (1.5 * OutEllipseWidth + OutCapWidth));
float centerHeight = Height - (float)(2 * (1.5 * OutEllipseWidth + OutCapWidth));
RectangleF centerRec = new RectangleF(p,new SizeF(centerWidth,centerHeight));
g.FillEllipse(new SolidBrush(CenterEllipseColor), centerRec);
}
}
6,使用Graphics绘制流动条。
效果:
F
FlowControl代码 :
public partial class FlowControl : UserControl
{
private float startOffset = 0.0f;
private Timer mytimer = new Timer();
Graphics g;
public FlowControl()
{
InitializeComponent();
设置控件样式
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
mytimer.Interval = 50;
mytimer.Tick += Mytimer_Tick;
mytimer.Start();
}
private void Mytimer_Tick(object sender, EventArgs e)
{
startOffset += moveSpeed;
if (Math.Abs(startOffset) > BarLength + GapLength)
{
startOffset = 0;
}
this.Invalidate();
}
#region Fileds
private int barHeight = 5;
[Browsable(true), Category("自定义属性"), Description("流动条宽度")]
public int BarHeight
{
get { return barHeight; }
set
{
this.barHeight = value;
base.Invalidate();
}
}
private Color barColor = Color.DodgerBlue;
[Browsable(true), Category("自定义属性"), Description("获取或设置管道控件的流动块颜色")]
public Color BarColor
{
get
{
return this.barColor;
}
set
{
this.barColor = value;
base.Invalidate();
}
}
private Color borderColor = Color.DimGray;
[Browsable(true), Category("自定义属性"), Description("获取或设置管道边线颜色")]
public Color BorderColor
{
get
{
return this.borderColor;
}
set
{
this.borderColor = value;
base.Invalidate();
}
}
private float borderWidth = 1;
[Browsable(true), Category("自定义属性"), Description("获取或设置管道壁厚度")]
public float BorderWidth
{
get
{
return this.borderWidth;
}
set
{
this.borderWidth = value;
base.Invalidate();
}
}
private Color pipeEdgeColor = Color.DimGray;
[Browsable(true), Category("自定义属性"), Description("获取或设置管道边缘颜色")]
public Color PipeEdgeColor
{
get
{
return this.pipeEdgeColor;
}
set
{
this.pipeEdgeColor = value;
base.Invalidate();
}
}
private Color pipeCenterColor = Color.LightGray;
[Browsable(true), Category("自定义属性"), Description("获取或设置管道控件的中心颜色")]
public Color PipeCenterColor
{
get
{
return this.pipeCenterColor;
}
set
{
this.pipeCenterColor = value;
base.Invalidate();
}
}
private PipeTurnDirection pipeTurnLeft = PipeTurnDirection.None;
[Browsable(true), Category("自定义属性"), Description("左管道的转向类型")]
public PipeTurnDirection PipeTurnLeft
{
get
{
return this.pipeTurnLeft;
}
set
{
this.pipeTurnLeft = value;
base.Invalidate();
}
}
private PipeTurnDirection pipeTurnRight = PipeTurnDirection.None;
[Browsable(true), Category("自定义属性"), Description("右管道的转向类型")]
public PipeTurnDirection PipeTurnRight
{
get
{
return this.pipeTurnRight;
}
set
{
this.pipeTurnRight = value;
base.Invalidate();
}
}
private DirectionStyle pipeLineDirection = DirectionStyle.Horizontal;
[Browsable(true), Category("自定义属性"), Description("设置管道是横向的还是纵向的")]
public DirectionStyle PipeLineDirection
{
get
{
return this.pipeLineDirection;
}
set
{
this.pipeLineDirection = value;
int temp;
if (value == DirectionStyle.Horizontal)
{
temp = Height;
Height = Width;
Width = temp;
}
else
{
temp = Width;
Width = Height;
Height = temp;
}
base.Invalidate();
}
}
private bool isActive = false;
[Browsable(true), Category("自定义属性"), DefaultValue(false), Description("获取或设置管道线是否激活液体显示")]
public bool IsActive
{
get
{
return this.isActive;
}
set
{
this.isActive = value;
this.mytimer.Enabled = value;
base.Invalidate();
}
}
private float moveSpeed = 0.3f;
[Browsable(true), Category("自定义属性"), Description("管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动")]
public float MoveSpeed
{
get
{
return this.moveSpeed;
}
set
{
this.moveSpeed = value;
base.Invalidate();
}
}
private int barLength = 5;
[Browsable(true), Category("自定义属性"), Description("流动条长度")]
public int BarLength
{
get
{
return this.barLength;
}
set
{
this.barLength = value;
base.Invalidate();
}
}
private int gapLength = 5;
[Browsable(true), Category("自定义属性"), Description("间隙长度")]
public int GapLength
{
get
{
return this.gapLength;
}
set
{
this.gapLength = value;
base.Invalidate();
}
}
#endregion
protected override void OnResize(EventArgs e)
{
if (PipeLineDirection == DirectionStyle.Horizontal)
{
if (Width < 2 * Height)
{
Width = 2 * Height;
}
}
else
{
if (Height < 2 * Width)
{
Height = 2 * Width;
}
}
base.OnResize(e);
}
protected override void OnPaint(PaintEventArgs e)
{
// base.OnPaint(e);
g = e.Graphics;
Rectangle rec;
Rectangle rec2;
GraphicsPath graphicsPath = new GraphicsPath();
if (PipeLineDirection == DirectionStyle.Horizontal)
{
#region 水平
switch (pipeTurnLeft)
{
case PipeTurnDirection.Up:
rec = new Rectangle(0, -Height, 2 * Height, 2 * Height);
rec2 = new Rectangle(rec.X + (int)BorderWidth / 2, rec.Y, rec.Width - (int)BorderWidth, rec.Height - (int)BorderWidth / 2);
PaintElliple(g, rec, rec2, 90, 90);
// path.AddArc(new Rectangle( Height / 2, rec.Y /2, Height , Height), 90, 90);
//特别需要注意角度旋转方向,如果角度旋转方向选错就形成闭环
graphicsPath.AddArc(new Rectangle(this.Height / 2, this.Height / 2 * (-1) - 1, this.Height, this.Height), 180.0f, -90.0f);
break;
case PipeTurnDirection.Down:
rec = new Rectangle(0, 0, 2 * Height, 2 * Height);
rec2 = new Rectangle(rec.X + (int)BorderWidth / 2, rec.Y + (int)BorderWidth / 2, rec.Width - (int)BorderWidth, rec.Height - (int)BorderWidth / 2);
PaintElliple(g, rec, rec2, 180, 90);
graphicsPath.AddArc(new Rectangle(Height / 2, Height / 2, Height, Height), 180, 90);
break;
case PipeTurnDirection.Left:
case PipeTurnDirection.Right:
case PipeTurnDirection.None:
PointF[] points = new PointF[] { new PointF(Height, BorderWidth / 2), new PointF(0, BorderWidth / 2), new PointF(0, Height - BorderWidth / 2), new PointF(Height, Height - BorderWidth / 2) };
PaintRectangle(g, new Rectangle(0, 0, Height, Height), points);
graphicsPath.AddLine(new PointF(0, Height / 2), new PointF(Height, Height / 2));
break;
default:
break;
}
switch (PipeTurnRight)
{
case PipeTurnDirection.Up:
rec = new Rectangle(Width - 2 * Height, -Height, 2 * Height, 2 * Height);
rec2 = new Rectangle(rec.X + (int)BorderWidth / 2, rec.Y, rec.Width - (int)BorderWidth, rec.Height - (int)BorderWidth / 2);
PaintElliple(g, rec, rec2, 0, 90);
graphicsPath.AddArc(new Rectangle(rec.X + Height / 2, rec.Y / 2, Height, Height), 90, -90);
break;
case PipeTurnDirection.Down:
rec = new Rectangle(Width - 2 * Height, 0, 2 * Height, 2 * Height);
rec2 = new Rectangle(rec.X, rec.Y + (int)BorderWidth / 2, rec.Width - (int)BorderWidth / 2, rec.Height - (int)BorderWidth / 2);
PaintElliple(g, rec, rec2, 270, 90);
//特别需要注意角度旋转方向,如果角度旋转方向选错就形成闭环
graphicsPath.AddArc(new Rectangle(rec.X + Height / 2, Height / 2, Height, Height), 270, 90);
break;
case PipeTurnDirection.Left:
case PipeTurnDirection.Right:
case PipeTurnDirection.None:
PointF[] points = new PointF[] { new PointF(Width - Height, BorderWidth / 2), new PointF(Width, BorderWidth / 2), new PointF(Width, Height - BorderWidth / 2), new PointF(Width - Height, Height - BorderWidth / 2) };
PaintRectangle(g, new Rectangle(Width - Height, 0, Height, Height), points);
graphicsPath.AddLine(Width - Height, Height / 2, Width, Height / 2);
break;
default:
break;
}
if (Width > Height * 2)
{
PointF[] points = new PointF[] { new PointF(Height, BorderWidth / 2), new PointF(Width - Height, BorderWidth / 2), new PointF(Height, Height - BorderWidth / 2), new PointF(Width - Height, Height - BorderWidth / 2) };
PaintRectangle(g, new Rectangle(Height, 0, Width - 2 * Height, Height), points);
// graphicsPath.AddLine(Height, Height / 2,Width- Height , Height / 2);
}
#endregion
}
else
{
//垂直
switch (pipeTurnLeft)
{
case PipeTurnDirection.Left:
rec = new Rectangle(-Width, 0, 2 * Width, 2 * Width);
rec2 = new Rectangle(rec.X, rec.Y + (int)BorderWidth / 2, rec.Width - (int)BorderWidth / 2, rec.Height - (int)BorderWidth);
PaintElliple(g, rec, rec2, 270, 90);
// path.AddArc(new Rectangle( Height / 2, rec.Y /2, Height , Height), 90, 90);
//特别需要注意角度旋转方向,如果角度旋转方向选错就形成闭环
graphicsPath.AddArc(new Rectangle(-this.Width / 2, this.Width / 2, this.Width, this.Width), 270.0f, 90.0f);
break;
case PipeTurnDirection.Right:
rec = new Rectangle(0, 0, 2 * Width, 2 * Width);
rec2 = new Rectangle(rec.X + (int)BorderWidth / 2, rec.Y + (int)BorderWidth / 2, rec.Width - (int)BorderWidth, rec.Height - (int)BorderWidth / 2);
PaintElliple(g, rec, rec2, 180, 90);
graphicsPath.AddArc(new Rectangle(Width / 2, Width / 2, Width, Width), 270, -90);
break;
case PipeTurnDirection.Up:
case PipeTurnDirection.Down:
case PipeTurnDirection.None:
PointF[] points = new PointF[] { new PointF(BorderWidth / 2, 0), new PointF(BorderWidth / 2, Width), new PointF(Width - BorderWidth / 2, 0), new PointF(Width - BorderWidth / 2, Width) };
PaintRectangle(g, new Rectangle(0, 0, Width, Width), points, LinearGradientMode.Horizontal);
graphicsPath.AddLine(new PointF(Width / 2, 0), new PointF(Width / 2, Width));
break;
default:
break;
}
switch (PipeTurnRight)
{
case PipeTurnDirection.Left:
rec = new Rectangle(-Width, Height - 2 * Width, 2 * Width, 2 * Width);
rec2 = new Rectangle(rec.X, rec.Y + (int)BorderWidth / 2, rec.Width - (int)BorderWidth / 2, rec.Height - (int)BorderWidth);
PaintElliple(g, rec, rec2, 0, 90);
//特别需要注意角度旋转方向,如果角度旋转方向选错就形成闭环
graphicsPath.AddArc(new Rectangle(rec.X / 2, rec.Y + Width / 2, this.Width, this.Width), 0f, 90.0f);
break;
case PipeTurnDirection.Right:
rec = new Rectangle(0, Height - 2 * Width, 2 * Width, 2 * Width);
rec2 = new Rectangle(rec.X + (int)BorderWidth / 2, rec.Y + 1, rec.Width - (int)BorderWidth, rec.Height - (int)BorderWidth / 2);
PaintElliple(g, rec, rec2, 90, 90);
graphicsPath.AddArc(new Rectangle(Width / 2, rec.Y + Width / 2, Width, Width), 180, -90);
break;
case PipeTurnDirection.Up:
case PipeTurnDirection.Down:
case PipeTurnDirection.None:
PointF[] points = new PointF[] { new PointF(BorderWidth / 2, Height - Width), new PointF(BorderWidth / 2, Height), new PointF(Width - BorderWidth / 2, Height - Width), new PointF(Width - BorderWidth / 2, Height) };
PaintRectangle(g, new Rectangle(0, Height - Width, Width, Width), points, LinearGradientMode.Horizontal);
graphicsPath.AddLine(new PointF(Width / 2, Height - Width), new PointF(Width / 2, Height));
break;
default:
break;
}
if (Height > Width * 2)
{
PointF[] points = new PointF[] { new PointF(BorderWidth / 2, Width), new PointF(BorderWidth / 2, Height - Width), new PointF(Width - BorderWidth / 2, Width), new PointF(Width - BorderWidth / 2, Height - Width) };
PaintRectangle(g, new Rectangle(0, Width, Width, Height - 2 * Width), points, LinearGradientMode.Horizontal);
// graphicsPath.AddLine(Height, Height / 2,Width- Height , Height / 2);
}
}
if (IsActive)
{
//绘制流动条
Pen barPen = new Pen(BarColor, BarHeight);
barPen.DashStyle = DashStyle.Custom;
barPen.DashOffset = startOffset;
barPen.DashPattern = new float[] { BarLength, GapLength };
graphicsPath.StartFigure();
g.DrawPath(barPen, graphicsPath);
}
}
//绘制椭圆与圆弧
void PaintElliple(Graphics g, Rectangle rec, Rectangle recArc, float startAngle, float sweepAngle)
{
GraphicsPath graphicsPath = new GraphicsPath();
graphicsPath.AddEllipse(rec);
//画刷效果呈现由中心向四方层叠
PathGradientBrush brush = new PathGradientBrush(graphicsPath);
brush.CenterPoint = new PointF(rec.X + rec.Width / 2, rec.Y + rec.Height / 2);
brush.InterpolationColors = new ColorBlend() { Colors = new Color[] { PipeEdgeColor, PipeCenterColor, PipeEdgeColor }, Positions = new float[] { 0, 0.5f, 1 } };
g.FillPie(brush, rec, startAngle, sweepAngle);
g.DrawArc(new Pen(BorderColor, BorderWidth), recArc, startAngle, sweepAngle);
}
void PaintRectangle(Graphics g, Rectangle rec, PointF[] points, LinearGradientMode linearGradientMode = LinearGradientMode.Vertical)
{
//画刷效果呈现线型分布,注意与PathGradientBrush的区别
LinearGradientBrush brush = new LinearGradientBrush(rec, PipeEdgeColor, PipeCenterColor, linearGradientMode);
brush.InterpolationColors = new ColorBlend() { Colors = new Color[] { PipeEdgeColor, PipeCenterColor, PipeEdgeColor }, Positions = new float[] { 0, 0.5f, 1 } };
brush.InterpolationColors = new ColorBlend() { Colors = new Color[] { PipeEdgeColor, PipeCenterColor, PipeEdgeColor }, Positions = new float[] { 0, 0.5f, 1 } };
g.FillRectangle(brush, rec);
g.DrawLine(new Pen(BorderColor, BorderWidth), points[0], points[1]);
g.DrawLine(new Pen(BorderColor, BorderWidth), points[2], points[3]);
}
}
/// <summary>
/// 管道左、右的转向类型
/// </summary>
public enum PipeTurnDirection
{
Up = 1,
Down,
Left,
Right,
None
}
/// <summary>
/// 管道的样式,水平还是数值
/// </summary>
public enum DirectionStyle
{
Horizontal = 1,
Vertical
}
7,使用Graphics绘制仪表盘1:
效果:
DashBoard控件代码
[DefaultEvent("Click")]//指定默认事件
public partial class DashBoard : UserControl
{
public DashBoard()
{
InitializeComponent();
// 设置控件样式
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
Font _wordFont = new Font("微软雅黑", 10, FontStyle.Bold);
[Browsable(true), Category("自定义属性"), Description("文字字体")]
public Font WordFont
{
get
{
return _wordFont;
}
set
{
_wordFont = value;
this.Invalidate();
}
}
Color _wordColor = Color.Black;
/// <summary>
/// 文字颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("文字颜色")]
public Color WordColor
{
get
{
return _wordColor;
}
set
{
_wordColor = value;
this.Invalidate();
}
}
bool _isWordShow = true;
/// <summary>
/// 文字是否显示
/// </summary>
[Browsable(true), Category("自定义属性"), Description("文字是否显示")]
public bool IsWordShow
{
get
{
return _isWordShow;
}
set
{
_isWordShow = value;
this.Invalidate();
}
}
string _wordFormat = "实际温度:{0}℃";
/// <summary>
/// 文字是否显示的格式,例如:"实际温度:{0}℃",{0}为实际值的占位符
/// </summary>
[Browsable(true), Category("自定义属性"), Description("文字是否显示的格式,例如:'实际温度:{0}℃',{0}为实际值的占位符")]
public string WordFormat
{
get
{
return _wordFormat;
}
set
{
_wordFormat = value;
this.Invalidate();
}
}
float _wordPositionFactor = 0.6f;
/// <summary>
/// 底部文字所在位置
/// </summary>
[Browsable(true), Category("自定义属性"), Description("底部文字所在位置")]
public float WordPositionFactor
{
get
{
return _wordPositionFactor;
}
set
{
if (value < 0 || value > 1)
{
_wordPositionFactor = 0.6f;
}
else
{
_wordPositionFactor = value;
}
this.Invalidate();
}
}
float _startValue = 0;
/// <summary>
/// 开始值
/// </summary>
[Browsable(true), Category("自定义属性"), Description("开始值")]
public float StartValue
{
get
{
return _startValue;
}
set
{
_startValue = value;
this.Invalidate();
}
}
float _endValue = 160;
/// <summary>
/// 结束值
/// </summary>
[Browsable(true), Category("自定义属性"), Description("结束值")]
public float EndValue
{
get
{
return _endValue;
}
set
{
_endValue = value;
this.Invalidate();
}
}
float _sweepRange = 240;
/// <summary>
/// 量程跨度,即从开始值到结束值所占用的角度
/// </summary>
[Browsable(true), Category("自定义属性"), Description("量程跨度,即从开始值到结束值所占用的角度")]
public float SweepRange
{
get
{
return _sweepRange;
}
set
{
if (value < 0)
{
_sweepRange = 240;
}
else
{
_sweepRange = value;
}
this.Invalidate();
}
}
int _largeMarkCount = 9;
/// <summary>
/// 刻度间隔值
/// </summary>
[Browsable(true), Category("自定义属性"), Description("刻度间隔值")]
public int LargeMarkCount
{
get
{
return _largeMarkCount;
}
set
{
if (value < 0)
{
_largeMarkCount = 9;
}
else
{
_largeMarkCount = value;
}
this.Invalidate();
}
}
MarkType _markStyle = MarkType.Average;
/// <summary>
/// 刻度分配样式,是平均分配还是自定义刻度值分配
/// </summary>
[Browsable(true), Category("自定义属性"), Description(" 刻度分配样式,是平均分配还是自定义刻度值分配")]
public MarkType MarkStyle
{
get
{
return _markStyle;
}
set
{
_largeMarkCount = 9;
_markStyle = value;
this.Invalidate();
}
}
float[] _customMarkValue = { 0, 20, 40, 60, 80, 100, 120, 140, 160 };
/// <summary>
/// 自定义刻度值
/// </summary>
[Browsable(true), Category("自定义属性"), Description("自定义刻度值")]
public float[] CustomMarkValue
{
get
{
return _customMarkValue;
}
set
{
_customMarkValue = value;
this.Invalidate();
}
}
Color _firstColor = Color.DodgerBlue;
/// <summary>
/// 第一部分颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("第一部分颜色")]
public Color FirstColor
{
get
{
return _firstColor;
}
set
{
_firstColor = value;
this.Invalidate();
}
}
int _firstColorHaveMarkCount = 6;
/// <summary>
/// 第一部分颜色所拥有的刻度数量
/// </summary>
[Browsable(true), Category("自定义属性"), Description("第一部分颜色所拥有的刻度数量")]
public int FirstColorHaveMarkCount
{
get
{
return _firstColorHaveMarkCount;
}
set
{
if (value < 0)
{
_firstColorHaveMarkCount = 2;
}
else
{
_firstColorHaveMarkCount = value;
}
this.Invalidate();
}
}
Color _secondColor = Color.LightGray;
/// <summary>
/// 第2部分颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("第2部分颜色")]
public Color SecondColor
{
get
{
return _secondColor;
}
set
{
_secondColor = value;
this.Invalidate();
}
}
int _outCircleWidth = 3;
/// <summary>
/// 外圆宽度
/// </summary>
[Browsable(true), Category("自定义属性"), Description("外圆宽度")]
public int OutCircleWidth
{
get
{
return _outCircleWidth;
}
set
{
if (value < 0)
{
return;
}
else
{
_outCircleWidth = value;
}
this.Invalidate();
}
}
float _pointerPartFactor = 0.1f;
/// <summary>
/// 指针部分所占的比例
/// </summary>
[Browsable(true), Category("自定义属性"), Description("指针部分所占的比例")]
public float PointerPartFactor
{
get
{
return _pointerPartFactor;
}
set
{
if (value < 0 || value > 1)
{
_pointerPartFactor = 0.2f;
}
else
{
_pointerPartFactor = value;
}
this.Invalidate();
}
}
/// <summary>
/// 尺寸
/// </summary>
int Dimensions
{
get
{
if (Width < Height)
{
return Width;
}
return Height;
}
}
int _outCap = 5;
/// <summary>
/// 外间隙
/// </summary>
[Browsable(true), Category("自定义属性"), Description("外间隙")]
public int OutGap
{
get
{
return _outCap;
}
set
{
if (value < 0)
{
return;
}
_outCap = value;
this.Invalidate();
}
}
int _innerCap = 15;
/// <summary>
/// 内间隙
/// </summary>
[Browsable(true), Category("自定义属性"), Description("内间隙")]
public int InnerGap
{
get
{
return _innerCap;
}
set
{
if (value < 0)
{
return;
}
_innerCap = value;
this.Invalidate();
}
}
float _actualValue = 60;
/// <summary>
/// 实际值
/// </summary>
[Browsable(true), Category("自定义属性"), Description("实际值")]
public float ActualValue
{
get
{
return _actualValue;
}
set
{
_actualValue = value;
this.Invalidate();
}
}
Color _markWordColor = Color.Black;
[Browsable(true), Category("自定义属性"), Description("刻度文字颜色")]
public Color MarkWordColor
{
get
{
return _markWordColor;
}
set
{
_markWordColor = value;
}
}
Font _markWordFont = DefaultFont;
[Browsable(true), Category("自定义属性"), Description("刻度文字字体")]
public Font MarkWordFont
{
get
{
return _markWordFont;
}
set
{
_markWordFont = value;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
//计算需要绘制的刻度数量
g.SmoothingMode = SmoothingMode.AntiAlias; //使绘图质量最高,即消除锯齿
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
Dictionary<int, float> dic = new Dictionary<int, float>();
if (MarkStyle == MarkType.Average)
{
for (int i = 0; i < LargeMarkCount; i++)
{
dic.Add(i, i * (SweepRange / (LargeMarkCount - 1)));
}
}
else
{
for (int i = 0; i < CustomMarkValue.Length; i++)
{
dic.Add(i, (CustomMarkValue[i] - CustomMarkValue.Min()) / Math.Abs((CustomMarkValue.Max() - CustomMarkValue.Min())) * SweepRange);
}
}
//绘制外圆
if (FirstColorHaveMarkCount > dic.Count)
{
FirstColorHaveMarkCount = dic.Count;
}
float startAngle = (360 - SweepRange) / 2 + 90;
//第1段
g.DrawArc(new Pen(FirstColor, OutCircleWidth), OutGap, OutGap, Dimensions - OutGap * 2, Dimensions - OutGap * 2, startAngle, dic[FirstColorHaveMarkCount - 1]);
//第2段
g.DrawArc(new Pen(SecondColor, OutCircleWidth), OutGap, OutGap, Dimensions - OutGap * 2, Dimensions - OutGap * 2, dic[FirstColorHaveMarkCount - 1] + startAngle, dic[dic.Count - 1] - dic[FirstColorHaveMarkCount - 1]);
//绘制刻度
//偏移原点
g.TranslateTransform(Dimensions / 2, Dimensions / 2);
//旋转角度
g.RotateTransform(-_sweepRange / 2);
foreach (var key in dic.Keys)
{
RectangleF rec = new RectangleF(-2, -(Dimensions - 2 * OutGap) / 2 - OutGap, 4, OutGap * 2);
if (key != 0)
{
g.RotateTransform(dic[key] - dic[key - 1]);
}
if (key < FirstColorHaveMarkCount)
{
g.FillRectangle(new SolidBrush(FirstColor), rec);
}
else
{
g.FillRectangle(new SolidBrush(SecondColor), rec);
}
}
//恢复坐标
g.ResetTransform();
//移动原点
g.TranslateTransform(Dimensions / 2, Dimensions / 2);
//旋转角度
// g.RotateTransform(-_sweepRange / 2);
//绘制MarkWord
// PointF p = new PointF((float)(Dimensions * Math.Cos(230*1.0 / 180 * Math.PI)), (float)(Dimensions * Math.Sin(230*1.0 / 180 * Math.PI)));
// g.DrawLine(Pens.Black, new PointF(0, 0), p);
float largeInterval = SweepRange / (LargeMarkCount - 1);
foreach (var key in dic.Keys)
{
//绘制文字
string markWord;
if (MarkStyle == MarkType.Average)
{
markWord = Math.Round(StartValue + key * (EndValue - StartValue) / (LargeMarkCount - 1), 1).ToString();
}
else
{
markWord = Math.Round(CustomMarkValue[key], 1).ToString();
}
float wordRadius = Dimensions / 2 - OutCircleWidth - OutGap - InnerGap;
double x = wordRadius * Math.Cos((dic[key] + startAngle) / 180 * Math.PI);
double y = wordRadius * Math.Sin((dic[key] + startAngle) / 180 * Math.PI);
SizeF size = g.MeasureString(markWord, this.Font);
PointF wordPoint = new PointF((float)x - size.Width / 2, (float)y - size.Height / 2);
g.DrawString(markWord, MarkWordFont, new SolidBrush(MarkWordColor), wordPoint);
}
if (IsWordShow)
{
//绘制底部文字
string txt = string.Format(WordFormat, ActualValue);
SizeF wordSize = g.MeasureString(txt, WordFont);
PointF txtPoint = new PointF(-wordSize.Width / 2, Dimensions / 2 * WordPositionFactor);
g.DrawString(txt, WordFont, new SolidBrush(WordColor), txtPoint);
}
//绘制指针
//圆心半径
float circleRadius = Dimensions / 2 * this.PointerPartFactor;
float pointerLength = circleRadius * 6;
float trackWidth = pointerLength / 4;
//绘制指针圆心
g.FillEllipse(new SolidBrush(FirstColor), -circleRadius, -circleRadius, 2 * circleRadius, 2 * circleRadius);
float relativeAngle;
if (ActualValue > EndValue)
{
relativeAngle = SweepRange;
}
else if (ActualValue < StartValue)
{
relativeAngle = 0;
}
else
{
if (MarkStyle == MarkType.Average)
{
relativeAngle = ((ActualValue - StartValue) / (EndValue - StartValue)) * SweepRange;
}
else
{
if (CustomMarkValue.Length < 2)
{
CustomMarkValue = new float[] { 0, 20, 30 };
}
relativeAngle = (ActualValue - CustomMarkValue.Min()) / (CustomMarkValue.Max() - CustomMarkValue.Min()) * SweepRange;
}
}
//绘制轨迹
g.DrawArc(new Pen(FirstColor, trackWidth), -pointerLength + trackWidth / 2, -pointerLength + trackWidth / 2, 2 * pointerLength - trackWidth, 2 * pointerLength - trackWidth, startAngle, relativeAngle);
//旋转角度
g.RotateTransform(-_sweepRange / 2);
//当前值对应的相对角度
//绘制指针
g.RotateTransform(relativeAngle);
g.DrawLine(new Pen(FirstColor, 2), -1, 0, -1, -pointerLength);
}
}
public enum MarkType
{
/// <summary>
/// 平均分配刻度
/// </summary>
Average,
/// <summary>
/// 自定义刻度值分配
/// </summary>
Custom
}
}
8,使用Graphics绘制仪表盘2:
效果:
Gague控件代码:
[DefaultEvent("Click")]
public partial class Gague : UserControl
{
public Gague()
{
InitializeComponent();
// 设置控件样式
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
Font _wordFont = new Font("微软雅黑", 10, FontStyle.Bold);
[Browsable(true), Category("自定义属性"), Description("文字字体")]
public Font WordFont
{
get
{
return _wordFont;
}
set
{
_wordFont = value;
this.Invalidate();
}
}
Color _wordColor = Color.SeaGreen;
/// <summary>
/// 文字颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("文字颜色")]
public Color WordColor
{
get
{
return _wordColor;
}
set
{
_wordColor = value;
this.Invalidate();
}
}
bool _isWordShow = true;
/// <summary>
/// 文字是否显示
/// </summary>
[Browsable(true), Category("自定义属性"), Description("文字是否显示")]
public bool IsWordShow
{
get
{
return _isWordShow;
}
set
{
_isWordShow = value;
this.Invalidate();
}
}
string _wordFormat = "实际温度:{0}℃";
/// <summary>
/// 文字是否显示的格式,例如:"实际温度:{0}℃",{0}为实际值的占位符
/// </summary>
[Browsable(true), Category("自定义属性"), Description("文字是否显示的格式,例如:'实际温度:{0}℃',{0}为实际值的占位符")]
public string WordFormat
{
get
{
return _wordFormat;
}
set
{
_wordFormat = value;
this.Invalidate();
}
}
float _wordPositionFactor = 0.7f;
/// <summary>
/// 底部文字所在位置
/// </summary>
[Browsable(true), Category("自定义属性"), Description("底部文字所在位置")]
public float WordPositionFactor
{
get
{
return _wordPositionFactor;
}
set
{
if (value < 0 || value > 1)
{
_wordPositionFactor = 0.6f;
}
else
{
_wordPositionFactor = value;
}
this.Invalidate();
}
}
float _startValue = 0;
/// <summary>
/// 开始值
/// </summary>
[Browsable(true), Category("自定义属性"), Description("开始值")]
public float StartValue
{
get
{
return _startValue;
}
set
{
_startValue = value;
this.Invalidate();
}
}
float _endValue = 160;
/// <summary>
/// 结束值
/// </summary>
[Browsable(true), Category("自定义属性"), Description("结束值")]
public float EndValue
{
get
{
return _endValue;
}
set
{
_endValue = value;
this.Invalidate();
}
}
float _lowAlarmValue = 25;
/// <summary>
/// 低报警阈值
/// </summary>
[Browsable(true), Category("自定义属性"), Description("低警戒值")]
public float LowAlarmValue
{
get
{
return _lowAlarmValue;
}
set
{
if (value < StartValue)
{
_lowAlarmValue = StartValue;
}
else
{
_lowAlarmValue = value;
}
this.Invalidate();
}
}
Color _lowAlarmColor = Color.Red;
/// <summary>
/// 低警区域颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("低警区域颜色")]
public Color LowAlarmColor
{
get
{
return _lowAlarmColor;
}
set
{
_lowAlarmColor = value;
this.Invalidate();
}
}
float _hightAlarmValue = 120;
/// <summary>
/// 高报警阈值
/// </summary>
[Browsable(true), Category("自定义属性"), Description("高警戒值")]
public float HightAlarmValue
{
get
{
return _hightAlarmValue;
}
set
{
if (value > EndValue)
{
_hightAlarmValue = EndValue;
}
else
{
_hightAlarmValue = value;
}
this.Invalidate();
}
}
Color _hightAlarmColor = Color.Red;
/// <summary>
/// 高报警区域颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("高警区域颜色")]
public Color HightAlarmColor
{
get
{
return _hightAlarmColor;
}
set
{
_hightAlarmColor = value;
this.Invalidate();
}
}
float _sweepRange = 240;
/// <summary>
/// 量程跨度,即从开始值到结束值所占用的角度
/// </summary>
[Browsable(true), Category("自定义属性"), Description("量程跨度,即从开始值到结束值所占用的角度")]
public float SweepRange
{
get
{
return _sweepRange;
}
set
{
if (value < 0)
{
_sweepRange = 240;
}
else
{
_sweepRange = value;
}
this.Invalidate();
}
}
Color _markColor = Color.LightSeaGreen;
/// <summary>
/// 刻度颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("刻度颜色")]
public Color MarkColor
{
get
{
return _markColor;
}
set
{
_markColor = value;
this.Invalidate();
}
}
Color _pointerColor = Color.Green;
/// <summary>
/// 指针颜色
/// </summary>
[Browsable(true), Category("自定义属性"), Description("指针颜色")]
public Color PointerColor
{
get
{
return _pointerColor;
}
set
{
_pointerColor = value;
this.Invalidate();
}
}
float _pointerPartFactor = 0.8f;
/// <summary>
/// 指针部分所占的比例
/// </summary>
[Browsable(true), Category("自定义属性"), Description("指针部分所占的比例")]
public float PointerPartFactor
{
get
{
return _pointerPartFactor;
}
set
{
if (value < 0 || value > 1)
{
_pointerPartFactor = 0.2f;
}
else
{
_pointerPartFactor = value;
}
this.Invalidate();
}
}
/// <summary>
/// 尺寸
/// </summary>
int Dimensions
{
get
{
if (Width < Height)
{
return Width;
}
return Height;
}
}
int _outCap = 5;
/// <summary>
/// 外间隙
/// </summary>
[Browsable(true), Category("自定义属性"), Description("外间隙")]
public int OutGap
{
get
{
return _outCap;
}
set
{
if (value < 0)
{
return;
}
_outCap = value;
this.Invalidate();
}
}
int _innerCap = 3;
/// <summary>
/// 内间隙
/// </summary>
[Browsable(true), Category("自定义属性"), Description("内间隙")]
public int InnerGap
{
get
{
return _innerCap;
}
set
{
if (value < 0)
{
return;
}
_innerCap = value;
this.Invalidate();
}
}
float _actualValue = 60;
/// <summary>
/// 实际值
/// </summary>
[Browsable(true), Category("自定义属性"), Description("实际值")]
public float ActualValue
{
get
{
return _actualValue;
}
set
{
_actualValue = value;
this.Invalidate();
}
}
Color _markWordColor = Color.Black;
[Browsable(true), Category("自定义属性"), Description("刻度文字颜色")]
public Color MarkWordColor
{
get
{
return _markWordColor;
}
set
{
_markWordColor = value;
}
}
Font _markWordFont = DefaultFont;
[Browsable(true), Category("自定义属性"), Description("刻度文字颜色")]
public Font MarkWordFont
{
get
{
return _markWordFont;
}
set
{
_markWordFont = value;
this.Invalidate();
}
}
int _largeMarkCount = 9;
[Browsable(true), Category("自定义属性"), Description("大刻度数量")]
public int LargeMarkCount
{
get
{
return _largeMarkCount;
}
set
{
if (value < 0)
{
_largeMarkCount = 5;
}
else
{
_largeMarkCount = value;
}
this.Invalidate();
}
}
int _markWidth = 3;
[Browsable(true), Category("自定义属性"), Description("刻度宽度")]
public int MarkWidth
{
get
{
return _markWidth;
}
set
{
if (value < 0)
{
_markWidth = 3;
}
else
{
_markWidth = value;
}
this.Invalidate();
}
}
int _markHeight = 4;
[Browsable(true), Category("自定义属性"), Description("刻度宽度")]
public int MarkHeight
{
get
{
return _markHeight;
}
set
{
if (value < 0)
{
_markHeight = 4;
}
else
{
_markHeight = value;
}
this.Invalidate();
}
}
int _markWordGap = 24;
[Browsable(true), Category("自定义属性"), Description("刻度文字与刻度间隙")]
public int MarkWordGap
{
get
{
return _markWordGap;
}
set
{
if (value < 0)
{
_markWordGap = 4;
}
else
{
_markWordGap = value;
}
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias; //使绘图质量最高,即消除锯齿
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
//绘制刻度
//计算小刻度大小
float smallMarkAngle = SweepRange / ((LargeMarkCount - 1) * 5);
g.TranslateTransform(Dimensions / 2, Dimensions / 2);
float offset = OutGap + InnerGap + MarkHeight;
g.RotateTransform(-_sweepRange / 2);
for (int i = 0; i <= LargeMarkCount - 1; i++)
{
//绘制大刻度
PointF[] points = new PointF[]
{
new PointF(-MarkWidth*1.0f/2, offset-Dimensions/2),
new PointF(MarkWidth*1.0f/2,offset-Dimensions/2),
new PointF(MarkWidth*1.0f/2,offset+MarkHeight*2-Dimensions/2),
new PointF(0,offset+MarkHeight*2+ MarkWidth*1.0f/2-Dimensions/2),
new PointF(-MarkWidth*1.0f/2,offset+MarkHeight*2-Dimensions/2)
};
g.FillPolygon(new SolidBrush(MarkColor), points);
g.RotateTransform(smallMarkAngle);
if (i != LargeMarkCount - 1)
{
//绘制小刻度
for (int j = 0; j < 4; j++)
{
g.FillRectangle(new SolidBrush(MarkColor), -MarkWidth * 1.0f / 2, offset - Dimensions / 2, MarkWidth, MarkHeight);
g.RotateTransform(smallMarkAngle);
}
}
}
//初始化原点,并将原点置于圆心
g.ResetTransform();
g.TranslateTransform(Dimensions / 2, Dimensions / 2);
float startAngle = 180 - SweepRange / 2 + 90;
float lowAlarmAngle;
if (LowAlarmValue == StartValue)
{
lowAlarmAngle = 0;
}
else
{
lowAlarmAngle = (LowAlarmValue - StartValue) * 1.0f / (EndValue - StartValue) * SweepRange;
}
float hightAlarmAngle;
if (HightAlarmValue == EndValue)
{
hightAlarmAngle = 0;
}
else
{
hightAlarmAngle = (EndValue - HightAlarmValue) * 1.0f / (EndValue - StartValue) * SweepRange;
}
//绘制警戒线
Pen lowAlarmPen = new Pen(LowAlarmColor, MarkWidth)
{
DashStyle = DashStyle.Dash,
DashPattern = new float[] { 3, 1 }
};
Pen hightAlarmPen = new Pen(HightAlarmColor, MarkWidth)
{
DashStyle = DashStyle.Dash,
DashPattern = new float[] { 3, 1 }
};
g.DrawArc(lowAlarmPen, OutGap - Dimensions / 2, OutGap - Dimensions / 2, Dimensions - 2 * OutGap, Dimensions - 2 * OutGap, startAngle, lowAlarmAngle);
g.DrawArc(hightAlarmPen, OutGap - Dimensions / 2, OutGap - Dimensions / 2, Dimensions - 2 * OutGap, Dimensions - 2 * OutGap, startAngle + SweepRange - hightAlarmAngle, hightAlarmAngle);
//绘制刻度文字
float largeMarkInterval = (EndValue - StartValue) / (LargeMarkCount - 1);
for (int i = 0; i <= LargeMarkCount - 1; i++)
{
float angle = startAngle + i * 5 * smallMarkAngle;
float radius = Dimensions / 2 - (OutGap + MarkWidth + InnerGap + MarkWordGap);
PointF p = new PointF(radius * (float)(Math.Cos(angle / 180 * Math.PI)), radius * (float)(Math.Sin(angle / 180 * Math.PI)));
string wordtxt = (Math.Round(StartValue + i * largeMarkInterval, 1)).ToString();
SizeF wordSize = g.MeasureString(wordtxt, MarkWordFont);
PointF wordPoint = new PointF(p.X - wordSize.Width / 2, p.Y - wordSize.Height / 2);
g.DrawString(wordtxt, MarkWordFont, new SolidBrush(MarkWordColor), wordPoint);
// g.DrawLine(Pens.Black, new Point(0, 0), p);
}
//绘制文字
if (this.IsWordShow)
{
string word = string.Format(WordFormat, ActualValue);
SizeF wSize = g.MeasureString(word, WordFont);
float wordPosition = Dimensions / 2 * this.WordPositionFactor;
PointF wPoint = new PointF(-wSize.Width / 2, wordPosition - wSize.Height / 2);
g.DrawString(word, WordFont, new SolidBrush(WordColor), wPoint);
}
//绘制指针
//使指针置于0位
g.RotateTransform(-SweepRange / 2);
//计算旋转的角度
if (StartValue != EndValue)
{
float pointerAngle;
if (ActualValue < StartValue)
{
pointerAngle = 0;
}
else if (ActualValue > EndValue)
{
pointerAngle = SweepRange;
}
else
{
pointerAngle = (ActualValue - StartValue) / (EndValue - StartValue) * SweepRange;
}
g.RotateTransform(pointerAngle);
}
float pointerLenght = Dimensions / 2 * PointerPartFactor;
float centerRadius = pointerLenght / 30;
GraphicsPath path = new GraphicsPath();
path.AddArc(-centerRadius, -centerRadius, 2 * centerRadius, 2 * centerRadius, 0, 180);
path.AddLine(-centerRadius, 0, 0, -pointerLenght);
g.FillPath(new SolidBrush(PointerColor), path);
}
}