123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730 |
- using PaintDotNet.SystemLayer;
- using System;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Windows.Forms;
- namespace PaintDotNet
- {
- /// <summary>
- /// 顶部和左侧的标尺控件
- /// </summary>
- public sealed class Ruler : UserControl
- {
- /// <summary>
- /// 默认单位,英寸
- /// </summary>
- private MeasurementUnit measurementUnit = MeasurementUnit.Inch;
- public MeasurementUnit MeasurementUnit
- {
- get
- {
- return measurementUnit;
- }
- set
- {
- if (value != measurementUnit)
- {
- measurementUnit = value;
- Invalidate();
- }
- }
- }
- /// <summary>
- /// 默认方向 水平
- /// </summary>
- private Orientation orientation = Orientation.Horizontal;
- [DefaultValue(Orientation.Horizontal)]
- public Orientation Orientation
- {
- get
- {
- return orientation;
- }
- set
- {
- if (orientation != value)
- {
- orientation = value;
- Invalidate();
- }
- }
- }
- /// <summary>
- /// 每英寸长度内的像素点数
- /// 默认写死的dpi,96没有实际意义
- /// 需要从标尺读取
- /// </summary>
- private double dpu = 96;
- [DefaultValue(96.0)]
- public double Dpu
- {
- get
- {
- return dpu;
- }
- set
- {
- if (value != dpu)
- {
- dpu = value;
- Invalidate();
- }
- }
- }
- /// <summary>
- /// 封装了缩放功能的结构体
- /// </summary>
- private ScaleFactor scaleFactor = ScaleFactor.OneToOne;
- [Browsable(false)]
- public ScaleFactor ScaleFactor
- {
- get
- {
- return scaleFactor;
- }
- set
- {
- if (scaleFactor != value)
- {
- scaleFactor = value;
- Invalidate();
- }
- }
- }
- private float offset = 0;
- [DefaultValue(0)]
- public float Offset
- {
- get
- {
- return offset;
- }
- set
- {
- if (offset != value)
- {
- offset = value;
- Invalidate();
- }
- }
- }
- private float rulerValue = 0.0f;
- [DefaultValue(0)]
- public float Value
- {
- get
- {
- return rulerValue;
- }
- set
- {
- if (this.rulerValue != value)
- {
- float oldStart = this.scaleFactor.ScaleScalar(this.rulerValue - offset) - 1;
- float oldEnd = this.scaleFactor.ScaleScalar(this.rulerValue + 1 - offset) + 1;
- RectangleF oldRect;
- if (this.orientation == Orientation.Horizontal)
- {
- oldRect = new RectangleF(oldStart, this.ClientRectangle.Top, oldEnd - oldStart, this.ClientRectangle.Height);
- }
- else // if (this.orientation == Orientation.Vertical)
- {
- oldRect = new RectangleF(this.ClientRectangle.Left, oldStart, this.ClientRectangle.Width, oldEnd - oldStart);
- }
- float newStart = this.scaleFactor.ScaleScalar(value - offset);
- float newEnd = this.scaleFactor.ScaleScalar(value + 1 - offset);
- RectangleF newRect;
- if (this.orientation == Orientation.Horizontal)
- {
- newRect = new RectangleF(newStart, this.ClientRectangle.Top, newEnd - newStart, this.ClientRectangle.Height);
- }
- else // if (this.orientation == Orientation.Vertical)
- {
- newRect = new RectangleF(this.ClientRectangle.Left, newStart, this.ClientRectangle.Width, newEnd - newStart);
- }
- this.rulerValue = value;
- Invalidate(Utility.RoundRectangle(oldRect));
- Invalidate(Utility.RoundRectangle(newRect));
- }
- }
- }
- private float highlightStart = 0.0f;
- public float HighlightStart
- {
- get
- {
- return this.highlightStart;
- }
- set
- {
- if (this.highlightStart != value)
- {
- this.highlightStart = value;
- Invalidate();
- }
- }
- }
- private float highlightLength = 0.0f;
- public float HighlightLength
- {
- get
- {
- return this.highlightLength;
- }
- set
- {
- if (this.highlightLength != value)
- {
- this.highlightLength = value;
- Invalidate();
- }
- }
- }
- private bool highlightEnabled = false;
- public bool HighlightEnabled
- {
- get
- {
- return this.highlightEnabled;
- }
- set
- {
- if (this.highlightEnabled != value)
- {
- this.highlightEnabled = value;
- Invalidate();
- }
- }
- }
- /// <summary>
- /// 构造方法
- /// </summary>
- public Ruler()
- {
- SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
- }
- protected override void OnPaint(PaintEventArgs e)
- {
- float valueStart = this.scaleFactor.ScaleScalar(this.rulerValue - offset);
- float valueEnd = this.scaleFactor.ScaleScalar(this.rulerValue + 1.0f - offset);
- float highlightStartPx = this.scaleFactor.ScaleScalar(this.highlightStart - offset);
- float highlightEndPx = this.scaleFactor.ScaleScalar(this.highlightStart + this.highlightLength - offset);
- RectangleF highlightRect;
- RectangleF valueRect;
- if (this.orientation == Orientation.Horizontal)
- {
- valueRect = new RectangleF(valueStart, this.ClientRectangle.Top, valueEnd - valueStart, this.ClientRectangle.Height);
- highlightRect = new RectangleF(highlightStartPx, this.ClientRectangle.Top, highlightEndPx - highlightStartPx, this.ClientRectangle.Height);
- }
- else // if (this.orientation == Orientation.Vertical)
- {
- valueRect = new RectangleF(this.ClientRectangle.Left, valueStart, this.ClientRectangle.Width, valueEnd - valueStart);
- highlightRect = new RectangleF(this.ClientRectangle.Left, highlightStartPx, this.ClientRectangle.Width, highlightEndPx - highlightStartPx);
- }
- if (!this.highlightEnabled)
- {
- highlightRect = RectangleF.Empty;
- }
- if (this.orientation == Orientation.Horizontal)
- {
- e.Graphics.DrawLine(
- SystemPens.WindowText,
- UI.ScaleWidth(15),
- ClientRectangle.Top,
- UI.ScaleWidth(15),
- ClientRectangle.Bottom);
- string abbStringName = "MeasurementUnit." + this.MeasurementUnit.ToString() + ".Abbreviation";
- string abbString = PdnResources.GetString(abbStringName);
- //e.Graphics.DrawString(abbString, Font, SystemBrushes.WindowText, UI.ScaleWidth(-2), 0);
- }
- Region clipRegion = new Region(highlightRect);
- clipRegion.Xor(valueRect);
- if (this.orientation == Orientation.Horizontal)
- {
- clipRegion.Exclude(new Rectangle(0, 0, UI.ScaleWidth(16), ClientRectangle.Height));
- }
- e.Graphics.SetClip(clipRegion, CombineMode.Replace);
- DrawRuler(e, true);
- clipRegion.Xor(this.ClientRectangle);
- if (this.orientation == Orientation.Horizontal)
- {
- clipRegion.Exclude(new Rectangle(0, 0, UI.ScaleWidth(16), ClientRectangle.Height - 1));
- }
- e.Graphics.SetClip(clipRegion, CombineMode.Replace);
- DrawRuler(e, false);
- clipRegion.Dispose();
- }
- private static readonly float[] majorDivisors =
- new float[]
- {
- 10.0f,
- 10.0f,
- 10.0f
- };
- private int[] GetSubdivs(MeasurementUnit unit)
- {
- switch (unit)
- {
- case MeasurementUnit.Inch:
- {
- return new int[] { 2 };
- }
- case MeasurementUnit.Mil:
- {
- return new int[] { 2 };
- }
- case MeasurementUnit.Centimeter:
- {
- return new int[] { 2 };
- }
- case MeasurementUnit.Millimeter:
- {
- return new int[] { 2 };
- }
- case MeasurementUnit.Micron:
- {
- return new int[] { 2 };
- }
- case MeasurementUnit.Nano:
- {
- return new int[] { 2 };
- }
- default:
- {
- return null;
- }
- }
- }
- /// <summary>
- /// 分割x轴
- /// </summary>
- /// <param name="g"></param>
- /// <param name="pen"></param>
- /// <param name="x"></param>
- /// <param name="delta"></param>
- /// <param name="index"></param>
- /// <param name="y"></param>
- /// <param name="height"></param>
- /// <param name="subdivs"></param>
- private void SubdivideX(
- Graphics g,
- Pen pen,
- float x,
- float delta,
- int index,
- float y,
- float height,
- int[] subdivs)
- {
- g.DrawLine(pen, x, y, x, y + height);
- if (index > 10)
- {
- return;
- }
- float div;
- if (subdivs != null && index >= 0)
- {
- div = subdivs[index % subdivs.Length];
- }
- else if (index < 0)
- {
- div = majorDivisors[(-index - 1) % majorDivisors.Length];
- }
- else
- {
- return;
- }
- for (int i = 0; i < div; i++)
- {
- if ((delta / div) > 3.5)
- {
- SubdivideX(g, pen, x + delta * i / div, delta / div, index + 1, y, height / div + 0.5f, subdivs);
- }
- }
- }
- /// <summary>
- /// 分割y轴
- /// </summary>
- /// <param name="g"></param>
- /// <param name="pen"></param>
- /// <param name="y"></param>
- /// <param name="delta"></param>
- /// <param name="index"></param>
- /// <param name="x"></param>
- /// <param name="width"></param>
- /// <param name="subdivs"></param>
- private void SubdivideY(
- Graphics g,
- Pen pen,
- float y,
- float delta,
- int index,
- float x,
- float width,
- int[] subdivs)
- {
- g.DrawLine(pen, x, y, x + width, y);
- if (index > 10)
- {
- return;
- }
- float div;
- if (subdivs != null && index >= 0)
- {
- div = subdivs[index % subdivs.Length];
- }
- else if (index < 0)
- {
- div = majorDivisors[(-index - 1) % majorDivisors.Length];
- }
- else
- {
- return;
- }
- for (int i = 0; i < div; i++)
- {
- if ((delta / div) > 3.5)
- {
- SubdivideY(g, pen, y + delta * i / div, delta / div, index + 1, x, width / div + 0.5f, subdivs);
- }
- }
- }
- /// <summary>
- /// 绘制标尺
- /// </summary>
- /// <param name="e"></param>
- /// <param name="highlighted"></param>
- private void DrawRuler(PaintEventArgs e, bool highlighted)
- {
- Pen pen;
- Brush cursorBrush;
- Brush textBrush;
- StringFormat textFormat = new StringFormat();
- int maxPixel;
- Color cursorColor;
- /**
- if (highlighted)
- {
- e.Graphics.Clear(SystemColors.Highlight);
- pen = SystemPens.HighlightText;
- textBrush = SystemBrushes.HighlightText;
- cursorColor = SystemColors.Window;
- }
- else
- {
- e.Graphics.Clear(SystemColors.Window);
- pen = SystemPens.WindowText;
- textBrush = SystemBrushes.WindowText;
- cursorColor = SystemColors.Highlight;
- }**/
- pen = SystemPens.WindowText;
- textBrush = SystemBrushes.WindowText;
- cursorColor = SystemColors.Highlight;
- cursorColor = Color.FromArgb(128, cursorColor);
- cursorBrush = new SolidBrush(cursorColor);
- if (orientation == Orientation.Horizontal)
- {
- maxPixel = ScaleFactor.UnscaleScalar(ClientRectangle.Width);
- textFormat.Alignment = StringAlignment.Near;
- textFormat.LineAlignment = StringAlignment.Far;
- }
- else // if (orientation == Orientation.Vertical)
- {
- maxPixel = ScaleFactor.UnscaleScalar(ClientRectangle.Height);
- textFormat.Alignment = StringAlignment.Near;
- textFormat.LineAlignment = StringAlignment.Near;
- textFormat.FormatFlags |= StringFormatFlags.DirectionVertical;
- }
- float majorSkip = 1f;
-
- int majorSkipPower = 0;
- float majorDivisionLength = (float)dpu;
- float majorDivisionPixels = (float)ScaleFactor.ScaleScalar(majorDivisionLength);
- int[] subdivs = GetSubdivs(measurementUnit);
- float offsetPixels = ScaleFactor.ScaleScalar((float)offset);
- int startMajor = (int)(offset / majorDivisionLength) - 1;
- int endMajor = (int)((offset + maxPixel) / majorDivisionLength) + 1;
- if (orientation == Orientation.Horizontal)
- {
- // draw Value
- if (!highlighted)
- {
- PointF pt = scaleFactor.ScalePointJustX(new PointF(ClientRectangle.Left + Value - Offset, ClientRectangle.Top));
- SizeF size = new SizeF(Math.Max(1, scaleFactor.ScaleScalar(1.0f)), ClientRectangle.Height);
- pt.X -= 0.5f;
- CompositingMode oldCM = e.Graphics.CompositingMode;
- e.Graphics.CompositingMode = CompositingMode.SourceOver;
- e.Graphics.FillRectangle(cursorBrush, new RectangleF(pt, size));
- e.Graphics.CompositingMode = oldCM;
- }
- // draw border
- e.Graphics.DrawLine(SystemPens.WindowText, new Point(ClientRectangle.Left, ClientRectangle.Bottom - 1),
- new Point(ClientRectangle.Right - 1, ClientRectangle.Bottom - 1));
- }
- else if (orientation == Orientation.Vertical)
- {
- // draw Value
- if (!highlighted)
- {
- PointF pt = scaleFactor.ScalePointJustY(new PointF(ClientRectangle.Left, ClientRectangle.Top + Value - Offset));
- SizeF size = new SizeF(ClientRectangle.Width, Math.Max(1, scaleFactor.ScaleScalar(1.0f)));
- pt.Y -= 0.5f;
- CompositingMode oldCM = e.Graphics.CompositingMode;
- e.Graphics.CompositingMode = CompositingMode.SourceOver;
- e.Graphics.FillRectangle(cursorBrush, new RectangleF(pt, size));
- e.Graphics.CompositingMode = oldCM;
- }
- // draw border
- e.Graphics.DrawLine(SystemPens.WindowText, new Point(ClientRectangle.Right - 1, ClientRectangle.Top),
- new Point(ClientRectangle.Right - 1, ClientRectangle.Bottom - 1));
- }
- while (majorDivisionPixels * majorSkip < 60)
- {
- majorSkip *= majorDivisors[majorSkipPower % majorDivisors.Length];
- ++majorSkipPower;
- }
- startMajor = (int)Math.Round((majorSkip * Math.Floor(startMajor / (double)majorSkip)));
- //decimal skip = Math.Round(Convert.ToDecimal(majorSkip), 1, MidpointRounding.AwayFromZero);
- //if(skip == 0)
- //{
- // skip = Math.Round(Convert.ToDecimal(majorSkip), 4, MidpointRounding.AwayFromZero);
- //}
- for (float major = startMajor; major <= endMajor; major += majorSkip)//skip
- {
- float majorMarkPos = ((float)major * majorDivisionPixels) - offsetPixels;
- //string majorText = major.ToString();//(Math.Round(Convert.ToDecimal(major), 4, MidpointRounding.AwayFromZero)).ToString();
- if (orientation == Orientation.Horizontal)
- {
- SubdivideX(e.Graphics, pen, ClientRectangle.Left + majorMarkPos, majorDivisionPixels * majorSkip, -majorSkipPower, ClientRectangle.Top, ClientRectangle.Height, subdivs);
- //e.Graphics.DrawString(majorText, Font, textBrush, new PointF(ClientRectangle.Left + majorMarkPos, ClientRectangle.Bottom), textFormat);
- }
- else // if (orientation == Orientation.Vertical)
- {
- SubdivideY(e.Graphics, pen, ClientRectangle.Top + majorMarkPos, majorDivisionPixels * majorSkip, -majorSkipPower, ClientRectangle.Left, ClientRectangle.Width, subdivs);
- // e.Graphics.DrawString(majorText, Font, textBrush, new PointF(ClientRectangle.Left, ClientRectangle.Top + majorMarkPos), textFormat);
- }
- }
- //
- // 以下是绘制文字
- //
- decimal skip = this.SkipNumberCalc(measurementUnit);
- int k = 0;
- int f = this.SkipInterval(measurementUnit);
- for (decimal major = startMajor; major <= endMajor; major += skip)//majorSkip
- {
- float majorMarkPos = ((float)major * majorDivisionPixels) - offsetPixels;
- string majorText = major.ToString();//(Math.Round(Convert.ToDecimal(major), 4, MidpointRounding.AwayFromZero)).ToString();
- if (orientation == Orientation.Horizontal)
- {
- if(k % f == 0)
- {
- e.Graphics.DrawString(majorText, Font, textBrush, new PointF(ClientRectangle.Left + majorMarkPos, ClientRectangle.Bottom), textFormat);
- }
- }
- else // if (orientation == Orientation.Vertical)
- {
- if (k % f == 0)
- {
- e.Graphics.DrawString(majorText, Font, textBrush, new PointF(ClientRectangle.Left, ClientRectangle.Top + majorMarkPos), textFormat);
- }
- }
- k++;
- }
- textFormat.Dispose();
- }
- /// <summary>
- /// 根据不同单位返回不同的间隔长度
- /// </summary>
- /// <param name="unit"></param>
- /// <returns></returns>
- private decimal SkipNumberCalc(MeasurementUnit unit)
- {
- decimal skip = 100M;
- if (unit == MeasurementUnit.Inch)
- {
- skip = 0.001M;
- }
- else if (unit == MeasurementUnit.Mil)
- {
- skip = 0.1M;//###Mil
- }
- else if (unit == MeasurementUnit.Centimeter)
- {
- skip = 0.01M;
- }
- else if (unit == MeasurementUnit.Millimeter)
- {
- skip = 0.1M;
- }
- else if (unit == MeasurementUnit.Micron)
- {
- skip = 10M;
- }
- else if (unit == MeasurementUnit.Nano)
- {
- skip = 10000M;
- }
- return skip;
- }
- /// <summary>
- /// 不同的缩放比列下,间隔多少单元格绘制文字
- /// </summary>
- /// <param name="unit"></param>
- /// <returns></returns>
- private int SkipInterval(MeasurementUnit unit)
- {
- int f = 1;
- if (scaleFactor.Ratio <= 0.05f)
- {
- switch (unit)
- {
- case MeasurementUnit.Pixel:
- case MeasurementUnit.Centimeter:
- case MeasurementUnit.Millimeter:
- f = 100;
- break;
- case MeasurementUnit.Inch:
- case MeasurementUnit.Mil://###Mil
- case MeasurementUnit.Micron:
- case MeasurementUnit.Nano:
- f = 1000;
- break;
- }
- }
- else if (scaleFactor.Ratio <= 0.1f)
- {
- switch (unit)
- {
- case MeasurementUnit.Pixel:
- case MeasurementUnit.Centimeter:
- case MeasurementUnit.Millimeter:
- f = 10;
- break;
- case MeasurementUnit.Inch:
- case MeasurementUnit.Mil://###Mil
- case MeasurementUnit.Micron:
- case MeasurementUnit.Nano:
- f = 100;
- break;
- }
- }
- else if (scaleFactor.Ratio <= 0.5f)
- {
- switch (unit)
- {
- case MeasurementUnit.Pixel:
- case MeasurementUnit.Centimeter:
- case MeasurementUnit.Millimeter:
- f = 5;
- break;
- case MeasurementUnit.Inch:
- case MeasurementUnit.Mil://###Mil
- case MeasurementUnit.Micron:
- case MeasurementUnit.Nano:
- f = 50;
- break;
- }
- }
- else
- {
- switch (unit)
- {
- case MeasurementUnit.Pixel:
- case MeasurementUnit.Centimeter:
- case MeasurementUnit.Millimeter:
- f = 1;
- break;
- case MeasurementUnit.Inch:
- case MeasurementUnit.Mil://###Mil
- case MeasurementUnit.Micron:
- case MeasurementUnit.Nano:
- f = 10;
- break;
- }
- }
- return f;
- }
- }
- }
|