效果如下:
简单谈下设计思路:
应该说绘制上和下的标尺没有分别.左和右的标尺无非就是绘制文字和刻度时横纵坐标的调整而已.绘制刻度的单位是象素.因为很可能在以后的使用中会同时需要使用dock = top和dock = left的两个标尺,组成坐标系,所以为了使他们的点不交叉,提供了一个MoveValue的属性,让他们的原点移动指定值后开始绘制.因为绘制的方法很简单, 下面直接给出代码:
源代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.IO;
namespace JcsControlLibrary
{
public partial class JcsRuler : Panel
{
//一般版式的format
StringFormat format = new StringFormat(StringFormat.GenericTypographic);
private int _ScaleValue;//刻度转换基数
private int _BaseStep;//最小刻度的基数
private int _NextSmallScale;//次小刻度的基数
private int _BigScale;//最长刻度线的基数
private int _ShowNumberScale;//显示数字的基数
private DrawUnit _DrawUnit;//单位
private float Stroke = 3;//绘制一笔的基数
private int RulerLength;//尺的长度
//private int RulerWidth = 21;//适合宽度或高度
private int _MoveValue = 21;//原点移动调整值
private LayoutType _LayoutType = LayoutType.NoneLayout;//布局状态
private bool _IsShowNumber = true;//是否显示数值
private Color _NextScaleColor = Color.Black ;//次小刻度的颜色
private Color _BigScaleColor = Color.Black;//最大刻度的颜色
private Color _BaseStepColor = Color.Black;//最小基本刻度的颜色
private Color _NumberColor = Color.Black; //刻度值的颜色
private bool _IsShowUnitCaption = false;//是否显示单位标题
//private bool _IsBorder
#region"Enum"
/// <summary>
/// 布局状态
/// </summary>
public enum LayoutType
{
HorizontalTop,
HorizontalBottom,
VerticalLeft,
VerticalRight,
NoneLayout
}
/// <summary>
/// 绘制的单位(象素,厘米,英寸)
/// </summary>
public enum DrawUnit
{
Pixels,
Cm,
Inch
}
#endregion
public JcsRuler()
{
InitializeComponent();
this.RulerLength = this.Width;
format.FormatFlags = StringFormatFlags.NoWrap;
format.Trimming = StringTrimming.Character;
}
#region"Property"
/// <summary>
/// 绘制刻度时候的放大基数(不允许为非正数)
/// </summary>
[CategoryAttribute("JcsControl属性"), DescriptionAttribute("绘制刻度的放大基数")]
public float BaseStroke
{
get
{
return this.Stroke;
}
set
{
if (value <= 0)
{
throw new Exception("绘制刻度的放大基数不允许为0或负数!");
}
this.Stroke = value;
this.Invalidate();
}
}
/// <summary>
/// 当前应用的绘制单位
/// </summary>
[CategoryAttribute("JcsControl属性"), DescriptionAttribute("当前应用的绘制单位")]
public DrawUnit CurrenDrawtUnit
{
get
{
return this._DrawUnit ;
}
set
{
this._DrawUnit = value;
this.Invalidate();
}
}
/// <summary>
/// 是否绘制刻度值
/// </summary>
[Category("JcsControl属性"),Description("是否绘制刻度值"),DefaultValue(true)]
public bool IsDrawNumber
{
get
{
return this._IsShowNumber;
}
set
{
this._IsShowNumber = value;
this.Invalidate();
}
}
/// <summary>
/// 最小刻度的颜色
/// </summary>
[Category("JcsControl属性"), Description("最小刻度的颜色"),DefaultValue(typeof(Color), "Black")]
public Color BaseStepColor
{
get
{
return this._BaseStepColor ;
}
set
{
this._BaseStepColor = value;
this.Invalidate();
}
}
/// <summary>
/// 次小刻度的颜色
/// </summary>
[Category("JcsControl属性"), Description("次小刻度的颜色"),DefaultValue(typeof(Color), "Black")]
public Color NextScaleColor
{
get
{
return this._NextScaleColor;
}
set
{
this._NextScaleColor = value;
this.Invalidate();
}
}
/// <summary>
/// 最大刻度的颜色
/// </summary>
[Category("JcsControl属性"), Description("最大刻度的颜色"),DefaultValue(typeof(Color), "Black")]
public Color BigScaleColor
{
get
{
return this._BigScaleColor ;
}
set
{
this._BigScaleColor = value;
this.Invalidate();
}
}
/// <summary>
/// 刻度数值的颜色
/// </summary>
[Category("JcsControl属性"), Description("刻度数值的颜色"),DefaultValue(typeof(Color),"Black")]
public Color NumberColor
{
get
{
return this._NumberColor;
}
set
{
this._NumberColor = value;
this.Invalidate();
}
}
/// <summary>
/// 是否显示当前单位标题
/// </summary>
[Category("JcsControl属性"), Description("是否显示当前单位标题"),DefaultValue(false)]
public bool IsShowUnitCaption
{
get
{
return this._IsShowUnitCaption;
}
set
{
this._IsShowUnitCaption = value;
this.Invalidate();
}
}
/// <summary>
/// 原点移动调整值
/// </summary>
[Category("JcsControl属性"), Description("原点移动调整值"), DefaultValue(21)]
public int MoveValue
{
get
{
return this._MoveValue ;
}
set
{
this._MoveValue = value;
this.Invalidate();
}
}
#endregion
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
drawruler(e.Graphics);
}
private void drawruler(Graphics g)
{
switch (this._DrawUnit)
{
case DrawUnit.Pixels :
_BaseStep = 5;
_NextSmallScale = 10;
_BigScale = 50;
_ShowNumberScale = 100;
_ScaleValue = 1;
break;
case DrawUnit.Cm:
g.PageUnit = GraphicsUnit.Millimeter;
g.PageScale = 1f;
_BaseStep = 1;
_NextSmallScale = 5;
_BigScale = 10;
_ShowNumberScale = 10;
_ScaleValue = 10;
break;
case DrawUnit.Inch :
g.PageUnit = GraphicsUnit.Inch;
g.PageScale = 1f / 12f;
_BaseStep = 1;
_NextSmallScale = 2;
_BigScale = 6;
_ShowNumberScale = 12;
_ScaleValue = 12;
break;
}
//PointF[] point = new PointF[] {
// new PointF(2, 2), new PointF(5, 5), new Point(this.Size), this.Location};
////进行坐标系的转换,从驱动坐标,也就是通常以象素为坐标的坐标系向世界坐标转换(目标坐标,源坐标,点集合)
//g.TransformPoints(CoordinateSpace.World, CoordinateSpace.Device, point);
switch (this._LayoutType)
{
case LayoutType.NoneLayout:
DrawRulerAtLayoutTop(g);
break;
case LayoutType.HorizontalTop:
DrawRulerAtLayoutTop(g);
break;
case LayoutType.HorizontalBottom:
DrawRulerAtLayoutTop(g);
break;
case LayoutType.VerticalLeft:
DrawRulerAtLayoutLeft(g);
break;
case LayoutType.VerticalRight:
DrawRulerAtLayoutRight(g);
break;
}
}
private void DrawRulerAtLayoutTop(Graphics g)
{
//ControlPaint.DarkDark(SystemColors.ControlDarkDark);
ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, this.Width, this.Height / 2));
for (int i = 0; i < RulerLength; i += _BaseStep)
{
float d = 1;//最小刻度的线长默认为1
using (Pen pen = new Pen(Color.Black, 1.8f))
{
pen.Color = this._BaseStepColor;
if (i % _NextSmallScale == 0)
{
if (i % _BigScale == 0)
{
d = 3;//最大线长为3
pen.Color = this._BigScaleColor;
}
else
{
d = 2;//次小线长为2
pen.Color = this._NextScaleColor;
}
}
g.DrawLine(pen, i + _MoveValue, 0f, i + _MoveValue, d * Stroke);
}
if (this._IsShowNumber)
{
if ((i % _ShowNumberScale) == 0)
{
//获取不依赖区域特性的字符
string text = (i / _ScaleValue).ToString(CultureInfo.InvariantCulture);
SizeF size = g.MeasureString(text, this.Font, RulerLength, this.format);
using (SolidBrush b = new SolidBrush(this._NumberColor))
{
g.DrawString(text, this.Font,b, i + _MoveValue - size.Width / 2, d * Stroke, this.format);
}
}
}
if (this._IsShowUnitCaption)
{
string text = this.GetDrawUnitString(_DrawUnit);
SizeF size = g.MeasureString(text, this.Font, RulerLength, this.format);
if (this._MoveValue > size.Width+1)
{
using (SolidBrush b = new SolidBrush(this._NumberColor))
{
g.DrawString(text, this.Font, b, 1, 1, this.format);
}
}
}
}
}
private void DrawRulerAtLayoutLeft(Graphics g)
{
for (int i = 0; i < RulerLength; i += _BaseStep)
{
float d = 1;//最小刻度的线长默认为1
using (Pen pen = new Pen(Color.Black, 1.8f))
{
pen.Color = this._BaseStepColor;
if (i % _NextSmallScale == 0)
{
if (i % _BigScale == 0)
{
d = 3;//最大线长为3
pen.Color = this._BigScaleColor;
}
else
{
d = 2;//次小线长为2
pen.Color = this._NextScaleColor ;
}
}
g.DrawLine(pen, this.Width - d * Stroke, i + _MoveValue, this.Width, i + _MoveValue);
}
if (this._IsShowNumber)
{
if ((i % _ShowNumberScale) == 0)
{
//获取不依赖区域特性的字符
string text = (i / _ScaleValue).ToString(CultureInfo.InvariantCulture);
SizeF size = g.MeasureString(text, this.Font, RulerLength, this.format);
using (SolidBrush b = new SolidBrush(this._NumberColor))
{
g.DrawString(text, this.Font, b, this.Width - d * Stroke - size.Width, i + _MoveValue - size.Height / 2, this.format);
}
}
}
}
}
private void DrawRulerAtLayoutRight(Graphics g)
{
for (int i = 0; i < RulerLength; i += _BaseStep)
{
float d = 1;//最小刻度的线长默认为1
using (Pen pen = new Pen(Color.Black, 1.8f))
{
pen.Color = this._BaseStepColor;
if (i % _NextSmallScale == 0)
{
if (i % _BigScale == 0)
{
d = 3;//最大线长为3
pen.Color = this._BigScaleColor;
}
else
{
d = 2;//次小线长为2
pen.Color = this._NextScaleColor ;
}
}
g.DrawLine(pen, 0, i + _MoveValue, d * Stroke, i + _MoveValue);
}
if (this._IsShowNumber)
{
if ((i % _ShowNumberScale) == 0)
{
//获取不依赖区域特性的字符
string text = (i / _ScaleValue).ToString(CultureInfo.InvariantCulture);
SizeF size = g.MeasureString(text, this.Font, RulerLength, this.format);
using (SolidBrush b = new SolidBrush(this._NumberColor))
{
g.DrawString(text, this.Font,b, d * Stroke, i + _MoveValue - size.Height / 2, this.format);
}
}
}
}
}
private void GetRulerWidth()
{
switch (this.Dock)
{
case DockStyle.Top:
this._LayoutType = LayoutType.HorizontalTop;
this.RulerLength = this.Width;
break;
case DockStyle.Left:
this._LayoutType = LayoutType.VerticalLeft;
this.RulerLength = this.Height;
break;
case DockStyle.Right:
this._LayoutType = LayoutType.VerticalRight;
this.RulerLength = this.Height;
break;
case DockStyle.Bottom:
this._LayoutType = LayoutType.HorizontalBottom;
this.RulerLength = this.Width;
break;
case DockStyle.None:
if (this.Width >= this.Height)
{
this._LayoutType = LayoutType.NoneLayout;
this.RulerLength = this.Width;
break;
}
else
{
this._LayoutType = LayoutType.NoneLayout;
this.RulerLength = this.Height;
break;
}
}
}
private string GetDrawUnitString(DrawUnit u)
{
string returnstring = null;
if (u == DrawUnit.Inch)
{
returnstring = "In";
}
else if(u == DrawUnit.Cm )
{
returnstring = "Cm";
}
else if (u == DrawUnit.Pixels )
{
returnstring = "Px";
}
return returnstring;
}
protected override void OnResize(EventArgs eventargs)
{
base.OnResize(eventargs);
this.GetRulerWidth();
}
}
}