马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

c#Winform自定义控件-雷达图

[复制链接]
查看1870 | 回复0 | 2019-9-26 09:17:42 | 显示全部楼层 |阅读模式

条件

入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。

GitHub:https://github.com/kwwwvagaa/NetWinformControl

码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git

如果觉得写的还行,请点个 star 支持一下吧

接待前来互换探究: 企鹅群568015492

092050rxv2wivruyycoe60.png

麻烦博客下方点个【保举】,谢谢

NuGet

  1. Install-Package HZH_Controls
复制代码

目次

https://www.cnblogs.com/bfyx/p/11364884.html

用处及效果

092050lhrzbloxxbi71xtx.png

预备工作

GDI+画的,不会的可以先百度了解下

开始

添加一个类UCRadarChart ,继承 UserControl

添加一些控制属性

  1. 1 /// <summary>
  2. 2 /// The split count
  3. 3 /// </summary>
  4. 4 private int splitCount = 5;
  5. 5 /// <summary>
  6. 6 /// Gets or sets the split count.
  7. 7 /// </summary>
  8. 8 /// <value>The split count.</value>
  9. 9 [Browsable(true)]
  10. 10 [Category("自定义")]
  11. 11 [Description("获取或设置分隔份数")]
  12. 12 public int SplitCount
  13. 13 {
  14. 14 get { return splitCount; }
  15. 15 set
  16. 16 {
  17. 17 splitCount = value;
  18. 18 Invalidate();
  19. 19 }
  20. 20 }
  21. 21
  22. 22 /// <summary>
  23. 23 /// The split odd color
  24. 24 /// </summary>
  25. 25 private Color splitOddColor = Color.White;
  26. 26 /// <summary>
  27. 27 /// 分隔奇数栏配景色
  28. 28 /// </summary>
  29. 29 /// <value>The color of the split odd.</value>
  30. 30 [Browsable(true)]
  31. 31 [Category("自定义")]
  32. 32 [Description("获取或设置分隔奇数栏配景色")]
  33. 33 public Color SplitOddColor
  34. 34 {
  35. 35 get { return splitOddColor; }
  36. 36 set
  37. 37 {
  38. 38 splitOddColor = value;
  39. 39 Invalidate();
  40. 40 }
  41. 41 }
  42. 42 /// <summary>
  43. 43 /// The split even color
  44. 44 /// </summary>
  45. 45 private Color splitEvenColor = Color.FromArgb(232, 232, 232);
  46. 46 /// <summary>
  47. 47 /// 分隔偶数栏配景色
  48. 48 /// </summary>
  49. 49 /// <value>The color of the split even.</value>
  50. 50 [Browsable(true)]
  51. 51 [Category("自定义")]
  52. 52 [Description("获取或设置分隔偶数栏配景色")]
  53. 53 public Color SplitEvenColor
  54. 54 {
  55. 55 get { return splitEvenColor; }
  56. 56 set { splitEvenColor = value; }
  57. 57 }
  58. 58
  59. 59 /// <summary>
  60. 60 /// The line color
  61. 61 /// </summary>
  62. 62 private Color lineColor = Color.FromArgb(153, 153, 153);
  63. 63 /// <summary>
  64. 64 /// Gets or sets the color of the line.
  65. 65 /// </summary>
  66. 66 /// <value>The color of the line.</value>
  67. 67 [Browsable(true)]
  68. 68 [Category("自定义")]
  69. 69 [Description("获取或设置线条色")]
  70. 70 public Color LineColor
  71. 71 {
  72. 72 get { return lineColor; }
  73. 73 set
  74. 74 {
  75. 75 lineColor = value;
  76. 76 Invalidate();
  77. 77 }
  78. 78 }
  79. 79
  80. 80 /// <summary>
  81. 81 /// The radar positions
  82. 82 /// </summary>
  83. 83 private RadarPosition[] radarPositions;
  84. 84 /// <summary>
  85. 85 /// 节点列表,至少必要3个
  86. 86 /// </summary>
  87. 87 /// <value>The radar positions.</value>
  88. 88 [Browsable(true)]
  89. 89 [Category("自定义")]
  90. 90 [Description("获取或设置节点,至少必要3个")]
  91. 91 public RadarPosition[] RadarPositions
  92. 92 {
  93. 93 get { return radarPositions; }
  94. 94 set
  95. 95 {
  96. 96 radarPositions = value;
  97. 97 Invalidate();
  98. 98 }
  99. 99 }
  100. 100
  101. 101 /// <summary>
  102. 102 /// The title
  103. 103 /// </summary>
  104. 104 private string title;
  105. 105 /// <summary>
  106. 106 /// 标题
  107. 107 /// </summary>
  108. 108 /// <value>The title.</value>
  109. 109 [Browsable(true)]
  110. 110 [Category("自定义")]
  111. 111 [Description("获取或设置标题")]
  112. 112 public string Title
  113. 113 {
  114. 114 get { return title; }
  115. 115 set
  116. 116 {
  117. 117 title = value;
  118. 118 ResetTitleSize();
  119. 119 Invalidate();
  120. 120 }
  121. 121 }
  122. 122
  123. 123 /// <summary>
  124. 124 /// The title font
  125. 125 /// </summary>
  126. 126 private Font titleFont = new Font("微软雅黑", 12);
  127. 127 /// <summary>
  128. 128 /// Gets or sets the title font.
  129. 129 /// </summary>
  130. 130 /// <value>The title font.</value>
  131. 131 [Browsable(true)]
  132. 132 [Category("自定义")]
  133. 133 [Description("获取或设置标题字体")]
  134. 134 public Font TitleFont
  135. 135 {
  136. 136 get { return titleFont; }
  137. 137 set
  138. 138 {
  139. 139 titleFont = value;
  140. 140 ResetTitleSize();
  141. 141 Invalidate();
  142. 142 }
  143. 143 }
  144. 144
  145. 145 /// <summary>
  146. 146 /// The title color
  147. 147 /// </summary>
  148. 148 private Color titleColor = Color.Black;
  149. 149 /// <summary>
  150. 150 /// Gets or sets the color of the title.
  151. 151 /// </summary>
  152. 152 /// <value>The color of the title.</value>
  153. 153 [Browsable(true)]
  154. 154 [Category("自定义")]
  155. 155 [Description("获取或设置标题文本颜色")]
  156. 156 public Color TitleColor
  157. 157 {
  158. 158 get { return titleColor; }
  159. 159 set
  160. 160 {
  161. 161 titleColor = value;
  162. 162 Invalidate();
  163. 163 }
  164. 164 }
  165. 165
  166. 166 /// <summary>
  167. 167 /// The lines
  168. 168 /// </summary>
  169. 169 private RadarLine[] lines;
  170. 170 /// <summary>
  171. 171 /// Gets or sets the lines.
  172. 172 /// </summary>
  173. 173 /// <value>The lines.</value>
  174. 174 [Browsable(true)]
  175. 175 [Category("自定义")]
  176. 176 [Description("获取或设置值线条,Values长度必须与RadarPositions长度一致,否则无法显示")]
  177. 177 public RadarLine[] Lines
  178. 178 {
  179. 179 get { return lines; }
  180. 180 set
  181. 181 {
  182. 182 lines = value;
  183. 183 Invalidate();
  184. 184 }
  185. 185 }
  186. 186
  187. 187
  188. 188 /// <summary>
  189. 189 /// The title size
  190. 190 /// </summary>
  191. 191 SizeF titleSize = SizeF.Empty;
  192. 192 /// <summary>
  193. 193 /// The m rect working
  194. 194 /// </summary>
  195. 195 private RectangleF m_rectWorking = Rectangle.Empty;
  196. 196 /// <summary>
  197. 197 /// The line value type size
  198. 198 /// </summary>
  199. 199 SizeF lineValueTypeSize = SizeF.Empty;
  200. 200 /// <summary>
  201. 201 /// The int line value COM count
  202. 202 /// </summary>
  203. 203 int intLineValueComCount = 0;
  204. 204 /// <summary>
  205. 205 /// The int line value row count
  206. 206 /// </summary>
  207. 207 int intLineValueRowCount = 0;
