using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.LinkLabel;
namespace CarQueueProgram
{
/// <summary>
/// 刻度尺控件
/// </summary>
public partial class Ruler : UserControl
{
private const int _monitorDPI = 96;
public Ruler()
{
InitializeComponent();
}
/// <summary>
/// 刻度枚举
/// </summary>
public DegreeIntervalEnum DegreeInterval { get; set; } = DegreeIntervalEnum.PointOne;
/// <summary>
/// 开始数字
/// </summary>
public int StartNum { get; set; } = 0;
/// <summary>
/// 结束数字
/// </summary>
public int EndNum { get; set; } = 10;
/// <summary>
/// 指定数字的倍数, 依据数字的倍数来显示相关数字. 如: 此属性设置为3, 刻度尺上显示的数字就是0, 3, 6, 9...
/// </summary>
public int MultipleNum { get; set; } = 1;
/// <summary>
/// 背景颜色
/// </summary>
public override Color BackColor { get; set; } = Color.Transparent;
/// <summary>
/// 设置线条颜色
/// </summary>
public override Color ForeColor { get; set; } = Color.Black;
/// <summary>
/// 字体设置
/// </summary>
public override Font Font { get; set; } = new Font("Arial", 9);
/// <summary>
/// 刻度是否向上
/// </summary>
public bool IsDegreeUp { get; set; } = false;
/// <summary>
/// 缩放比例
/// </summary>
public float Scaling { get; set; } = 1f;
/// <summary>
/// 设置刻度尺到左侧的距离
/// </summary>
public int OffsetLeft { get; set; } = 6;
/// <summary>
/// 刻度尺长度
/// </summary>
public int RulerLength
{
get
{
if (EndNum <= StartNum)
{
throw new ArgumentOutOfRangeException(nameof(EndNum), $"{nameof(EndNum)}数值不可以小于等于{nameof(StartNum)}数值!");
}
return EndNum - StartNum;
}
}
protected override void OnPaint(PaintEventArgs e)
{
if (EndNum <= StartNum)
{
throw new ArgumentOutOfRangeException(nameof(EndNum), $"{nameof(EndNum)}数值不可以小于等于{nameof(StartNum)}数值!");
}
var g = e.Graphics;
using (var pen = new Pen(ForeColor))
{
//如果刻度向上则取客户端设置的高度数值, 如果刻度向下, 需要减去设置的字体高度和2(该数字是刻度线和刻度数值的间距)
int rectH = Height - (IsDegreeUp ? 0 : (Font.Height + 2));
//绘制矩形
Rectangle rectangle = new Rectangle(0, 0, Width, Height);
//填充矩形颜色(通过BackColor设置)
Brush brush = new SolidBrush(BackColor);
g.FillRectangle(brush, rectangle);
//绘制一条直线
float lineY = rectH / 2f;
g.DrawLine(pen, new PointF(0, lineY), new PointF(Width, lineY));
//绘制刻度
var degreesCount = GetDegreesCount();
var degreeInterval = GetDegreeInterval();
decimal num = StartNum;
for (int i = 0; i < degreesCount; i++)
{
//刻度线的x坐标(依据索引值(i)不同而变化)
float x = GetXCoordinate(i, Scaling, OffsetLeft);
PointF startPoint;
PointF endPoint;
//如果是需要显示的倍数(举例: MultipleNum为2, 那么需要显示的数值为0, 2, 4, 6...)
if (num % MultipleNum == 0M)
{
startPoint = GetStartPoint(x, 1f, lineY);
endPoint = GetEndPoint(x, 1f, lineY);
string numStr = ((int)num).ToString();
//获取字符串大小信息
SizeF strSize = g.MeasureString(numStr, Font);
//字符串宽度
float strWidth = strSize.Width;
//字体宽度
float fontWidth = strWidth / numStr.Length;
//获取字符串的节点位置
PointF strPoint = GetStrPoint(x, fontWidth, numStr.Length, 1f, lineY);
g.DrawString(numStr, Font, new SolidBrush(ForeColor), strPoint);
}
//如果刻度线的索引值是5的倍数(比如0-1之间的0.5刻度线)
else if (num % 5M == 0M)
{
startPoint = GetStartPoint(x, 0.5f, lineY);
endPoint = GetEndPoint(x, 0.5f, lineY);
}
else
{
startPoint = GetStartPoint(x, 0.25f, lineY);
endPoint = GetEndPoint(x, 0.25f, lineY);
}
g.DrawLine(pen, startPoint, endPoint);
num += degreeInterval;
}
}
}
/// <summary>
/// 获取刻度尺总数
/// </summary>
/// <returns></returns>
private int GetDegreesCount()
{
int num = EndNum - StartNum;
int degreesCount;
if (DegreeInterval == DegreeIntervalEnum.One)
{
degreesCount = (num / 1) + 1;
}
else
{
degreesCount = (int)(num / 0.1M) + 1;
}
return degreesCount;
}
/// <summary>
/// 获取每刻度代表多少数值
/// </summary>
/// <returns></returns>
private decimal GetDegreeInterval()
{
decimal degreeInterval;
if (DegreeInterval == DegreeIntervalEnum.One)
{
degreeInterval = 1M;
}
else
{
degreeInterval = 0.1M;
}
return degreeInterval;
}
/// <summary>
/// 获取刻度线的起始节点(为画刻度线准备)
/// </summary>
/// <param name="x">刻度线的x坐标</param>
/// <param name="multiple">
/// 刻度线长度的倍数,
/// 如果是需要显示数值的刻度线, 倍数是1;
/// 如果刻度线的索引值是5的倍数, 倍数是0.5;
/// 如果是普通的刻度线, 倍数是0.25;
/// </param>
/// <param name="lineY">刻度尺直线条的y坐标</param>
/// <returns></returns>
private PointF GetStartPoint(float x, float multiple, float lineY)
{
PointF startPoint;
if (IsDegreeUp)
{
startPoint = new PointF(x, (1 - multiple) * lineY);
}
else
{
startPoint = new PointF(x, lineY);
}
return startPoint;
}
/// <summary>
/// 获取刻度线的结束节点(为画刻度线准备)
/// </summary>
/// <param name="x">刻度线的x坐标</param>
/// <param name="multiple">
/// 刻度线长度的倍数,
/// 如果是需要显示数值的刻度线, 倍数是1;
/// 如果刻度线的索引值是5的倍数, 倍数是0.5;
/// 如果是普通的刻度线, 倍数是0.25;
/// </param>
/// <param name="lineY">刻度尺直线条的y坐标</param>
/// <returns></returns>
private PointF GetEndPoint(float x, float multiple, float lineY)
{
PointF endPoint;
if (IsDegreeUp)
{
endPoint = new PointF(x, lineY);
}
else
{
endPoint = new PointF(x, (1 + multiple) * lineY);
}
return endPoint;
}
/// <summary>
/// 获取字符串的节点位置
/// </summary>
/// <param name="x">刻度线的x坐标</param>
/// <param name="fontWidth">字体宽度</param>
/// <param name="strLen">字符串长度</param>
/// <param name="multiple">
/// 刻度线长度的倍数,
/// 如果是需要显示数值的刻度线, 倍数是1;
/// 如果刻度线的索引值是5的倍数, 倍数是0.5;
/// 如果是普通的刻度线, 倍数是0.25;
/// </param>
/// <param name="lineY">刻度尺直线条的y坐标</param>
/// <returns></returns>
private PointF GetStrPoint(float x, float fontWidth, int strLen, float multiple, float lineY)
{
//字符串的x坐标是刻度线坐标值减去半个长度的字符串乘以字体宽度的积
float xVal = x - fontWidth * (strLen * 1.0f / 2);
float yVal;
if (IsDegreeUp)
{
yVal = lineY + 2;
}
else
{
yVal = (1 + multiple) * lineY + 2;
}
var point = new PointF(xVal, yVal);
return point;
}
/// <summary>
/// 获取x轴坐标
/// </summary>
/// <param name="degree">刻度</param>
/// <returns></returns>
public static float GetXCoordinate(float degree, float scaling, int offset)
{
float x = _monitorDPI / 25.4f * degree * scaling + offset;
return x;
}
/// <summary>
/// 刻度枚举
/// </summary>
public enum DegreeIntervalEnum
{
/// <summary>
/// 0.1
/// </summary>
PointOne,
/// <summary>
/// 1
/// </summary>
One
}
}
}
一定程度上参考了“C#窗体加标尺的两种方式及显现效果_c#标尺_冰的学习时光的博客-CSDN博客”这个博客。对此博主表示一定的感谢,也希望我的实现能够帮助到大家,同时也欢迎大家提出改进的建议
文章介绍了一个C#的自定义用户控件Ruler,用于创建刻度尺效果。该控件支持设置刻度间隔、开始和结束数值、背景色、线条颜色、字体等属性。在OnPaint方法中绘制刻度和数值,提供了灵活性和可配置性。代码中包含了错误检查和缩放比例调整等功能,适用于WindowsForms应用程序的界面设计。

1800

被折叠的 条评论
为什么被折叠?



