using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; namespace FurnaceUI.Controls { /// /// 整个组件的代码辅助工具,提供了一个基础的类库方法 /// public class Helper { /// /// 从一个矩形的图形中获取菱形的坐标数组 /// /// 矩形 /// 数组结果 public static Point[] GetRhombusFromRectangle(Rectangle rect) { return new Point[] { new Point(rect.X, rect.Y + rect.Height / 2), new Point(rect.X + rect.Width / 2, rect.Y + rect.Height - 1), new Point(rect.X + rect.Width - 1, rect.Y + rect.Height / 2), new Point(rect.X + rect.Width / 2, rect.Y), new Point(rect.X, rect.Y + rect.Height / 2), }; } /// /// 计算绘图时的相对偏移值 /// /// 0-100分的最大值,就是指准备绘制的最大值 /// 0-100分的最小值,就是指准备绘制的最小值 /// 实际绘图区域的高度 /// 需要绘制数据的当前值 /// 相对于0的位置,还需要增加上面的偏值 public static float ComputePaintLocationY(int max, int min, int height, int value) { if ((max - min) == 0f) { return height; } else { return height - (value - min) * 1.0f / (max - min) * height; } } /// /// 计算绘图时的相对偏移值 /// /// 0-100分的最大值,就是指准备绘制的最大值 /// 0-100分的最小值,就是指准备绘制的最小值 /// 实际绘图区域的高度 /// 需要绘制数据的当前值 /// 相对于0的位置,还需要增加上面的偏值 public static float ComputePaintLocationY(float max, float min, float height, float value) { if ((max - min) == 0f) { return height; } else { return height - (value - min) / (max - min) * height; } } /// /// 绘制坐标系中的刻度线 /// /// 绘图对象 /// 画坐标轴的画笔 /// /// /// /// /// /// /// /// /// /// /// /// /// public static void PaintCoordinateDivide( Graphics g, Pen penLine, Pen penDash, Font font, Brush brush, StringFormat sf, int degree, int max, int min, int width, int height, int left = 60, int right = 8, int up = 8, int down = 8 ) { for (int i = 0; i <= degree; i++) { int value = (max - min) * i / degree + min; int location = (int)ComputePaintLocationY(max, min, (height - up - down), value) + up + 1; g.DrawLine(penLine, left - 1, location, left - 4, location); if (i != 0) { g.DrawLine(penDash, left, location, width - right, location); } g.DrawString(value.ToString(), font, brush, new Rectangle(-5, location - font.Height / 2, left, font.Height), sf); } } /// /// 根据指定的方向绘制一个箭头 /// /// /// /// /// /// public static void PaintTriangle(Graphics g, Brush brush, Point point, int size, GraphDirection direction) { Point[] points = new Point[4]; if (direction == GraphDirection.Leftward) { points[0] = new Point(point.X, point.Y - size); points[1] = new Point(point.X, point.Y + size); points[2] = new Point(point.X - 2 * size, point.Y); } else if (direction == GraphDirection.Rightward) { points[0] = new Point(point.X, point.Y - size); points[1] = new Point(point.X, point.Y + size); points[2] = new Point(point.X + 2 * size, point.Y); } else if (direction == GraphDirection.Upward) { points[0] = new Point(point.X - size, point.Y); points[1] = new Point(point.X + size, point.Y); points[2] = new Point(point.X, point.Y - 2 * size); } else { points[0] = new Point(point.X - size, point.Y); points[1] = new Point(point.X + size, point.Y); points[2] = new Point(point.X, point.Y + 2 * size); } points[3] = points[0]; g.FillPolygon(brush, points); } /// /// 根据指定的方向绘制一个箭头 /// /// /// /// /// /// public static void PaintTriangle(Graphics g, Brush brush, PointF point, int size, GraphDirection direction) { PointF[] points = new PointF[4]; if (direction == GraphDirection.Leftward) { points[0] = new PointF(point.X, point.Y - size); points[1] = new PointF(point.X, point.Y + size); points[2] = new PointF(point.X - 2 * size, point.Y); } else if (direction == GraphDirection.Rightward) { points[0] = new PointF(point.X, point.Y - size); points[1] = new PointF(point.X, point.Y + size); points[2] = new PointF(point.X + 2 * size, point.Y); } else if (direction == GraphDirection.Upward) { points[0] = new PointF(point.X - size, point.Y); points[1] = new PointF(point.X + size, point.Y); points[2] = new PointF(point.X, point.Y - 2 * size); } else { points[0] = new PointF(point.X - size, point.Y); points[1] = new PointF(point.X + size, point.Y); points[2] = new PointF(point.X, point.Y + 2 * size); } points[3] = points[0]; g.FillPolygon(brush, points); } /// /// 一个通用的数组新增个数方法,会自动判断越界情况,越界的情况下,会自动的截断或是填充 -> /// A common array of new methods, will automatically determine the cross-border situation, in the case of cross-border, will be automatically truncated or filled /// /// 数据类型 /// 原数据 /// 等待新增的数据 /// 原数据的最大值 public static void AddArrayData(ref T[] array, T[] data, int max) { if (data == null) return; // 数据为空 if (data.Length == 0) return; // 数据长度为空 if (array.Length == max) { Array.Copy(array, data.Length, array, 0, array.Length - data.Length); Array.Copy(data, 0, array, array.Length - data.Length, data.Length); } else { if ((array.Length + data.Length) > max) { T[] tmp = new T[max]; for (int i = 0; i < (max - data.Length); i++) { tmp[i] = array[i + (array.Length - max + data.Length)]; } for (int i = 0; i < data.Length; i++) { tmp[tmp.Length - data.Length + i] = data[i]; } // 更新数据 array = tmp; } else { T[] tmp = new T[array.Length + data.Length]; for (int i = 0; i < array.Length; i++) { tmp[i] = array[i]; } for (int i = 0; i < data.Length; i++) { tmp[tmp.Length - data.Length + i] = data[i]; } array = tmp; } } } /// /// 尺寸转换,计算旋转后的尺寸。 /// /// /// /// public static SizeF ConvertSize(SizeF size, float angle) { Matrix matrix = new Matrix(); matrix.Rotate(angle); // 旋转矩形四个顶点 PointF[] pts = new PointF[4]; pts[0].X = -size.Width / 2f; pts[0].Y = -size.Height / 2f; pts[1].X = -size.Width / 2f; pts[1].Y = size.Height / 2f; pts[2].X = size.Width / 2f; pts[2].Y = size.Height / 2f; pts[3].X = size.Width / 2f; pts[3].Y = -size.Height / 2f; matrix.TransformPoints(pts); // 求取四个顶点的包围盒 float left = float.MaxValue; float right = float.MinValue; float top = float.MaxValue; float bottom = float.MinValue; foreach (PointF pt in pts) { // 求取并集 if (pt.X < left) left = pt.X; if (pt.X > right) right = pt.X; if (pt.Y < top) top = pt.Y; if (pt.Y > bottom) bottom = pt.Y; } SizeF result = new SizeF(right - left, bottom - top); return result; } /// /// 绘制旋转文本 /// /// /// /// /// /// /// /// public static void DrawString(Graphics g, string s, Font font, Brush brush, PointF point, StringFormat format, float angle) { // Save the matrix Matrix mtxSave = g.Transform; Matrix mtxRotate = g.Transform; mtxRotate.RotateAt(angle, point); g.Transform = mtxRotate; g.DrawString(s, font, brush, point, format); // Reset the matrix g.Transform = mtxSave; } private static int GetPow(int digit) { int result = 1; for (int i = 0; i < digit; i++) { result *= 10; } return result; } /// /// 获得数据的上限值,这个上限值是自动计算的。 /// /// 数据值 /// 数据值 public static int CalculateMaxSectionFrom(int[] values) { int max = values.Max(); if (max <= 5) return 5; if (max <= 10) return 10; int digit = max.ToString().Length - 2; int head = int.Parse(max.ToString().Substring(0, 2)); if (head < 12) return 12 * GetPow(digit); if (head < 14) return 14 * GetPow(digit); if (head < 16) return 16 * GetPow(digit); if (head < 18) return 18 * GetPow(digit); if (head < 20) return 20 * GetPow(digit); if (head < 22) return 22 * GetPow(digit); if (head < 24) return 24 * GetPow(digit); if (head < 26) return 26 * GetPow(digit); if (head < 28) return 28 * GetPow(digit); if (head < 30) return 30 * GetPow(digit); if (head < 40) return 40 * GetPow(digit); if (head < 50) return 50 * GetPow(digit); if (head < 60) return 60 * GetPow(digit); if (head < 80) return 80 * GetPow(digit); return 100 * GetPow(digit); } /// /// 获取当前颜色更淡的颜色信息 /// /// 颜色信息 /// 颜色 public static Color GetColorLight(Color color) { return Color.FromArgb(color.R + (255 - color.R) * 40 / 100, color.G + (255 - color.G) * 40 / 100, color.B + (255 - color.B) * 40 / 100); } /// /// 获取当前颜色更淡的颜色信息 /// /// 颜色信息 /// 颜色 public static Color GetColorLightFive(Color color) { return Color.FromArgb(color.R + (255 - color.R) * 50 / 100, color.G + (255 - color.G) * 50 / 100, color.B + (255 - color.B) * 50 / 100); } #if NET45 /// /// 获取当前颜色更淡的颜色信息 /// /// 颜色信息 /// 颜色 public static System.Windows.Media.Color GetColorLight( System.Windows.Media.Color color ) { return System.Windows.Media.Color.FromRgb( (byte)(color.R + (255 - color.R) * 40 / 100), (byte)(color.G + (255 - color.G) * 40 / 100), (byte)(color.B + (255 - color.B) * 40 / 100) ); } /// /// 获取当前颜色更淡的颜色信息 /// /// 颜色信息 /// 颜色 public static System.Windows.Media.Color GetColorLightFive( System.Windows.Media.Color color ) { return System.Windows.Media.Color.FromRgb( (byte)(color.R + (255 - color.R) * 50 / 100), (byte)(color.G + (255 - color.G) * 50 / 100), (byte)(color.B + (255 - color.B) * 50 / 100) ); } #endif /// /// 从字符串表示的点位信息里解析出真正的点位信息 /// /// 字符串的点位 /// 原来的长度信息 /// 原来的高度信息 /// 实际的宽度信息 /// 实际的高度信息 /// x偏移量信息 /// y偏移量信息 /// public static PointF[] GetPointsFrom(string points, float soureWidth, float sourceHeight, float width, float height, float dx = 0, float dy = 0) { string[] itemPoint = points.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); PointF[] ret = new PointF[itemPoint.Length]; for (int i = 0; i < itemPoint.Length; i++) { int index = itemPoint[i].IndexOf(','); float x = Convert.ToSingle(itemPoint[i].Substring(0, index)); float y = Convert.ToSingle(itemPoint[i].Substring(index + 1)); ret[i] = new PointF(width * (x + dx) / soureWidth, height * (y + dy) / sourceHeight); } return ret; } } /// /// 图形的方向 /// public enum GraphDirection { /// /// 向上 /// Upward = 1, /// /// 向下 /// Downward = 2, /// /// 向左 /// Leftward = 3, /// /// 向右 /// Rightward = 4, } /// /// 指示控件的样子 /// public enum HslDirectionStyle { /// /// 控件是横向摆放的 /// Horizontal = 1, /// /// 控件是纵向摆放的 /// Vertical = 2 } /// /// 系统的主题样式,将会改变一些控件的外观 /// public enum HslThemeStyle { /// /// 浅色的主题 /// Light = 1, /// /// 深色的主题 /// Dark = 2, } /// /// 某些特殊图形的表现形式 /// public enum HslRenderStyle { /// /// 椭圆 /// Ellipse = 1, /// /// 矩形 /// Rectangle = 2, /// /// 菱形 /// Rhombus = 3 } /// /// 包含整型和字符串描述的数据类型 /// public struct Paintdata { /// /// 数量 /// public int Count { get; set; } /// /// 描述 /// public string Description { get; set; } } /// /// 计算的基础数据 /// public class CenterPoint { /// /// 中心点的位置 /// public Point Point { get; set; } /// /// 半径 /// public int Radius { get; set; } /// /// 角度 /// public double Angle { get; set; } } }