复制代码

属性改变时处置惩罚工作区域

  1. 1 /// <summary>
  2. 2 /// Handles the SizeChanged event of the UCRadarChart control.
  3. 3 /// </summary>
  4. 4 /// <param name="sender">The source of the event.</param>
  5. 5 /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
  6. 6 void UCRadarChart_SizeChanged(object sender, EventArgs e)
  7. 7 {
  8. 8 ResetWorkingRect();
  9. 9 }
  10. 10
  11. 11 /// <summary>
  12. 12 /// Resets the working rect.
  13. 13 /// </summary>
  14. 14 private void ResetWorkingRect()
  15. 15 {
  16. 16 if (lines != null && lines.Length > 0)
  17. 17 {
  18. 18 using (Graphics g = this.CreateGraphics())
  19. 19 {
  20. 20 foreach (var item in lines)
  21. 21 {
  22. 22 var s = g.MeasureString(item.Name, Font);
  23. 23 if (s.Width > lineValueTypeSize.Width)
  24. 24 lineValueTypeSize = s;
  25. 25 }
  26. 26 }
  27. 27 }
  28. 28 var lineTypePanelHeight = 0f;
  29. 29 if (lineValueTypeSize != SizeF.Empty)
  30. 30 {
  31. 31 intLineValueComCount = (int)(this.Width / (lineValueTypeSize.Width + 25));
  32. 32
  33. 33 intLineValueRowCount = lines.Length / intLineValueComCount;
  34. 34 if (lines.Length % intLineValueComCount != 0)
  35. 35 {
  36. 36 intLineValueRowCount++;
  37. 37 }
  38. 38 lineTypePanelHeight = (lineValueTypeSize.Height + 10) * intLineValueRowCount;
  39. 39 }
  40. 40 var min = Math.Min(this.Width, this.Height - titleSize.Height - lineTypePanelHeight);
  41. 41 var rectWorking = new RectangleF((this.Width - min) / 2 + 10, titleSize.Height + lineTypePanelHeight + 10, min - 10, min - 10);
  42. 42 //处置惩罚文字
  43. 43 float fltSplitAngle = 360F / radarPositions.Length;
  44. 44 float fltRadiusWidth = rectWorking.Width / 2;
  45. 45 float minX = rectWorking.Left;
  46. 46 float maxX = rectWorking.Right;
  47. 47 float minY = rectWorking.Top;
  48. 48 float maxY = rectWorking.Bottom;
  49. 49 using (Graphics g = this.CreateGraphics())
  50. 50 {
  51. 51 PointF centrePoint = new PointF(rectWorking.Left + rectWorking.Width / 2, rectWorking.Top + rectWorking.Height / 2);
  52. 52 for (int i = 0; i < radarPositions.Length; i++)
  53. 53 {
  54. 54 float fltAngle = 270 + fltSplitAngle * i;
  55. 55 fltAngle = fltAngle % 360;
  56. 56 PointF _point = GetPointByAngle(centrePoint, fltAngle, fltRadiusWidth);
  57. 57 var _txtSize = g.MeasureString(radarPositions[i].Text, Font);
  58. 58 if (_point.X < centrePoint.X)//左
  59. 59 {
  60. 60 if (_point.X - _txtSize.Width < minX)
  61. 61 {
  62. 62 minX = rectWorking.Left + _txtSize.Width;
  63. 63 }
  64. 64 }
  65. 65 else//右
  66. 66 {
  67. 67 if (_point.X + _txtSize.Width > maxX)
  68. 68 {
  69. 69 maxX = rectWorking.Right - _txtSize.Width;
  70. 70 }
  71. 71 }
  72. 72 if (_point.Y < centrePoint.Y)//上
  73. 73 {
  74. 74 if (_point.Y - _txtSize.Height < minY)
  75. 75 {
  76. 76 minY = rectWorking.Top + _txtSize.Height;
  77. 77 }
  78. 78 }
  79. 79 else//下
  80. 80 {
  81. 81 if (_point.Y + _txtSize.Height > maxY)
  82. 82 {
  83. 83 maxY = rectWorking.Bottom - _txtSize.Height;
  84. 84 }
  85. 85 }
  86. 86 }
  87. 87 }
  88. 88
  89. 89 min = Math.Min(maxX - minX, maxY - minY);
  90. 90 m_rectWorking = new RectangleF(minX, minY, min, min);
  91. 91 }
复制代码

