经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
C# GDI绘制仪表盘(纯代码实现)
来源:cnblogs  作者:永恒921  时间:2018/11/16 10:31:31  对本文有异议
  1. 纯代码实现GDI绘制仪表盘,效果在代码下面。

    public
    partial class HalfDashboardUc : UserControl
  2. {
  3. /// <summary>
  4. /// 仪表盘背景图片
  5. /// </summary>
  6. private Image dashboardImage;
  7. /// <summary>
  8. /// 定义该仪表盘画布的最大值为371
  9. /// </summary>
  10. private int maxSize = 371;
  11. /// <summary>
  12. /// 仪表盘画布的放大倍数,默认1
  13. /// </summary>
  14. private float multiple = 1;
  15. /// <summary>
  16. /// 定义该仪表盘的直径大小
  17. /// </summary>
  18. private float diameter;
  19. /// <summary>
  20. /// 每个间隔值
  21. /// </summary>
  22. private int intervalValue;
  23. /// <summary>
  24. /// 仪表盘显示的最小值,默认为0
  25. /// </summary>
  26. private float minValue = 0;
  27. /// <summary>
  28. /// 仪表盘显示的最小值
  29. /// </summary>
  30. [Category("wyl")]
  31. [Description("仪表盘显示的最小值")]
  32. public float MinValue
  33. {
  34. get
  35. {
  36. return minValue;
  37. }
  38. set
  39. {
  40. if (value >= MaxValue)
  41. {
  42. MessageBox.Show("最小值不能超过最大值!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  43. minValue = 0;
  44. }
  45. else
  46. {
  47. minValue = value;
  48. //drawBackImage();
  49. }
  50. }
  51. }
  52. /// <summary>
  53. /// 仪表盘上显示的最大值,默认123。
  54. /// </summary>
  55. private float maxValue = 123;
  56. /// <summary>
  57. /// 仪表盘上显示的最大值
  58. /// </summary>
  59. [Category("wyl")]
  60. [Description("仪表盘上显示的最大值")]
  61. public float MaxValue
  62. {
  63. get
  64. {
  65. return maxValue;
  66. }
  67. set
  68. {
  69. if (value <= MinValue)
  70. {
  71. MessageBox.Show("最大值不能低于最小值!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  72. maxValue = 123;
  73. }
  74. else
  75. {
  76. maxValue = value;
  77. //drawBackImage();
  78. }
  79. }
  80. }
  81. // <summary>
  82. /// 仪表盘变换的值,默认为0;
  83. /// </summary>
  84. private float changeValue = 0;
  85. /// <summary>
  86. /// 仪表盘变换的值
  87. /// </summary>
  88. public float ChangeValue
  89. {
  90. get
  91. {
  92. return changeValue;
  93. }
  94. set
  95. {
  96. changeValue = value;
  97. }
  98. }
  99. /// <summary>
  100. /// 指针颜色
  101. /// </summary>
  102. private Color pinColor = Color.FromArgb(191, 148, 28);
  103. public Color PinColor
  104. {
  105. get
  106. {
  107. return pinColor;
  108. }
  109. set
  110. {
  111. pinColor = value;
  112. }
  113. }
  114. public HalfDashboardUc()
  115. {
  116. InitializeComponent();
  117. //双缓存防止屏幕抖动
  118. this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true);
  119. this.SetStyle(ControlStyles.UserPaint, true);
  120. this.UpdateStyles();
  121. //设置背景颜色为透明
  122. this.BackColor = Color.Transparent;
  123. }
  124. //private int uintfontsize = 40;
  125. /// <summary>
  126. /// 初始化仪表盘画布
  127. /// </summary>
  128. private void InitialCanvas()
  129. {
  130. //对比控件的长高,以最小值为仪表盘的半径
  131. if (this.Width > 2 * this.Height)
  132. {
  133. diameter = 2 * this.Height - 15;
  134. }
  135. else
  136. {
  137. diameter = this.Width - 15;
  138. }
  139. multiple = (float)diameter / maxSize;//计算仪表盘放大倍数
  140. //如果半径大于仪表盘的最大值,则设定放大倍数为默认值
  141. if (multiple > 1)
  142. {
  143. multiple = 1;
  144. diameter = maxSize;
  145. }
  146. intervalValue = (int)((MaxValue - minValue) / 3);//计算每个间隔之间的值
  147. }
  148. /// <summary>
  149. /// 画底图
  150. /// </summary>
  151. private void drawBackImage()
  152. {
  153. Bitmap bit = new Bitmap(this.Width, this.Height);
  154. Graphics gp = Graphics.FromImage(bit);
  155. gp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  156. float radius = diameter / 2;//半径
  157. float cerX = this.Width / 2;
  158. float cerY = this.Height / 2 + radius / 2 - 10 * multiple;
  159. //float cerY = this.Height - 20 ;
  160. gp.TranslateTransform(cerX, cerY);//以中心点为画布的起始点
  161. //gp.DrawPie(new Pen(new SolidBrush(Color.FromArgb(19,20,25)),3), -radius, -radius, diameter, diameter, 175, 190);
  162. gp.DrawArc(new Pen(new SolidBrush(Color.FromArgb(19, 20, 25)), 3), -radius, -radius, diameter, diameter, 175, 190);
  163. float x1 = (float)((radius) * Math.Cos(175 * Math.PI / 180));
  164. float y1 = (float)((radius) * Math.Sin(175 * Math.PI / 180));
  165. float x2 = (float)((radius) * Math.Cos(5 * Math.PI / 180));
  166. float y2 = (float)((radius) * Math.Sin(5 * Math.PI / 180));
  167. gp.DrawLine(new Pen(new SolidBrush(Color.FromArgb(19, 20, 25)), 3), x1, y1, x2, y2);
  168. //gp.DrawEllipse(new Pen(Brushes.Red), -5, -5, 10, 10);
  169. float startRad = 180;//起始角度
  170. float sweepShot = 0;//旋转角度
  171. //gp.DrawLine(new Pen(Brushes.Red), -radius, 0, -(radius - 10), 0);
  172. for (int i = 0; i <= 30; i++)
  173. {
  174. double rad = (sweepShot + startRad) * Math.PI / 180;
  175. if (i % 5 == 0)
  176. {
  177. float px1 = (float)((radius - 5 ) * Math.Cos(rad));
  178. float py1 = (float)((radius - 5 ) * Math.Sin(rad));
  179. float px2 = (float)((radius - 15) * Math.Cos(rad));
  180. float py2 = (float)((radius - 15) * Math.Sin(rad));
  181. gp.DrawLine(new Pen(new SolidBrush(Color.FromArgb(122, 179, 222)), 2), px1, py1, px2, py2);
  182. }
  183. else
  184. {
  185. float px1 = (float)((radius - 5 ) * Math.Cos(rad));
  186. float py1 = (float)((radius - 5 ) * Math.Sin(rad));
  187. float px2 = (float)((radius - 10 ) * Math.Cos(rad));
  188. float py2 = (float)((radius - 10 ) * Math.Sin(rad));
  189. gp.DrawLine(new Pen(new SolidBrush(Color.FromArgb(77, 88, 124)), 1), px1, py1, px2, py2);
  190. }
  191. sweepShot += 6;
  192. }
  193. //刻度字体
  194. Font scaleFont = new Font("宋体", 9, FontStyle.Bold);
  195. startRad = 270;//起始角度
  196. sweepShot = 0;//旋转角度
  197. Color c1 = Color.FromArgb(0, 192, 0);
  198. for (int i = 0; i < 4; i++)
  199. {
  200. int tempValue = i * intervalValue;
  201. SizeF tempSf = gp.MeasureString(tempValue.ToString(), scaleFont);
  202. //计算角度值
  203. double rad = (sweepShot + startRad) * Math.PI / 180;
  204. float px = (float)((radius - 18) * Math.Cos(rad));
  205. float py = (float)((radius - 18) * Math.Sin(rad));
  206. if (sweepShot == 0)
  207. {
  208. gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Wheat, px - tempSf.Width / 2, py);
  209. }
  210. else if (sweepShot == 30)
  211. {
  212. gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width + 5 * multiple, py - tempSf.Height / 2 + 10 * multiple);
  213. }
  214. else if (sweepShot == 60)
  215. {
  216. gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width, py - tempSf.Height / 2 + 5 * multiple);
  217. }
  218. else if (sweepShot == 90)
  219. {
  220. gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width, py - tempSf.Height / 2);
  221. }
  222. //else if (sweepShot == 120)
  223. //{
  224. // gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width, py - tempSf.Height / 2);
  225. //}
  226. sweepShot += 30;
  227. }
  228. startRad = 270;//起始角度
  229. sweepShot = 0;//旋转角度
  230. for (int i = 0; i < 4; i++)
  231. {
  232. int tempValue = -i * intervalValue;
  233. SizeF tempSf = gp.MeasureString(tempValue.ToString(), scaleFont);
  234. //计算角度值
  235. double rad = (sweepShot + startRad) * Math.PI / 180;
  236. float px = (float)((radius - 18 * multiple) * Math.Cos(rad));
  237. float py = (float)((radius - 18 * multiple) * Math.Sin(rad));
  238. if (sweepShot == -30)
  239. {
  240. gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Red, px, py + tempSf.Height / 2);
  241. }
  242. else if (sweepShot == -60)
  243. {
  244. gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Red, px + tempSf.Width / 2 - 10 * multiple, py + tempSf.Height / 2 - 5 * multiple);
  245. }
  246. else if (sweepShot == -90)
  247. {
  248. gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Red, px + tempSf.Width/2 , py - tempSf.Height / 2);
  249. }
  250. sweepShot -= 30;
  251. }
  252. gp.Dispose();
  253. this.BackgroundImage = bit;
  254. }
  255. /// <summary>
  256. /// 画图
  257. /// </summary>
  258. /// <param name="g"></param>
  259. private void DrawPin(Graphics g)
  260. {
  261. Bitmap bit = new Bitmap(this.Width, this.Height);
  262. Graphics gp = Graphics.FromImage(bit);
  263. gp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  264. float radius = diameter / 2;//半径
  265. float startRad = 270;//起始角度
  266. float sweepShot = (float)(ChangeValue / MaxValue * 90);//旋转角度
  267. float cerX = this.Width / 2;
  268. float cerY = this.Height / 2 + radius / 2 - 10 * multiple;
  269. gp.TranslateTransform(cerX, cerY);//以中心点为画布的起始点
  270. //gp.DrawEllipse(new Pen(PinColor, 1), -5, -5, 10, 10);//画中心圆圈
  271. double rad = (sweepShot + startRad) * Math.PI / 180;//计算角度
  272. float px = (float)((radius - 15) * Math.Cos(rad));
  273. float py = (float)((radius - 15) * Math.Sin(rad));
  274. PointF[] pf = new PointF[] { new PointF(0, -radius + 15), new PointF(-4, 0), new PointF(4, 0) };
  275. gp.RotateTransform(sweepShot);
  276. //PointF[] pf = new PointF[] { new PointF(px, py), new PointF(-4, 0), new PointF(4, 0) };
  277. gp.FillPolygon(new SolidBrush(PinColor), pf);
  278. //gp.DrawLine(new Pen(new SolidBrush(PinColor), 3f), 0, 0, px, py);
  279. g.DrawImage(bit, 0, 0);
  280. gp.Dispose();
  281. }
  282. private void HalfDashboardUc_Load(object sender, EventArgs e)
  283. {
  284. InitialCanvas();
  285. drawBackImage();
  286. }
  287. private void HalfDashboardUc_Paint(object sender, PaintEventArgs e)
  288. {
  289. DrawPin(e.Graphics);
  290. }
  291. private void HalfDashboardUc_Resize(object sender, EventArgs e)
  292. {
  293. InitialCanvas();
  294. drawBackImage();
  295. }
  296. }

效果实现如下:

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号