zoukankan      html  css  js  c++  java
  • (五十四)c#Winform自定义控件-仪表盘-HZHControls

    官网

    http://www.hzhcontrols.com

    前提

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

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

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

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

    欢迎前来交流探讨: 企鹅群568015492 企鹅群568015492

    麻烦博客下方点个【推荐】,谢谢

    NuGet

    Install-Package HZH_Controls

    目录

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

    用处及效果

    准备工作

    依然使用GDI+画的,不懂的话就百度一下吧

    另外主要用到了三角函数,如果不懂,可以向初中的数学老师再问问(你也可以百度一下)

    开始

    添加一个类UCMeter 继承 UserControl

    首先添加一个需要控制的属性

      1 private int splitCount = 10;
      2         /// <summary>
      3         /// Gets or sets the split count.
      4         /// </summary>
      5         /// <value>The split count.</value>
      6         [Description("分隔刻度数量,>1"), Category("自定义")]
      7         public int SplitCount
      8         {
      9             get { return splitCount; }
     10             set
     11             {
     12                 if (value < 1)
     13                     return;
     14                 splitCount = value;
     15                 Refresh();
     16             }
     17         }
     18 
     19         private int meterDegrees = 150;
     20         /// <summary>
     21         /// Gets or sets the meter degrees.
     22         /// </summary>
     23         /// <value>The meter degrees.</value>
     24         [Description("表盘跨度角度,0-360"), Category("自定义")]
     25         public int MeterDegrees
     26         {
     27             get { return meterDegrees; }
     28             set
     29             {
     30                 if (value > 360 || value <= 0)
     31                     return;
     32                 meterDegrees = value;
     33                 Refresh();
     34             }
     35         }
     36 
     37         private decimal minValue = 0;
     38         /// <summary>
     39         /// Gets or sets the minimum value.
     40         /// </summary>
     41         /// <value>The minimum value.</value>
     42         [Description("最小值,<MaxValue"), Category("自定义")]
     43         public decimal MinValue
     44         {
     45             get { return minValue; }
     46             set
     47             {
     48                 if (value >= maxValue)
     49                     return;
     50                 minValue = value;
     51                 Refresh();
     52             }
     53         }
     54 
     55         private decimal maxValue = 100;
     56         /// <summary>
     57         /// Gets or sets the maximum value.
     58         /// </summary>
     59         /// <value>The maximum value.</value>
     60         [Description("最大值,>MinValue"), Category("自定义")]
     61         public decimal MaxValue
     62         {
     63             get { return maxValue; }
     64             set
     65             {
     66                 if (value <= minValue)
     67                     return;
     68                 maxValue = value;
     69                 Refresh();
     70             }
     71         }
     72         /// <summary>
     73         /// 获取或设置控件显示的文字的字体。
     74         /// </summary>
     75         /// <value>The font.</value>
     76         /// <PermissionSet>
     77         ///   <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
     78         ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
     79         ///   <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
     80         ///   <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
     81         /// </PermissionSet>
     82         [Description("刻度字体"), Category("自定义")]
     83         public override Font Font
     84         {
     85             get
     86             {
     87                 return base.Font;
     88             }
     89             set
     90             {
     91                 base.Font = value;
     92                 Refresh();
     93             }
     94         }
     95 
     96         private decimal m_value = 0;
     97         /// <summary>
     98         /// Gets or sets the value.
     99         /// </summary>
    100         /// <value>The value.</value>
    101         [Description("值,>=MinValue并且<=MaxValue"), Category("自定义")]
    102         public decimal Value
    103         {
    104             get { return m_value; }
    105             set
    106             {
    107                 if (value < minValue || value > maxValue)
    108                     return;
    109                 m_value = value;
    110                 Refresh();
    111             }
    112         }
    113 
    114         private MeterTextLocation textLocation = MeterTextLocation.None;
    115         /// <summary>
    116         /// Gets or sets the text location.
    117         /// </summary>
    118         /// <value>The text location.</value>
    119         [Description("值和固定文字显示位置"), Category("自定义")]
    120         public MeterTextLocation TextLocation
    121         {
    122             get { return textLocation; }
    123             set
    124             {
    125                 textLocation = value;
    126                 Refresh();
    127             }
    128         }
    129 
    130         private string fixedText;
    131         /// <summary>
    132         /// Gets or sets the fixed text.
    133         /// </summary>
    134         /// <value>The fixed text.</value>
    135         [Description("固定文字"), Category("自定义")]
    136         public string FixedText
    137         {
    138             get { return fixedText; }
    139             set
    140             {
    141                 fixedText = value;
    142                 Refresh();
    143             }
    144         }
    145 
    146         private Font textFont = DefaultFont;
    147         /// <summary>
    148         /// Gets or sets the text font.
    149         /// </summary>
    150         /// <value>The text font.</value>
    151         [Description("值和固定文字字体"), Category("自定义")]
    152         public Font TextFont
    153         {
    154             get { return textFont; }
    155             set
    156             {
    157                 textFont = value;
    158                 Refresh();
    159             }
    160         }
    161 
    162         private Color externalRoundColor = Color.FromArgb(255, 77, 59);
    163         /// <summary>
    164         /// Gets or sets the color of the external round.
    165         /// </summary>
    166         /// <value>The color of the external round.</value>
    167         [Description("外圆颜色"), Category("自定义")]
    168         public Color ExternalRoundColor
    169         {
    170             get { return externalRoundColor; }
    171             set
    172             {
    173                 externalRoundColor = value;
    174                 Refresh();
    175             }
    176         }
    177 
    178         private Color insideRoundColor = Color.FromArgb(255, 77, 59);
    179         /// <summary>
    180         /// Gets or sets the color of the inside round.
    181         /// </summary>
    182         /// <value>The color of the inside round.</value>
    183         [Description("内圆颜色"), Category("自定义")]
    184         public Color InsideRoundColor
    185         {
    186             get { return insideRoundColor; }
    187             set
    188             {
    189                 insideRoundColor = value;
    190                 Refresh();
    191             }
    192         }
    193 
    194         private Color boundaryLineColor = Color.FromArgb(255, 77, 59);
    195         /// <summary>
    196         /// Gets or sets the color of the boundary line.
    197         /// </summary>
    198         /// <value>The color of the boundary line.</value>
    199         [Description("边界线颜色"), Category("自定义")]
    200         public Color BoundaryLineColor
    201         {
    202             get { return boundaryLineColor; }
    203             set
    204             {
    205                 boundaryLineColor = value;
    206                 Refresh();
    207             }
    208         }
    209 
    210         private Color scaleColor = Color.FromArgb(255, 77, 59);
    211         /// <summary>
    212         /// Gets or sets the color of the scale.
    213         /// </summary>
    214         /// <value>The color of the scale.</value>
    215         [Description("刻度颜色"), Category("自定义")]
    216         public Color ScaleColor
    217         {
    218             get { return scaleColor; }
    219             set
    220             {
    221                 scaleColor = value;
    222                 Refresh();
    223             }
    224         }
    225 
    226         private Color scaleValueColor = Color.FromArgb(255, 77, 59);
    227         /// <summary>
    228         /// Gets or sets the color of the scale value.
    229         /// </summary>
    230         /// <value>The color of the scale value.</value>
    231         [Description("刻度值文字颜色"), Category("自定义")]
    232         public Color ScaleValueColor
    233         {
    234             get { return scaleValueColor; }
    235             set
    236             {
    237                 scaleValueColor = value;
    238                 Refresh();
    239             }
    240         }
    241 
    242         private Color pointerColor = Color.FromArgb(255, 77, 59);
    243         /// <summary>
    244         /// Gets or sets the color of the pointer.
    245         /// </summary>
    246         /// <value>The color of the pointer.</value>
    247         [Description("指针颜色"), Category("自定义")]
    248         public Color PointerColor
    249         {
    250             get { return pointerColor; }
    251             set
    252             {
    253                 pointerColor = value;
    254                 Refresh();
    255             }
    256         }
    257 
    258         private Color textColor = Color.FromArgb(255, 77, 59);
    259         /// <summary>
    260         /// Gets or sets the color of the text.
    261         /// </summary>
    262         /// <value>The color of the text.</value>
    263         [Description("值和固定文字颜色"), Category("自定义")]
    264         public Color TextColor
    265         {
    266             get { return textColor; }
    267             set
    268             {
    269                 textColor = value;
    270                 Refresh();
    271             }
    272         }
    273 
    274         Rectangle m_rectWorking;

    重绘

     1  protected override void OnPaint(PaintEventArgs e)
     2         {
     3             base.OnPaint(e);
     4             var g = e.Graphics;
     5             g.SetGDIHigh();
     6 
     7             //外圆
     8             float fltStartAngle = -90 - (meterDegrees) / 2 + 360;
     9             var r1 = new Rectangle(m_rectWorking.Location, new Size(m_rectWorking.Width, m_rectWorking.Width));
    10             g.DrawArc(new Pen(new SolidBrush(externalRoundColor), 1), r1, fltStartAngle, meterDegrees);
    11             //内圆
    12             var r2 = new Rectangle(m_rectWorking.Left + (m_rectWorking.Width - m_rectWorking.Width / 4) / 2, m_rectWorking.Top + (m_rectWorking.Width - m_rectWorking.Width / 4) / 2, m_rectWorking.Width / 4, m_rectWorking.Width / 4);
    13             g.DrawArc(new Pen(new SolidBrush(insideRoundColor), 1), r2, fltStartAngle, meterDegrees);
    14 
    15             //边界线
    16             if (meterDegrees != 360)
    17             {
    18                 float fltAngle = fltStartAngle - 180;
    19 
    20                 float intY = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - m_rectWorking.Width / 8) * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    21                 float intX = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - m_rectWorking.Width / 8) * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    22 
    23                 float fltY1 = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - (m_rectWorking.Width / 8 * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    24                 float fltX1 = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - (m_rectWorking.Width / 8 * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    25 
    26                 g.DrawLine(new Pen(new SolidBrush(boundaryLineColor), 1), new PointF(intX, intY), new PointF(fltX1, fltY1));
    27                 g.DrawLine(new Pen(new SolidBrush(boundaryLineColor), 1), new PointF(m_rectWorking.Right - (fltX1 - m_rectWorking.Left), fltY1), new PointF(m_rectWorking.Right - (intX - m_rectWorking.Left), intY));
    28             }
    29 
    30             //分割线
    31             int _splitCount = splitCount * 2;
    32             float fltSplitValue = (float)meterDegrees / (float)_splitCount;
    33             for (int i = 0; i <= _splitCount; i++)
    34             {
    35                 float fltAngle = (fltStartAngle + fltSplitValue * i - 180) % 360;
    36                 float fltY1 = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2) * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    37                 float fltX1 = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2) * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    38                 float fltY2 = 0;
    39                 float fltX2 = 0;
    40                 if (i % 2 == 0)
    41                 {
    42                     fltY2 = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 10) * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    43                     fltX2 = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 10) * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    44                     if (!(meterDegrees == 360 && i == _splitCount))
    45                     {
    46                         decimal decValue = minValue + (maxValue - minValue) / _splitCount * i;
    47                         var txtSize = g.MeasureString(decValue.ToString("0.##"), this.Font);
    48                         float fltFY1 = (float)(m_rectWorking.Top - txtSize.Height / 2 + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 20) * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    49                         float fltFX1 = (float)(m_rectWorking.Left - txtSize.Width / 2 + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 20) * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    50                         g.DrawString(decValue.ToString("0.##"), Font, new SolidBrush(scaleValueColor), fltFX1, fltFY1);
    51                     }
    52                 }
    53                 else
    54                 {
    55                     fltY2 = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 5) * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    56                     fltX2 = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 5) * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    57                 }
    58                 g.DrawLine(new Pen(new SolidBrush(scaleColor), i % 2 == 0 ? 2 : 1), new PointF(fltX1, fltY1), new PointF(fltX2, fltY2));
    59             }
    60 
    61             //值文字和固定文字
    62             if (textLocation != MeterTextLocation.None)
    63             {
    64                 string str = m_value.ToString("0.##");
    65                 var txtSize = g.MeasureString(str, textFont);
    66                 float fltY = m_rectWorking.Top + m_rectWorking.Width / 4 - txtSize.Height / 2;
    67                 float fltX = m_rectWorking.Left + m_rectWorking.Width / 2 - txtSize.Width / 2;
    68                 g.DrawString(str, textFont, new SolidBrush(textColor), new PointF(fltX, fltY));
    69 
    70                 if (!string.IsNullOrEmpty(fixedText))
    71                 {
    72                     str = fixedText;
    73                     txtSize = g.MeasureString(str, textFont);
    74                     fltY = m_rectWorking.Top + m_rectWorking.Width / 4 + txtSize.Height / 2;
    75                     fltX = m_rectWorking.Left + m_rectWorking.Width / 2 - txtSize.Width / 2;
    76                     g.DrawString(str, textFont, new SolidBrush(textColor), new PointF(fltX, fltY));
    77                 }
    78             }
    79 
    80             //画指针
    81             g.FillEllipse(new SolidBrush(Color.FromArgb(100, pointerColor.R, pointerColor.G, pointerColor.B)), new Rectangle(m_rectWorking.Left + m_rectWorking.Width / 2 - 10, m_rectWorking.Top + m_rectWorking.Width / 2 - 10, 20, 20));
    82             g.FillEllipse(Brushes.Red, new Rectangle(m_rectWorking.Left + m_rectWorking.Width / 2 - 5, m_rectWorking.Top + m_rectWorking.Width / 2 - 5, 10, 10));
    83             float fltValueAngle = (fltStartAngle + ((float)(m_value - minValue) / (float)(maxValue - minValue)) * (float)meterDegrees - 180) % 360;
    84             float intValueY1 = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 30) * Math.Sin(Math.PI * (fltValueAngle / 180.00F))));
    85             float intValueX1 = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 30) * Math.Cos(Math.PI * (fltValueAngle / 180.00F)))));
    86             g.DrawLine(new Pen(new SolidBrush(pointerColor), 3), intValueX1, intValueY1, m_rectWorking.Left + m_rectWorking.Width / 2, m_rectWorking.Top + m_rectWorking.Width / 2);
    87         }

    还有一个显示文字位置的枚举

     1 /// <summary>
     2     /// Enum MeterTextLocation
     3     /// </summary>
     4     public enum MeterTextLocation
     5     {
     6         /// <summary>
     7         /// The none
     8         /// </summary>
     9         None,
    10         /// <summary>
    11         /// The top
    12         /// </summary>
    13         Top,
    14         /// <summary>
    15         /// The bottom
    16         /// </summary>
    17         Bottom
    18     }

    代码就这么多了,看完整代码

      1 // ***********************************************************************
      2 // Assembly         : HZH_Controls
      3 // Created          : 2019-09-03
      4 //
      5 // ***********************************************************************
      6 // <copyright file="UCMeter.cs">
      7 //     Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
      8 // </copyright>
      9 //
     10 // Blog: https://www.cnblogs.com/bfyx
     11 // GitHub:https://github.com/kwwwvagaa/NetWinformControl
     12 // gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
     13 //
     14 // If you use this code, please keep this note.
     15 // ***********************************************************************
     16 using System;
     17 using System.Collections.Generic;
     18 using System.Linq;
     19 using System.Text;
     20 using System.Windows.Forms;
     21 using System.Drawing;
     22 using System.Drawing.Drawing2D;
     23 using System.ComponentModel;
     24 
     25 namespace HZH_Controls.Controls
     26 {
     27     /// <summary>
     28     /// Class UCMeter.
     29     /// Implements the <see cref="System.Windows.Forms.UserControl" />
     30     /// </summary>
     31     /// <seealso cref="System.Windows.Forms.UserControl" />
     32     public class UCMeter : UserControl
     33     {
     34         private int splitCount = 10;
     35         /// <summary>
     36         /// Gets or sets the split count.
     37         /// </summary>
     38         /// <value>The split count.</value>
     39         [Description("分隔刻度数量,>1"), Category("自定义")]
     40         public int SplitCount
     41         {
     42             get { return splitCount; }
     43             set
     44             {
     45                 if (value < 1)
     46                     return;
     47                 splitCount = value;
     48                 Refresh();
     49             }
     50         }
     51 
     52         private int meterDegrees = 150;
     53         /// <summary>
     54         /// Gets or sets the meter degrees.
     55         /// </summary>
     56         /// <value>The meter degrees.</value>
     57         [Description("表盘跨度角度,0-360"), Category("自定义")]
     58         public int MeterDegrees
     59         {
     60             get { return meterDegrees; }
     61             set
     62             {
     63                 if (value > 360 || value <= 0)
     64                     return;
     65                 meterDegrees = value;
     66                 Refresh();
     67             }
     68         }
     69 
     70         private decimal minValue = 0;
     71         /// <summary>
     72         /// Gets or sets the minimum value.
     73         /// </summary>
     74         /// <value>The minimum value.</value>
     75         [Description("最小值,<MaxValue"), Category("自定义")]
     76         public decimal MinValue
     77         {
     78             get { return minValue; }
     79             set
     80             {
     81                 if (value >= maxValue)
     82                     return;
     83                 minValue = value;
     84                 Refresh();
     85             }
     86         }
     87 
     88         private decimal maxValue = 100;
     89         /// <summary>
     90         /// Gets or sets the maximum value.
     91         /// </summary>
     92         /// <value>The maximum value.</value>
     93         [Description("最大值,>MinValue"), Category("自定义")]
     94         public decimal MaxValue
     95         {
     96             get { return maxValue; }
     97             set
     98             {
     99                 if (value <= minValue)
    100                     return;
    101                 maxValue = value;
    102                 Refresh();
    103             }
    104         }
    105         /// <summary>
    106         /// 获取或设置控件显示的文字的字体。
    107         /// </summary>
    108         /// <value>The font.</value>
    109         /// <PermissionSet>
    110         ///   <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
    111         ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
    112         ///   <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
    113         ///   <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
    114         /// </PermissionSet>
    115         [Description("刻度字体"), Category("自定义")]
    116         public override Font Font
    117         {
    118             get
    119             {
    120                 return base.Font;
    121             }
    122             set
    123             {
    124                 base.Font = value;
    125                 Refresh();
    126             }
    127         }
    128 
    129         private decimal m_value = 0;
    130         /// <summary>
    131         /// Gets or sets the value.
    132         /// </summary>
    133         /// <value>The value.</value>
    134         [Description("值,>=MinValue并且<=MaxValue"), Category("自定义")]
    135         public decimal Value
    136         {
    137             get { return m_value; }
    138             set
    139             {
    140                 if (value < minValue || value > maxValue)
    141                     return;
    142                 m_value = value;
    143                 Refresh();
    144             }
    145         }
    146 
    147         private MeterTextLocation textLocation = MeterTextLocation.None;
    148         /// <summary>
    149         /// Gets or sets the text location.
    150         /// </summary>
    151         /// <value>The text location.</value>
    152         [Description("值和固定文字显示位置"), Category("自定义")]
    153         public MeterTextLocation TextLocation
    154         {
    155             get { return textLocation; }
    156             set
    157             {
    158                 textLocation = value;
    159                 Refresh();
    160             }
    161         }
    162 
    163         private string fixedText;
    164         /// <summary>
    165         /// Gets or sets the fixed text.
    166         /// </summary>
    167         /// <value>The fixed text.</value>
    168         [Description("固定文字"), Category("自定义")]
    169         public string FixedText
    170         {
    171             get { return fixedText; }
    172             set
    173             {
    174                 fixedText = value;
    175                 Refresh();
    176             }
    177         }
    178 
    179         private Font textFont = DefaultFont;
    180         /// <summary>
    181         /// Gets or sets the text font.
    182         /// </summary>
    183         /// <value>The text font.</value>
    184         [Description("值和固定文字字体"), Category("自定义")]
    185         public Font TextFont
    186         {
    187             get { return textFont; }
    188             set
    189             {
    190                 textFont = value;
    191                 Refresh();
    192             }
    193         }
    194 
    195         private Color externalRoundColor = Color.FromArgb(255, 77, 59);
    196         /// <summary>
    197         /// Gets or sets the color of the external round.
    198         /// </summary>
    199         /// <value>The color of the external round.</value>
    200         [Description("外圆颜色"), Category("自定义")]
    201         public Color ExternalRoundColor
    202         {
    203             get { return externalRoundColor; }
    204             set
    205             {
    206                 externalRoundColor = value;
    207                 Refresh();
    208             }
    209         }
    210 
    211         private Color insideRoundColor = Color.FromArgb(255, 77, 59);
    212         /// <summary>
    213         /// Gets or sets the color of the inside round.
    214         /// </summary>
    215         /// <value>The color of the inside round.</value>
    216         [Description("内圆颜色"), Category("自定义")]
    217         public Color InsideRoundColor
    218         {
    219             get { return insideRoundColor; }
    220             set
    221             {
    222                 insideRoundColor = value;
    223                 Refresh();
    224             }
    225         }
    226 
    227         private Color boundaryLineColor = Color.FromArgb(255, 77, 59);
    228         /// <summary>
    229         /// Gets or sets the color of the boundary line.
    230         /// </summary>
    231         /// <value>The color of the boundary line.</value>
    232         [Description("边界线颜色"), Category("自定义")]
    233         public Color BoundaryLineColor
    234         {
    235             get { return boundaryLineColor; }
    236             set
    237             {
    238                 boundaryLineColor = value;
    239                 Refresh();
    240             }
    241         }
    242 
    243         private Color scaleColor = Color.FromArgb(255, 77, 59);
    244         /// <summary>
    245         /// Gets or sets the color of the scale.
    246         /// </summary>
    247         /// <value>The color of the scale.</value>
    248         [Description("刻度颜色"), Category("自定义")]
    249         public Color ScaleColor
    250         {
    251             get { return scaleColor; }
    252             set
    253             {
    254                 scaleColor = value;
    255                 Refresh();
    256             }
    257         }
    258 
    259         private Color scaleValueColor = Color.FromArgb(255, 77, 59);
    260         /// <summary>
    261         /// Gets or sets the color of the scale value.
    262         /// </summary>
    263         /// <value>The color of the scale value.</value>
    264         [Description("刻度值文字颜色"), Category("自定义")]
    265         public Color ScaleValueColor
    266         {
    267             get { return scaleValueColor; }
    268             set
    269             {
    270                 scaleValueColor = value;
    271                 Refresh();
    272             }
    273         }
    274 
    275         private Color pointerColor = Color.FromArgb(255, 77, 59);
    276         /// <summary>
    277         /// Gets or sets the color of the pointer.
    278         /// </summary>
    279         /// <value>The color of the pointer.</value>
    280         [Description("指针颜色"), Category("自定义")]
    281         public Color PointerColor
    282         {
    283             get { return pointerColor; }
    284             set
    285             {
    286                 pointerColor = value;
    287                 Refresh();
    288             }
    289         }
    290 
    291         private Color textColor = Color.FromArgb(255, 77, 59);
    292         /// <summary>
    293         /// Gets or sets the color of the text.
    294         /// </summary>
    295         /// <value>The color of the text.</value>
    296         [Description("值和固定文字颜色"), Category("自定义")]
    297         public Color TextColor
    298         {
    299             get { return textColor; }
    300             set
    301             {
    302                 textColor = value;
    303                 Refresh();
    304             }
    305         }
    306 
    307         Rectangle m_rectWorking;
    308         public UCMeter()
    309         {
    310             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
    311             this.SetStyle(ControlStyles.DoubleBuffer, true);
    312             this.SetStyle(ControlStyles.ResizeRedraw, true);
    313             this.SetStyle(ControlStyles.Selectable, true);
    314             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
    315             this.SetStyle(ControlStyles.UserPaint, true);
    316             this.SizeChanged += UCMeter1_SizeChanged;
    317             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
    318             this.Size = new Size(350, 200);
    319         }
    320 
    321         void UCMeter1_SizeChanged(object sender, EventArgs e)
    322         {
    323             m_rectWorking = new Rectangle(10, 10, this.Width - 20, this.Height - 20);
    324         }
    325 
    326 
    327         protected override void OnPaint(PaintEventArgs e)
    328         {
    329             base.OnPaint(e);
    330             var g = e.Graphics;
    331             g.SetGDIHigh();
    332 
    333             //外圆
    334             float fltStartAngle = -90 - (meterDegrees) / 2 + 360;
    335             var r1 = new Rectangle(m_rectWorking.Location, new Size(m_rectWorking.Width, m_rectWorking.Width));
    336             g.DrawArc(new Pen(new SolidBrush(externalRoundColor), 1), r1, fltStartAngle, meterDegrees);
    337             //内圆
    338             var r2 = new Rectangle(m_rectWorking.Left + (m_rectWorking.Width - m_rectWorking.Width / 4) / 2, m_rectWorking.Top + (m_rectWorking.Width - m_rectWorking.Width / 4) / 2, m_rectWorking.Width / 4, m_rectWorking.Width / 4);
    339             g.DrawArc(new Pen(new SolidBrush(insideRoundColor), 1), r2, fltStartAngle, meterDegrees);
    340 
    341             //边界线
    342             if (meterDegrees != 360)
    343             {
    344                 float fltAngle = fltStartAngle - 180;
    345 
    346                 float intY = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - m_rectWorking.Width / 8) * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    347                 float intX = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - m_rectWorking.Width / 8) * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    348 
    349                 float fltY1 = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - (m_rectWorking.Width / 8 * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    350                 float fltX1 = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - (m_rectWorking.Width / 8 * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    351 
    352                 g.DrawLine(new Pen(new SolidBrush(boundaryLineColor), 1), new PointF(intX, intY), new PointF(fltX1, fltY1));
    353                 g.DrawLine(new Pen(new SolidBrush(boundaryLineColor), 1), new PointF(m_rectWorking.Right - (fltX1 - m_rectWorking.Left), fltY1), new PointF(m_rectWorking.Right - (intX - m_rectWorking.Left), intY));
    354             }
    355 
    356             //分割线
    357             int _splitCount = splitCount * 2;
    358             float fltSplitValue = (float)meterDegrees / (float)_splitCount;
    359             for (int i = 0; i <= _splitCount; i++)
    360             {
    361                 float fltAngle = (fltStartAngle + fltSplitValue * i - 180) % 360;
    362                 float fltY1 = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2) * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    363                 float fltX1 = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2) * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    364                 float fltY2 = 0;
    365                 float fltX2 = 0;
    366                 if (i % 2 == 0)
    367                 {
    368                     fltY2 = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 10) * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    369                     fltX2 = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 10) * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    370                     if (!(meterDegrees == 360 && i == _splitCount))
    371                     {
    372                         decimal decValue = minValue + (maxValue - minValue) / _splitCount * i;
    373                         var txtSize = g.MeasureString(decValue.ToString("0.##"), this.Font);
    374                         float fltFY1 = (float)(m_rectWorking.Top - txtSize.Height / 2 + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 20) * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    375                         float fltFX1 = (float)(m_rectWorking.Left - txtSize.Width / 2 + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 20) * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    376                         g.DrawString(decValue.ToString("0.##"), Font, new SolidBrush(scaleValueColor), fltFX1, fltFY1);
    377                     }
    378                 }
    379                 else
    380                 {
    381                     fltY2 = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 5) * Math.Sin(Math.PI * (fltAngle / 180.00F))));
    382                     fltX2 = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 5) * Math.Cos(Math.PI * (fltAngle / 180.00F)))));
    383                 }
    384                 g.DrawLine(new Pen(new SolidBrush(scaleColor), i % 2 == 0 ? 2 : 1), new PointF(fltX1, fltY1), new PointF(fltX2, fltY2));
    385             }
    386 
    387             //值文字和固定文字
    388             if (textLocation != MeterTextLocation.None)
    389             {
    390                 string str = m_value.ToString("0.##");
    391                 var txtSize = g.MeasureString(str, textFont);
    392                 float fltY = m_rectWorking.Top + m_rectWorking.Width / 4 - txtSize.Height / 2;
    393                 float fltX = m_rectWorking.Left + m_rectWorking.Width / 2 - txtSize.Width / 2;
    394                 g.DrawString(str, textFont, new SolidBrush(textColor), new PointF(fltX, fltY));
    395 
    396                 if (!string.IsNullOrEmpty(fixedText))
    397                 {
    398                     str = fixedText;
    399                     txtSize = g.MeasureString(str, textFont);
    400                     fltY = m_rectWorking.Top + m_rectWorking.Width / 4 + txtSize.Height / 2;
    401                     fltX = m_rectWorking.Left + m_rectWorking.Width / 2 - txtSize.Width / 2;
    402                     g.DrawString(str, textFont, new SolidBrush(textColor), new PointF(fltX, fltY));
    403                 }
    404             }
    405 
    406             //画指针
    407             g.FillEllipse(new SolidBrush(Color.FromArgb(100, pointerColor.R, pointerColor.G, pointerColor.B)), new Rectangle(m_rectWorking.Left + m_rectWorking.Width / 2 - 10, m_rectWorking.Top + m_rectWorking.Width / 2 - 10, 20, 20));
    408             g.FillEllipse(Brushes.Red, new Rectangle(m_rectWorking.Left + m_rectWorking.Width / 2 - 5, m_rectWorking.Top + m_rectWorking.Width / 2 - 5, 10, 10));
    409             float fltValueAngle = (fltStartAngle + ((float)(m_value - minValue) / (float)(maxValue - minValue)) * (float)meterDegrees - 180) % 360;
    410             float intValueY1 = (float)(m_rectWorking.Top + m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 30) * Math.Sin(Math.PI * (fltValueAngle / 180.00F))));
    411             float intValueX1 = (float)(m_rectWorking.Left + (m_rectWorking.Width / 2 - ((m_rectWorking.Width / 2 - 30) * Math.Cos(Math.PI * (fltValueAngle / 180.00F)))));
    412             g.DrawLine(new Pen(new SolidBrush(pointerColor), 3), intValueX1, intValueY1, m_rectWorking.Left + m_rectWorking.Width / 2, m_rectWorking.Top + m_rectWorking.Width / 2);
    413         }
    414     }
    415 
    416     /// <summary>
    417     /// Enum MeterTextLocation
    418     /// </summary>
    419     public enum MeterTextLocation
    420     {
    421         /// <summary>
    422         /// The none
    423         /// </summary>
    424         None,
    425         /// <summary>
    426         /// The top
    427         /// </summary>
    428         Top,
    429         /// <summary>
    430         /// The bottom
    431         /// </summary>
    432         Bottom
    433     }
    434 }
    View Code

    最后的话

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

  • 相关阅读:
    再叙存储设备
    分布式文件系统---测试
    分布式文件系统
    Solr 分布式(复制)配置--成功验证
    搜索服务之离线处理思路
    我为公司做的总体架构,欢迎提建议
    python的面向对象
    python异常处理
    迭代器和生成器
    python函数
  • 原文地址:https://www.cnblogs.com/bfyx/p/11457234.html
Copyright © 2011-2022 走看看