重绘

  1. 1 protected override void OnPaint(PaintEventArgs e)
  2. 2 {
  3. 3 base.OnPaint(e);
  4. 4 var g = e.Graphics;
  5. 5 g.SetGDIHigh();
  6. 6
  7. 7 if (!string.IsNullOrEmpty(title))
  8. 8 {
  9. 9 g.DrawString(title, titleFont, new SolidBrush(titleColor), new RectangleF(m_rectWorking.Left + (m_rectWorking.Width - titleSize.Width) / 2, m_rectWorking.Top - titleSize.Height - 10 - (intLineValueRowCount * (10 + lineValueTypeSize.Height)), titleSize.Width, titleSize.Height));
  10. 10 }
  11. 11
  12. 12 if (radarPositions.Length <= 2)
  13. 13 {
  14. 14 g.DrawString("至少必要3个极点", Font, new SolidBrush(Color.Black), m_rectWorking, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
  15. 15 return;
  16. 16 }
  17. 17
  18. 18 var y = m_rectWorking.Top - 20 - (intLineValueRowCount * (10 + lineValueTypeSize.Height));
  19. 19
  20. 20 for (int i = 0; i < intLineValueRowCount; i++)
  21. 21 {
  22. 22 var x = 0f;
  23. 23 int intCount = intLineValueComCount;
  24. 24 if (i == intLineValueRowCount - 1)
  25. 25 {
  26. 26 intCount = lines.Length % intLineValueComCount;
  27. 27
  28. 28 }
  29. 29 x = m_rectWorking.Left + (m_rectWorking.Width - intCount * (lineValueTypeSize.Width + 25)) / 2;
  30. 30
  31. 31 for (int j = 0; j < intCount; j++)
  32. 32 {
  33. 33 g.FillRectangle(new SolidBrush(lines[i * intLineValueComCount + j].LineColor.Value), new RectangleF(x + (lineValueTypeSize.Width + 25)*j, y + lineValueTypeSize.Height * i, 15, lineValueTypeSize.Height));
  34. 34 g.DrawString(lines[i * intLineValueComCount + j].Name, Font, new SolidBrush(lines[i * intLineValueComCount + j].LineColor.Value), new PointF(x + (lineValueTypeSize.Width + 25) * j + 20, y + lineValueTypeSize.Height * i));
  35. 35 }
  36. 36 }
  37. 37
  38. 38 float fltSplitAngle = 360F / radarPositions.Length;
  39. 39 float fltRadiusWidth = m_rectWorking.Width / 2;
  40. 40 float fltSplitRadiusWidth = fltRadiusWidth / splitCount;
  41. 41 PointF centrePoint = new PointF(m_rectWorking.Left + m_rectWorking.Width / 2, m_rectWorking.Top + m_rectWorking.Height / 2);
  42. 42
  43. 43 List<List<PointF>> lstRingPoints = new List<List<PointF>>(splitCount);
  44. 44 //分割点
  45. 45 for (int i = 0; i < radarPositions.Length; i++)
  46. 46 {
  47. 47 float fltAngle = 270 + fltSplitAngle * i;
  48. 48 fltAngle = fltAngle % 360;
  49. 49 for (int j = 0; j < splitCount; j++)
  50. 50 {
  51. 51 if (i == 0)
  52. 52 {
  53. 53 lstRingPoints.Add(new List<PointF>());
  54. 54 }
  55. 55 PointF _point = GetPointByAngle(centrePoint, fltAngle, fltSplitRadiusWidth * (splitCount - j));
  56. 56 lstRingPoints[j].Add(_point);
  57. 57 }
  58. 58 }
  59. 59
  60. 60 for (int i = 0; i < lstRingPoints.Count; i++)
  61. 61 {
  62. 62 var ring = lstRingPoints[i];
  63. 63 GraphicsPath path = new GraphicsPath();
  64. 64 path.AddLines(ring.ToArray());
  65. 65 if ((lstRingPoints.Count - i) % 2 == 0)
  66. 66 {
  67. 67 g.FillPath(new SolidBrush(splitEvenColor), path);
  68. 68 }
  69. 69 else
  70. 70 {
  71. 71 g.FillPath(new SolidBrush(splitOddColor), path);
  72. 72 }
  73. 73 }
  74. 74
  75. 75 //画环
  76. 76 foreach (var ring in lstRingPoints)
  77. 77 {
  78. 78 ring.Add(ring[0]);
  79. 79 g.DrawLines(new Pen(new SolidBrush(lineColor)), ring.ToArray());
  80. 80 }
  81. 81 //分割线
  82. 82 foreach (var item in lstRingPoints[0])
  83. 83 {
  84. 84 g.DrawLine(new Pen(new SolidBrush(lineColor)), centrePoint, item);
  85. 85 }
  86. 86
  87. 87 //值
  88. 88 for (int i = 0; i < lines.Length; i++)
  89. 89 {
  90. 90 var line = lines[i];
  91. 91 if (line.Values.Length != radarPositions.Length)//如果数据长度和节点长度不一致则不绘制
  92. 92 continue;
  93. 93 if (line.LineColor == null || line.LineColor == Color.Empty || line.LineColor == Color.Transparent)
  94. 94 line.LineColor = ControlHelper.Colors[i + 13];
  95. 95 List<PointF> ps = new List<PointF>();
  96. 96 for (int j = 0; j < radarPositions.Length; j++)
  97. 97 {
  98. 98 float fltAngle = 270 + fltSplitAngle * j;
  99. 99 fltAngle = fltAngle % 360;
  100. 100 PointF _point = GetPointByAngle(centrePoint, fltAngle, fltRadiusWidth * (float)(line.Values[j] / radarPositions[i].MaxValue));
  101. 101 ps.Add(_point);
  102. 102 }
  103. 103 ps.Add(ps[0]);
  104. 104 if (line.FillColor != null && line.FillColor != Color.Empty && line.FillColor != Color.Transparent)
  105. 105 {
  106. 106 GraphicsPath path = new GraphicsPath();
  107. 107 path.AddLines(ps.ToArray());
  108. 108 g.FillPath(new SolidBrush(line.FillColor.Value), path);
  109. 109 }
  110. 110 g.DrawLines(new Pen(new SolidBrush(line.LineColor.Value), 2), ps.ToArray());
  111. 111
  112. 112 for (int j = 0; j < radarPositions.Length; j++)
  113. 113 {
  114. 114 var item = ps[j];
  115. 115 g.FillEllipse(new SolidBrush(Color.White), new RectangleF(item.X - 3, item.Y - 3, 6, 6));
  116. 116 g.DrawEllipse(new Pen(new SolidBrush(line.LineColor.Value)), new RectangleF(item.X - 3, item.Y - 3, 6, 6));
  117. 117 if (line.ShowValueText)
  118. 118 {
  119. 119 var valueSize = g.MeasureString(line.Values[j].ToString("0.##"), Font);
  120. 120 g.DrawString(line.Values[j].ToString("0.##"), Font, new SolidBrush(line.LineColor.Value), new PointF(item.X - valueSize.Width / 2, item.Y - valueSize.Height - 5));
  121. 121 }
  122. 122 }
  123. 123 }
  124. 124
  125. 125 //文本
  126. 126
  127. 127 for (int i = 0; i < radarPositions.Length; i++)
  128. 128 {
  129. 129 PointF point = lstRingPoints[0][i];
  130. 130 var txtSize = g.MeasureString(radarPositions[i].Text, Font);
  131. 131
  132. 132 if (point.X == centrePoint.X)
  133. 133 {
  134. 134 if (point.Y > centrePoint.Y)
  135. 135 {
  136. 136 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X - txtSize.Width / 2, point.Y + 10));
  137. 137 }
  138. 138 else
  139. 139 {
  140. 140 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X - txtSize.Width / 2, point.Y - 10 - txtSize.Height));
  141. 141 }
  142. 142 }
  143. 143 else if (point.Y == centrePoint.Y)
  144. 144 {
  145. 145 if (point.X < centrePoint.X)
  146. 146 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X - 10 - txtSize.Width, point.Y - txtSize.Height / 2));
  147. 147 else
  148. 148 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X + 10, point.Y - txtSize.Height / 2));
  149. 149 }
  150. 150 else if (point.X < centrePoint.X)//左
  151. 151 {
  152. 152 if (point.Y < centrePoint.Y)//左上
  153. 153 {
  154. 154 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X - 10 - txtSize.Width, point.Y - 10 + txtSize.Height / 2));
  155. 155 }
  156. 156 else//左下
  157. 157 {
  158. 158 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X - 10 - txtSize.Width, point.Y + 10 - txtSize.Height / 2));
  159. 159 }
  160. 160 }
  161. 161 else
  162. 162 {
  163. 163 if (point.Y < centrePoint.Y)//右上
  164. 164 {
  165. 165 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X + 10, point.Y - 10 + txtSize.Height / 2));
  166. 166 }
  167. 167 else//右下
  168. 168 {
  169. 169 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X + 10, point.Y + 10 - txtSize.Height / 2));
  170. 170 }
  171. 171 }
  172. 172 }
  173. 173
  174. 174 }
