效果如下:
简单谈下设计思路:
应该说绘制上和下的标尺没有分别.左和右的标尺无非就是绘制文字和刻度时横纵坐标的调整而已.绘制刻度的单位是象素.因为很可能在以后的使用中会同时需要使用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(); } }}