复制代码

辅助函数

  1. 1 #region 根据中心点、角度、半径盘算圆边坐标点 English:Calculating the coordinate points of circular edge according to the center point, angle and radius
  2. 2 /// <summary>
  3. 3 /// 功能形貌:根据中心点、角度、半径盘算圆边坐标点 English:Calculating the coordinate points of circular edge according to the center point, angle and radius
  4. 4 /// 作  者:HZH
  5. 5 /// 创建日期:2019-09-25 09:46:32
  6. 6 /// 任务编号:POS
  7. 7 /// </summary>
  8. 8 /// <param name="centrePoint">centrePoint</param>
  9. 9 /// <param name="fltAngle">fltAngle</param>
  10. 10 /// <param name="fltRadiusWidth">fltRadiusWidth</param>
  11. 11 /// <returns>返回值</returns>
  12. 12 private PointF GetPointByAngle(PointF centrePoint, float fltAngle, float fltRadiusWidth)
  13. 13 {
  14. 14 PointF p = centrePoint;
  15. 15 if (fltAngle == 0)
  16. 16 {
  17. 17 p.X += fltRadiusWidth;
  18. 18 }
  19. 19 else if (fltAngle == 90)
  20. 20 {
  21. 21 p.Y += fltRadiusWidth;
  22. 22 }
  23. 23 else if (fltAngle == 180)
  24. 24 {
  25. 25 p.X -= fltRadiusWidth;
  26. 26 }
  27. 27 else if (fltAngle == 270)
  28. 28 {
  29. 29 p.Y -= fltRadiusWidth;
  30. 30 }
  31. 31 else if (fltAngle > 0 && fltAngle < 90)
  32. 32 {
  33. 33 p.Y += (float)Math.Sin(Math.PI * (fltAngle / 180.00F)) * fltRadiusWidth;
  34. 34 p.X += (float)Math.Cos(Math.PI * (fltAngle / 180.00F)) * fltRadiusWidth;
  35. 35 }
  36. 36 else if (fltAngle > 90 && fltAngle < 180)
  37. 37 {
  38. 38 p.Y += (float)Math.Sin(Math.PI * ((180 - fltAngle) / 180.00F)) * fltRadiusWidth;
  39. 39 p.X -= (float)Math.Cos(Math.PI * ((180 - fltAngle) / 180.00F)) * fltRadiusWidth;
  40. 40 }
  41. 41 else if (fltAngle > 180 && fltAngle < 270)
  42. 42 {
  43. 43 p.Y -= (float)Math.Sin(Math.PI * ((fltAngle - 180) / 180.00F)) * fltRadiusWidth;
  44. 44 p.X -= (float)Math.Cos(Math.PI * ((fltAngle - 180) / 180.00F)) * fltRadiusWidth;
  45. 45 }
  46. 46 else if (fltAngle > 270 && fltAngle < 360)
  47. 47 {
  48. 48 p.Y -= (float)Math.Sin(Math.PI * ((360 - fltAngle) / 180.00F)) * fltRadiusWidth;
  49. 49 p.X += (float)Math.Cos(Math.PI * ((360 - fltAngle) / 180.00F)) * fltRadiusWidth;
  50. 50 }
  51. 51 return p;
  52. 52 }
  53. 53 #endregion
  54. 54
  55. 55 /// <summary>
  56. 56 /// Resets the size of the title.
  57. 57 /// </summary>
  58. 58 private void ResetTitleSize()
  59. 59 {
  60. 60 if (!string.IsNullOrEmpty(title))
  61. 61 {
  62. 62 using (Graphics g = this.CreateGraphics())
  63. 63 {
  64. 64 titleSize = g.MeasureString(title, titleFont);
  65. 65 }
  66. 66 }
  67. 67 else
  68. 68 {
  69. 69 titleSize = SizeF.Empty;
  70. 70 }
  71. 71 titleSize.Height += 20;
  72. 72 ResetWorkingRect();
  73. 73 }
复制代码

完整代码

092051i0elzz6fculpiruc.gif
092051fdunnenndnfve8n8.gif
  1. 1 // ***********************************************************************
  2. 2 // Assembly : HZH_Controls
  3. 3 // Created : 2019-09-25
  4. 4 //
  5. 5 // ***********************************************************************
  6. 6 // <copyright file="UCRadarChart.cs">
  7. 7 // Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
  8. 8 // </copyright>
  9. 9 //
  10. 10 // Blog: https://www.cnblogs.com/bfyx
  11. 11 // GitHub:https://github.com/kwwwvagaa/NetWinformControl
  12. 12 // gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
  13. 13 //
  14. 14 // If you use this code, please keep this note.
  15. 15 // ***********************************************************************
  16. 16 using System;
  17. 17 using System.Collections.Generic;
  18. 18 using System.Linq;
  19. 19 using System.Text;
  20. 20 using System.Windows.Forms;
  21. 21 using System.Drawing;
  22. 22 using System.Drawing.Drawing2D;
  23. 23 using System.ComponentModel;
  24. 24
  25. 25 namespace HZH_Controls.Controls
  26. 26 {
  27. 27 /// <summary>
  28. 28 /// Class UCRadarChart.
  29. 29 /// Implements the <see cref="System.Windows.Forms.UserControl" />
  30. 30 /// </summary>
  31. 31 /// <seealso cref="System.Windows.Forms.UserControl" />
  32. 32 public class UCRadarChart : UserControl
  33. 33 {
  34. 34 /// <summary>
  35. 35 /// The split count
  36. 36 /// </summary>
  37. 37 private int splitCount = 5;
  38. 38 /// <summary>
  39. 39 /// Gets or sets the split count.
  40. 40 /// </summary>
  41. 41 /// <value>The split count.</value>
  42. 42 [Browsable(true)]
  43. 43 [Category("自定义")]
  44. 44 [Description("获取或设置分隔份数")]
  45. 45 public int SplitCount
  46. 46 {
  47. 47 get { return splitCount; }
  48. 48 set
  49. 49 {
  50. 50 splitCount = value;
  51. 51 Invalidate();
  52. 52 }
  53. 53 }
  54. 54
  55. 55 /// <summary>
  56. 56 /// The split odd color
  57. 57 /// </summary>
  58. 58 private Color splitOddColor = Color.White;
  59. 59 /// <summary>
  60. 60 /// 分隔奇数栏配景色
  61. 61 /// </summary>
  62. 62 /// <value>The color of the split odd.</value>
  63. 63 [Browsable(true)]
  64. 64 [Category("自定义")]
  65. 65 [Description("获取或设置分隔奇数栏配景色")]
  66. 66 public Color SplitOddColor
  67. 67 {
  68. 68 get { return splitOddColor; }
  69. 69 set
  70. 70 {
  71. 71 splitOddColor = value;
  72. 72 Invalidate();
  73. 73 }
  74. 74 }
  75. 75 /// <summary>
  76. 76 /// The split even color
  77. 77 /// </summary>
  78. 78 private Color splitEvenColor = Color.FromArgb(232, 232, 232);
  79. 79 /// <summary>
  80. 80 /// 分隔偶数栏配景色
  81. 81 /// </summary>
  82. 82 /// <value>The color of the split even.</value>
  83. 83 [Browsable(true)]
  84. 84 [Category("自定义")]
  85. 85 [Description("获取或设置分隔偶数栏配景色")]
  86. 86 public Color SplitEvenColor
  87. 87 {
  88. 88 get { return splitEvenColor; }
  89. 89 set { splitEvenColor = value; }
  90. 90 }
  91. 91
  92. 92 /// <summary>
  93. 93 /// The line color
  94. 94 /// </summary>
  95. 95 private Color lineColor = Color.FromArgb(153, 153, 153);
  96. 96 /// <summary>
  97. 97 /// Gets or sets the color of the line.
  98. 98 /// </summary>
  99. 99 /// <value>The color of the line.</value>
  100. 100 [Browsable(true)]
  101. 101 [Category("自定义")]
  102. 102 [Description("获取或设置线条色")]
  103. 103 public Color LineColor
  104. 104 {
  105. 105 get { return lineColor; }
  106. 106 set
  107. 107 {
  108. 108 lineColor = value;
  109. 109 Invalidate();
  110. 110 }
  111. 111 }
  112. 112
  113. 113 /// <summary>
  114. 114 /// The radar positions
  115. 115 /// </summary>
  116. 116 private RadarPosition[] radarPositions;
  117. 117 /// <summary>
  118. 118 /// 节点列表,至少必要3个
  119. 119 /// </summary>
  120. 120 /// <value>The radar positions.</value>
  121. 121 [Browsable(true)]
  122. 122 [Category("自定义")]
  123. 123 [Description("获取或设置节点,至少必要3个")]
  124. 124 public RadarPosition[] RadarPositions
  125. 125 {
  126. 126 get { return radarPositions; }
  127. 127 set
  128. 128 {
  129. 129 radarPositions = value;
  130. 130 Invalidate();
  131. 131 }
  132. 132 }
  133. 133
  134. 134 /// <summary>
  135. 135 /// The title
  136. 136 /// </summary>
  137. 137 private string title;
  138. 138 /// <summary>
  139. 139 /// 标题
  140. 140 /// </summary>
  141. 141 /// <value>The title.</value>
  142. 142 [Browsable(true)]
  143. 143 [Category("自定义")]
  144. 144 [Description("获取或设置标题")]
  145. 145 public string Title
  146. 146 {
  147. 147 get { return title; }
  148. 148 set
  149. 149 {
  150. 150 title = value;
  151. 151 ResetTitleSize();
  152. 152 Invalidate();
  153. 153 }
  154. 154 }
  155. 155
  156. 156 /// <summary>
  157. 157 /// The title font
  158. 158 /// </summary>
  159. 159 private Font titleFont = new Font("微软雅黑", 12);
  160. 160 /// <summary>
  161. 161 /// Gets or sets the title font.
  162. 162 /// </summary>
  163. 163 /// <value>The title font.</value>
  164. 164 [Browsable(true)]
  165. 165 [Category("自定义")]
  166. 166 [Description("获取或设置标题字体")]
  167. 167 public Font TitleFont
  168. 168 {
  169. 169 get { return titleFont; }
  170. 170 set
  171. 171 {
  172. 172 titleFont = value;
  173. 173 ResetTitleSize();
  174. 174 Invalidate();
  175. 175 }
  176. 176 }
  177. 177
  178. 178 /// <summary>
  179. 179 /// The title color
  180. 180 /// </summary>
  181. 181 private Color titleColor = Color.Black;
  182. 182 /// <summary>
  183. 183 /// Gets or sets the color of the title.
  184. 184 /// </summary>
  185. 185 /// <value>The color of the title.</value>
  186. 186 [Browsable(true)]
  187. 187 [Category("自定义")]
  188. 188 [Description("获取或设置标题文本颜色")]
  189. 189 public Color TitleColor
  190. 190 {
  191. 191 get { return titleColor; }
  192. 192 set
  193. 193 {
  194. 194 titleColor = value;
  195. 195 Invalidate();
  196. 196 }
  197. 197 }
  198. 198
  199. 199 /// <summary>
  200. 200 /// The lines
  201. 201 /// </summary>
  202. 202 private RadarLine[] lines;
  203. 203 /// <summary>
  204. 204 /// Gets or sets the lines.
  205. 205 /// </summary>
  206. 206 /// <value>The lines.</value>
  207. 207 [Browsable(true)]
  208. 208 [Category("自定义")]
  209. 209 [Description("获取或设置值线条,Values长度必须与RadarPositions长度一致,否则无法显示")]
  210. 210 public RadarLine[] Lines
  211. 211 {
  212. 212 get { return lines; }
  213. 213 set
  214. 214 {
  215. 215 lines = value;
  216. 216 Invalidate();
  217. 217 }
  218. 218 }
  219. 219
  220. 220
  221. 221 /// <summary>
  222. 222 /// The title size
  223. 223 /// </summary>
  224. 224 SizeF titleSize = SizeF.Empty;
  225. 225 /// <summary>
  226. 226 /// The m rect working
  227. 227 /// </summary>
  228. 228 private RectangleF m_rectWorking = Rectangle.Empty;
  229. 229 /// <summary>
  230. 230 /// The line value type size
  231. 231 /// </summary>
  232. 232 SizeF lineValueTypeSize = SizeF.Empty;
  233. 233 /// <summary>
  234. 234 /// The int line value COM count
  235. 235 /// </summary>
  236. 236 int intLineValueComCount = 0;
  237. 237 /// <summary>
  238. 238 /// The int line value row count
  239. 239 /// </summary>
  240. 240 int intLineValueRowCount = 0;
  241. 241 /// <summary>
  242. 242 /// Initializes a new instance of the <see cref="UCRadarChart"/> class.
  243. 243 /// </summary>
  244. 244 public UCRadarChart()
  245. 245 {
  246. 246 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
  247. 247 this.SetStyle(ControlStyles.DoubleBuffer, true);
  248. 248 this.SetStyle(ControlStyles.ResizeRedraw, true);
  249. 249 this.SetStyle(ControlStyles.Selectable, true);
  250. 250 this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
  251. 251 this.SetStyle(ControlStyles.UserPaint, true);
  252. 252 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
  253. 253 this.SizeChanged += UCRadarChart_SizeChanged;
  254. 254 Size = new System.Drawing.Size(150, 150);
  255. 255 radarPositions = new RadarPosition[0];
  256. 256 if (ControlHelper.IsDesignMode())
  257. 257 {
  258. 258 radarPositions = new RadarPosition[6];
  259. 259 for (int i = 0; i < 6; i++)
  260. 260 {
  261. 261 radarPositions[i] = new RadarPosition
  262. 262 {
  263. 263 Text = "Item" + (i + 1),
  264. 264 MaxValue = 100
  265. 265 };
  266. 266 }
  267. 267 }
  268. 268
  269. 269 lines = new RadarLine[0];
  270. 270 if (ControlHelper.IsDesignMode())
  271. 271 {
  272. 272 Random r = new Random();
  273. 273 lines = new RadarLine[2];
  274. 274 for (int i = 0; i < 2; i++)
  275. 275 {
  276. 276 lines[i] = new RadarLine()
  277. 277 {
  278. 278 Name = "line" + i
  279. 279 };
  280. 280 lines[i].Values = new double[radarPositions.Length];
  281. 281 for (int j = 0; j < radarPositions.Length; j++)
  282. 282 {
  283. 283 lines[i].Values[j] = r.Next(20, (int)radarPositions[j].MaxValue);
  284. 284 }
  285. 285 }
  286. 286 }
  287. 287 }
  288. 288
  289. 289 /// <summary>
  290. 290 /// Handles the SizeChanged event of the UCRadarChart control.
  291. 291 /// </summary>
  292. 292 /// <param name="sender">The source of the event.</param>
  293. 293 /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
  294. 294 void UCRadarChart_SizeChanged(object sender, EventArgs e)
  295. 295 {
  296. 296 ResetWorkingRect();
  297. 297 }
  298. 298
  299. 299 /// <summary>
  300. 300 /// Resets the working rect.
  301. 301 /// </summary>
  302. 302 private void ResetWorkingRect()
  303. 303 {
  304. 304 if (lines != null && lines.Length > 0)
  305. 305 {
  306. 306 using (Graphics g = this.CreateGraphics())
  307. 307 {
  308. 308 foreach (var item in lines)
  309. 309 {
  310. 310 var s = g.MeasureString(item.Name, Font);
  311. 311 if (s.Width > lineValueTypeSize.Width)
  312. 312 lineValueTypeSize = s;
  313. 313 }
  314. 314 }
  315. 315 }
  316. 316 var lineTypePanelHeight = 0f;
  317. 317 if (lineValueTypeSize != SizeF.Empty)
  318. 318 {
  319. 319 intLineValueComCount = (int)(this.Width / (lineValueTypeSize.Width + 25));
  320. 320
  321. 321 intLineValueRowCount = lines.Length / intLineValueComCount;
  322. 322 if (lines.Length % intLineValueComCount != 0)
  323. 323 {
  324. 324 intLineValueRowCount++;
  325. 325 }
  326. 326 lineTypePanelHeight = (lineValueTypeSize.Height + 10) * intLineValueRowCount;
  327. 327 }
  328. 328 var min = Math.Min(this.Width, this.Height - titleSize.Height - lineTypePanelHeight);
  329. 329 var rectWorking = new RectangleF((this.Width - min) / 2 + 10, titleSize.Height + lineTypePanelHeight + 10, min - 10, min - 10);
  330. 330 //处置惩罚文字
  331. 331 float fltSplitAngle = 360F / radarPositions.Length;
  332. 332 float fltRadiusWidth = rectWorking.Width / 2;
  333. 333 float minX = rectWorking.Left;
  334. 334 float maxX = rectWorking.Right;
  335. 335 float minY = rectWorking.Top;
  336. 336 float maxY = rectWorking.Bottom;
  337. 337 using (Graphics g = this.CreateGraphics())
  338. 338 {
  339. 339 PointF centrePoint = new PointF(rectWorking.Left + rectWorking.Width / 2, rectWorking.Top + rectWorking.Height / 2);
  340. 340 for (int i = 0; i < radarPositions.Length; i++)
  341. 341 {
  342. 342 float fltAngle = 270 + fltSplitAngle * i;
  343. 343 fltAngle = fltAngle % 360;
  344. 344 PointF _point = GetPointByAngle(centrePoint, fltAngle, fltRadiusWidth);
  345. 345 var _txtSize = g.MeasureString(radarPositions[i].Text, Font);
  346. 346 if (_point.X < centrePoint.X)//左
  347. 347 {
  348. 348 if (_point.X - _txtSize.Width < minX)
  349. 349 {
  350. 350 minX = rectWorking.Left + _txtSize.Width;
  351. 351 }
  352. 352 }
  353. 353 else//右
  354. 354 {
  355. 355 if (_point.X + _txtSize.Width > maxX)
  356. 356 {
  357. 357 maxX = rectWorking.Right - _txtSize.Width;
  358. 358 }
  359. 359 }
  360. 360 if (_point.Y < centrePoint.Y)//上
  361. 361 {
  362. 362 if (_point.Y - _txtSize.Height < minY)
  363. 363 {
  364. 364 minY = rectWorking.Top + _txtSize.Height;
  365. 365 }
  366. 366 }
  367. 367 else//下
  368. 368 {
  369. 369 if (_point.Y + _txtSize.Height > maxY)
  370. 370 {
  371. 371 maxY = rectWorking.Bottom - _txtSize.Height;
  372. 372 }
  373. 373 }
  374. 374 }
  375. 375 }
  376. 376
  377. 377 min = Math.Min(maxX - minX, maxY - minY);
  378. 378 m_rectWorking = new RectangleF(minX, minY, min, min);
  379. 379 }
  380. 380
  381. 381 /// <summary>
  382. 382 /// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 变乱。
  383. 383 /// </summary>
  384. 384 /// <param name="e">包罗变乱数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
  385. 385 protected override void OnPaint(PaintEventArgs e)
  386. 386 {
  387. 387 base.OnPaint(e);
  388. 388 var g = e.Graphics;
  389. 389 g.SetGDIHigh();
  390. 390
  391. 391 if (!string.IsNullOrEmpty(title))
  392. 392 {
  393. 393 g.DrawString(title, titleFont, new SolidBrush(titleColor), new RectangleF(m_rectWorking.Left + (m_rectWorking.Width - titleSize.Width) / 2, m_rectWorking.Top - titleSize.Height - 10 - (intLineValueRowCount * (10 + lineValueTypeSize.Height)), titleSize.Width, titleSize.Height));
  394. 394 }
  395. 395
  396. 396 if (radarPositions.Length <= 2)
  397. 397 {
  398. 398 g.DrawString("至少必要3个极点", Font, new SolidBrush(Color.Black), m_rectWorking, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
  399. 399 return;
  400. 400 }
  401. 401
  402. 402 var y = m_rectWorking.Top - 20 - (intLineValueRowCount * (10 + lineValueTypeSize.Height));
  403. 403
  404. 404 for (int i = 0; i < intLineValueRowCount; i++)
  405. 405 {
  406. 406 var x = 0f;
  407. 407 int intCount = intLineValueComCount;
  408. 408 if (i == intLineValueRowCount - 1)
  409. 409 {
  410. 410 intCount = lines.Length % intLineValueComCount;
  411. 411
  412. 412 }
  413. 413 x = m_rectWorking.Left + (m_rectWorking.Width - intCount * (lineValueTypeSize.Width + 25)) / 2;
  414. 414
  415. 415 for (int j = 0; j < intCount; j++)
  416. 416 {
  417. 417 g.FillRectangle(new SolidBrush(lines[i * intLineValueComCount + j].LineColor.Value), new RectangleF(x + (lineValueTypeSize.Width + 25)*j, y + lineValueTypeSize.Height * i, 15, lineValueTypeSize.Height));
  418. 418 g.DrawString(lines[i * intLineValueComCount + j].Name, Font, new SolidBrush(lines[i * intLineValueComCount + j].LineColor.Value), new PointF(x + (lineValueTypeSize.Width + 25) * j + 20, y + lineValueTypeSize.Height * i));
  419. 419 }
  420. 420 }
  421. 421
  422. 422 float fltSplitAngle = 360F / radarPositions.Length;
  423. 423 float fltRadiusWidth = m_rectWorking.Width / 2;
  424. 424 float fltSplitRadiusWidth = fltRadiusWidth / splitCount;
  425. 425 PointF centrePoint = new PointF(m_rectWorking.Left + m_rectWorking.Width / 2, m_rectWorking.Top + m_rectWorking.Height / 2);
  426. 426
  427. 427 List<List<PointF>> lstRingPoints = new List<List<PointF>>(splitCount);
  428. 428 //分割点
  429. 429 for (int i = 0; i < radarPositions.Length; i++)
  430. 430 {
  431. 431 float fltAngle = 270 + fltSplitAngle * i;
  432. 432 fltAngle = fltAngle % 360;
  433. 433 for (int j = 0; j < splitCount; j++)
  434. 434 {
  435. 435 if (i == 0)
  436. 436 {
  437. 437 lstRingPoints.Add(new List<PointF>());
  438. 438 }
  439. 439 PointF _point = GetPointByAngle(centrePoint, fltAngle, fltSplitRadiusWidth * (splitCount - j));
  440. 440 lstRingPoints[j].Add(_point);
  441. 441 }
  442. 442 }
  443. 443
  444. 444 for (int i = 0; i < lstRingPoints.Count; i++)
  445. 445 {
  446. 446 var ring = lstRingPoints[i];
  447. 447 GraphicsPath path = new GraphicsPath();
  448. 448 path.AddLines(ring.ToArray());
  449. 449 if ((lstRingPoints.Count - i) % 2 == 0)
  450. 450 {
  451. 451 g.FillPath(new SolidBrush(splitEvenColor), path);
  452. 452 }
  453. 453 else
  454. 454 {
  455. 455 g.FillPath(new SolidBrush(splitOddColor), path);
  456. 456 }
  457. 457 }
  458. 458
  459. 459 //画环
  460. 460 foreach (var ring in lstRingPoints)
  461. 461 {
  462. 462 ring.Add(ring[0]);
  463. 463 g.DrawLines(new Pen(new SolidBrush(lineColor)), ring.ToArray());
  464. 464 }
  465. 465 //分割线
  466. 466 foreach (var item in lstRingPoints[0])
  467. 467 {
  468. 468 g.DrawLine(new Pen(new SolidBrush(lineColor)), centrePoint, item);
  469. 469 }
  470. 470
  471. 471 //值
  472. 472 for (int i = 0; i < lines.Length; i++)
  473. 473 {
  474. 474 var line = lines[i];
  475. 475 if (line.Values.Length != radarPositions.Length)//如果数据长度和节点长度不一致则不绘制
  476. 476 continue;
  477. 477 if (line.LineColor == null || line.LineColor == Color.Empty || line.LineColor == Color.Transparent)
  478. 478 line.LineColor = ControlHelper.Colors[i + 13];
  479. 479 List<PointF> ps = new List<PointF>();
  480. 480 for (int j = 0; j < radarPositions.Length; j++)
  481. 481 {
  482. 482 float fltAngle = 270 + fltSplitAngle * j;
  483. 483 fltAngle = fltAngle % 360;
  484. 484 PointF _point = GetPointByAngle(centrePoint, fltAngle, fltRadiusWidth * (float)(line.Values[j] / radarPositions[i].MaxValue));
  485. 485 ps.Add(_point);
  486. 486 }
  487. 487 ps.Add(ps[0]);
  488. 488 if (line.FillColor != null && line.FillColor != Color.Empty && line.FillColor != Color.Transparent)
  489. 489 {
  490. 490 GraphicsPath path = new GraphicsPath();
  491. 491 path.AddLines(ps.ToArray());
  492. 492 g.FillPath(new SolidBrush(line.FillColor.Value), path);
  493. 493 }
  494. 494 g.DrawLines(new Pen(new SolidBrush(line.LineColor.Value), 2), ps.ToArray());
  495. 495
  496. 496 for (int j = 0; j < radarPositions.Length; j++)
  497. 497 {
  498. 498 var item = ps[j];
  499. 499 g.FillEllipse(new SolidBrush(Color.White), new RectangleF(item.X - 3, item.Y - 3, 6, 6));
  500. 500 g.DrawEllipse(new Pen(new SolidBrush(line.LineColor.Value)), new RectangleF(item.X - 3, item.Y - 3, 6, 6));
  501. 501 if (line.ShowValueText)
  502. 502 {
  503. 503 var valueSize = g.MeasureString(line.Values[j].ToString("0.##"), Font);
  504. 504 g.DrawString(line.Values[j].ToString("0.##"), Font, new SolidBrush(line.LineColor.Value), new PointF(item.X - valueSize.Width / 2, item.Y - valueSize.Height - 5));
  505. 505 }
  506. 506 }
  507. 507 }
  508. 508
  509. 509 //文本
  510. 510
  511. 511 for (int i = 0; i < radarPositions.Length; i++)
  512. 512 {
  513. 513 PointF point = lstRingPoints[0][i];
  514. 514 var txtSize = g.MeasureString(radarPositions[i].Text, Font);
  515. 515
  516. 516 if (point.X == centrePoint.X)
  517. 517 {
  518. 518 if (point.Y > centrePoint.Y)
  519. 519 {
  520. 520 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X - txtSize.Width / 2, point.Y + 10));
  521. 521 }
  522. 522 else
  523. 523 {
  524. 524 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X - txtSize.Width / 2, point.Y - 10 - txtSize.Height));
  525. 525 }
  526. 526 }
  527. 527 else if (point.Y == centrePoint.Y)
  528. 528 {
  529. 529 if (point.X < centrePoint.X)
  530. 530 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X - 10 - txtSize.Width, point.Y - txtSize.Height / 2));
  531. 531 else
  532. 532 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X + 10, point.Y - txtSize.Height / 2));
  533. 533 }
  534. 534 else if (point.X < centrePoint.X)//左
  535. 535 {
  536. 536 if (point.Y < centrePoint.Y)//左上
  537. 537 {
  538. 538 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X - 10 - txtSize.Width, point.Y - 10 + txtSize.Height / 2));
  539. 539 }
  540. 540 else//左下
  541. 541 {
  542. 542 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X - 10 - txtSize.Width, point.Y + 10 - txtSize.Height / 2));
  543. 543 }
  544. 544 }
  545. 545 else
  546. 546 {
  547. 547 if (point.Y < centrePoint.Y)//右上
  548. 548 {
  549. 549 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X + 10, point.Y - 10 + txtSize.Height / 2));
  550. 550 }
  551. 551 else//右下
  552. 552 {
  553. 553 g.DrawString(radarPositions[i].Text, Font, new SolidBrush(ForeColor), new PointF(point.X + 10, point.Y + 10 - txtSize.Height / 2));
  554. 554 }
  555. 555 }
  556. 556 }
  557. 557
  558. 558 }
  559. 559
  560. 560 #region 根据中心点、角度、半径盘算圆边坐标点 English:Calculating the coordinate points of circular edge according to the center point, angle and radius
  561. 561 /// <summary>
  562. 562 /// 功能形貌:根据中心点、角度、半径盘算圆边坐标点 English:Calculating the coordinate points of circular edge according to the center point, angle and radius
  563. 563 /// 作  者:HZH
  564. 564 /// 创建日期:2019-09-25 09:46:32
  565. 565 /// 任务编号:POS
  566. 566 /// </summary>
  567. 567 /// <param name="centrePoint">centrePoint</param>
  568. 568 /// <param name="fltAngle">fltAngle</param>
  569. 569 /// <param name="fltRadiusWidth">fltRadiusWidth</param>
  570. 570 /// <returns>返回值</returns>
  571. 571 private PointF GetPointByAngle(PointF centrePoint, float fltAngle, float fltRadiusWidth)
  572. 572 {
  573. 573 PointF p = centrePoint;
  574. 574 if (fltAngle == 0)
  575. 575 {
  576. 576 p.X += fltRadiusWidth;
  577. 577 }
  578. 578 else if (fltAngle == 90)
  579. 579 {
  580. 580 p.Y += fltRadiusWidth;
  581. 581 }
  582. 582 else if (fltAngle == 180)
  583. 583 {
  584. 584 p.X -= fltRadiusWidth;
  585. 585 }
  586. 586 else if (fltAngle == 270)
  587. 587 {
  588. 588 p.Y -= fltRadiusWidth;
  589. 589 }
  590. 590 else if (fltAngle > 0 && fltAngle < 90)
  591. 591 {
  592. 592 p.Y += (float)Math.Sin(Math.PI * (fltAngle / 180.00F)) * fltRadiusWidth;
  593. 593 p.X += (float)Math.Cos(Math.PI * (fltAngle / 180.00F)) * fltRadiusWidth;
  594. 594 }
  595. 595 else if (fltAngle > 90 && fltAngle < 180)
  596. 596 {
  597. 597 p.Y += (float)Math.Sin(Math.PI * ((180 - fltAngle) / 180.00F)) * fltRadiusWidth;
  598. 598 p.X -= (float)Math.Cos(Math.PI * ((180 - fltAngle) / 180.00F)) * fltRadiusWidth;
  599. 599 }
  600. 600 else if (fltAngle > 180 && fltAngle < 270)
  601. 601 {
  602. 602 p.Y -= (float)Math.Sin(Math.PI * ((fltAngle - 180) / 180.00F)) * fltRadiusWidth;
  603. 603 p.X -= (float)Math.Cos(Math.PI * ((fltAngle - 180) / 180.00F)) * fltRadiusWidth;
  604. 604 }
  605. 605 else if (fltAngle > 270 && fltAngle < 360)
  606. 606 {
  607. 607 p.Y -= (float)Math.Sin(Math.PI * ((360 - fltAngle) / 180.00F)) * fltRadiusWidth;
  608. 608 p.X += (float)Math.Cos(Math.PI * ((360 - fltAngle) / 180.00F)) * fltRadiusWidth;
  609. 609 }
  610. 610 return p;
  611. 611 }
  612. 612 #endregion
  613. 613
  614. 614 /// <summary>
  615. 615 /// Resets the size of the title.
  616. 616 /// </summary>
  617. 617 private void ResetTitleSize()
  618. 618 {
  619. 619 if (!string.IsNullOrEmpty(title))
  620. 620 {
  621. 621 using (Graphics g = this.CreateGraphics())
  622. 622 {
  623. 623 titleSize = g.MeasureString(title, titleFont);
  624. 624 }
  625. 625 }
  626. 626 else
  627. 627 {
  628. 628 titleSize = SizeF.Empty;
  629. 629 }
  630. 630 titleSize.Height += 20;
  631. 631 ResetWorkingRect();
  632. 632 }
  633. 633 }
  634. 634 }
复制代码
View Code

末了的话

如果你喜好的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧







来源:https://www.cnblogs.com/bfyx/archive/2019/09/25/11584514.html
C#论坛 www.ibcibc.com IBC编程社区
C#
C#论坛
IBC编程社区
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则