欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

c# Winform自定义控件-仪表盘功能

程序员文章站 2022-03-11 08:49:16
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 github:https://github.com/kwwwvagaa/netwinf...

前提

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

github:https://github.com/kwwwvagaa/netwinformcontrol

码云:

nuget

install-package hzh_controls

目录

用处及效果

c# Winform自定义控件-仪表盘功能

准备工作

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

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

开始

添加一个类ucmeter 继承 usercontrol

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

private int splitcount = 10;
     /// <summary>
     /// gets or sets the split count.
     /// </summary>
     /// <value>the split count.</value>
     [description("分隔刻度数量,>1"), category("自定义")]
     public int splitcount
     {
       get { return splitcount; }
      set
      {
        if (value < 1)
          return;
        splitcount = value;
        refresh();
      }
    }
    private int meterdegrees = 150;
    /// <summary>
    /// gets or sets the meter degrees.
    /// </summary>
    /// <value>the meter degrees.</value>
    [description("表盘跨度角度,0-360"), category("自定义")]
    public int meterdegrees
    {
      get { return meterdegrees; }
      set
      {
        if (value > 360 || value <= 0)
          return;
        meterdegrees = value;
        refresh();
      }
    }
    private decimal minvalue = 0;
    /// <summary>
    /// gets or sets the minimum value.
    /// </summary>
    /// <value>the minimum value.</value>
    [description("最小值,<maxvalue"), category("自定义")]
    public decimal minvalue
    {
      get { return minvalue; }
      set
      {
        if (value >= maxvalue)
          return;
        minvalue = value;
        refresh();
      }
    }
    private decimal maxvalue = 100;
    /// <summary>
    /// gets or sets the maximum value.
    /// </summary>
    /// <value>the maximum value.</value>
    [description("最大值,>minvalue"), category("自定义")]
    public decimal maxvalue
    {
      get { return maxvalue; }
      set
      {
        if (value <= minvalue)
          return;
        maxvalue = value;
        refresh();
      }
    }
    /// <summary>
    /// 获取或设置控件显示的文字的字体。
    /// </summary>
    /// <value>the font.</value>
    /// <permissionset>
    ///  <ipermission class="system.security.permissions.environmentpermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" />
    ///  <ipermission class="system.security.permissions.fileiopermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" />
    ///  <ipermission class="system.security.permissions.securitypermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" flags="unmanagedcode, controlevidence" />
    ///  <ipermission class="system.diagnostics.performancecounterpermission, system, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" />
    /// </permissionset>
    [description("刻度字体"), category("自定义")]
    public override font font
    {
      get
      {
        return base.font;
      }
      set
      {
        base.font = value;
        refresh();
      }
    }
    private decimal m_value = 0;
    /// <summary>
    /// gets or sets the value.
    /// </summary>
    /// <value>the value.</value>
    [description("值,>=minvalue并且<=maxvalue"), category("自定义")]
    public decimal value
    {
      get { return m_value; }
      set
      {
        if (value < minvalue || value > maxvalue)
          return;
        m_value = value;
        refresh();
      }
    }
    private metertextlocation textlocation = metertextlocation.none;
    /// <summary>
    /// gets or sets the text location.
    /// </summary>
    /// <value>the text location.</value>
    [description("值和固定文字显示位置"), category("自定义")]
    public metertextlocation textlocation
    {
      get { return textlocation; }
      set
      {
        textlocation = value;
        refresh();
      }
    }
    private string fixedtext;
    /// <summary>
    /// gets or sets the fixed text.
    /// </summary>
    /// <value>the fixed text.</value>
    [description("固定文字"), category("自定义")]
    public string fixedtext
    {
      get { return fixedtext; }
      set
      {
        fixedtext = value;
        refresh();
      }
    }
    private font textfont = defaultfont;
    /// <summary>
    /// gets or sets the text font.
    /// </summary>
    /// <value>the text font.</value>
    [description("值和固定文字字体"), category("自定义")]
    public font textfont
    {
      get { return textfont; }
      set
      {
        textfont = value;
        refresh();
      }
    }
    private color externalroundcolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the external round.
    /// </summary>
    /// <value>the color of the external round.</value>
    [description("外圆颜色"), category("自定义")]
    public color externalroundcolor
    {
      get { return externalroundcolor; }
      set
      {
        externalroundcolor = value;
        refresh();
      }
    }
    private color insideroundcolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the inside round.
    /// </summary>
    /// <value>the color of the inside round.</value>
    [description("内圆颜色"), category("自定义")]
    public color insideroundcolor
    {
      get { return insideroundcolor; }
      set
      {
        insideroundcolor = value;
        refresh();
      }
    }
    private color boundarylinecolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the boundary line.
    /// </summary>
    /// <value>the color of the boundary line.</value>
    [description("边界线颜色"), category("自定义")]
    public color boundarylinecolor
    {
      get { return boundarylinecolor; }
      set
      {
        boundarylinecolor = value;
        refresh();
      }
    }
    private color scalecolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the scale.
    /// </summary>
    /// <value>the color of the scale.</value>
    [description("刻度颜色"), category("自定义")]
    public color scalecolor
    {
      get { return scalecolor; }
      set
      {
        scalecolor = value;
        refresh();
      }
    }
    private color scalevaluecolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the scale value.
    /// </summary>
    /// <value>the color of the scale value.</value>
    [description("刻度值文字颜色"), category("自定义")]
    public color scalevaluecolor
    {
      get { return scalevaluecolor; }
      set
      {
        scalevaluecolor = value;
        refresh();
      }
    }
    private color pointercolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the pointer.
    /// </summary>
    /// <value>the color of the pointer.</value>
    [description("指针颜色"), category("自定义")]
    public color pointercolor
    {
      get { return pointercolor; }
      set
      {
        pointercolor = value;
        refresh();
      }
    }
    private color textcolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the text.
    /// </summary>
    /// <value>the color of the text.</value>
    [description("值和固定文字颜色"), category("自定义")]
    public color textcolor
    {
      get { return textcolor; }
      set
      {
        textcolor = value;
        refresh();
      }
    }

    rectangle m_rectworking;

重绘

protected override void onpaint(painteventargs e)
     {
       base.onpaint(e);
       var g = e.graphics;
       g.setgdihigh();
       //外圆
       float fltstartangle = -90 - (meterdegrees) / 2 + 360;
       var r1 = new rectangle(m_rectworking.location, new size(m_rectworking.width, m_rectworking.width));
       g.drawarc(new pen(new solidbrush(externalroundcolor), 1), r1, fltstartangle, meterdegrees);
       //内圆
       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);
       g.drawarc(new pen(new solidbrush(insideroundcolor), 1), r2, fltstartangle, meterdegrees);
       //边界线
       if (meterdegrees != 360)
       {
         float fltangle = fltstartangle - 180;
         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))));
         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)))));
         float flty1 = (float)(m_rectworking.top + m_rectworking.width / 2 - (m_rectworking.width / 8 * math.sin(math.pi * (fltangle / 180.00f))));
         float fltx1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - (m_rectworking.width / 8 * math.cos(math.pi * (fltangle / 180.00f)))));
         g.drawline(new pen(new solidbrush(boundarylinecolor), 1), new pointf(intx, inty), new pointf(fltx1, flty1));
         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));
       }
       //分割线
       int _splitcount = splitcount * 2;
       float fltsplitvalue = (float)meterdegrees / (float)_splitcount;
       for (int i = 0; i <= _splitcount; i++)
       {
         float fltangle = (fltstartangle + fltsplitvalue * i - 180) % 360;
         float flty1 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2) * math.sin(math.pi * (fltangle / 180.00f))));
         float fltx1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2) * math.cos(math.pi * (fltangle / 180.00f)))));
         float flty2 = 0;
         float fltx2 = 0;
         if (i % 2 == 0)
         {
           flty2 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 10) * math.sin(math.pi * (fltangle / 180.00f))));
           fltx2 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 10) * math.cos(math.pi * (fltangle / 180.00f)))));
           if (!(meterdegrees == 360 && i == _splitcount))
           {
             decimal decvalue = minvalue + (maxvalue - minvalue) / _splitcount * i;
             var txtsize = g.measurestring(decvalue.tostring("0.##"), this.font);
             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))));
             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)))));
             g.drawstring(decvalue.tostring("0.##"), font, new solidbrush(scalevaluecolor), fltfx1, fltfy1);
           }
         }
         else
         {
           flty2 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 5) * math.sin(math.pi * (fltangle / 180.00f))));
           fltx2 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 5) * math.cos(math.pi * (fltangle / 180.00f)))));
         }
         g.drawline(new pen(new solidbrush(scalecolor), i % 2 == 0 ? 2 : 1), new pointf(fltx1, flty1), new pointf(fltx2, flty2));
       }
       //值文字和固定文字
       if (textlocation != metertextlocation.none)
       {
         string str = m_value.tostring("0.##");
         var txtsize = g.measurestring(str, textfont);
         float flty = m_rectworking.top + m_rectworking.width / 4 - txtsize.height / 2;
         float fltx = m_rectworking.left + m_rectworking.width / 2 - txtsize.width / 2;
         g.drawstring(str, textfont, new solidbrush(textcolor), new pointf(fltx, flty));
         if (!string.isnullorempty(fixedtext))
         {
           str = fixedtext;
           txtsize = g.measurestring(str, textfont);
           flty = m_rectworking.top + m_rectworking.width / 4 + txtsize.height / 2;
           fltx = m_rectworking.left + m_rectworking.width / 2 - txtsize.width / 2;
           g.drawstring(str, textfont, new solidbrush(textcolor), new pointf(fltx, flty));
         }
       }
       //画指针
       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));
       g.fillellipse(brushes.red, new rectangle(m_rectworking.left + m_rectworking.width / 2 - 5, m_rectworking.top + m_rectworking.width / 2 - 5, 10, 10));
       float fltvalueangle = (fltstartangle + ((float)(m_value - minvalue) / (float)(maxvalue - minvalue)) * (float)meterdegrees - 180) % 360;
       float intvaluey1 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 30) * math.sin(math.pi * (fltvalueangle / 180.00f))));
       float intvaluex1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 30) * math.cos(math.pi * (fltvalueangle / 180.00f)))));
       g.drawline(new pen(new solidbrush(pointercolor), 3), intvaluex1, intvaluey1, m_rectworking.left + m_rectworking.width / 2, m_rectworking.top + m_rectworking.width / 2);
     }

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

 /// <summary>
   /// enum metertextlocation
   /// </summary>
   public enum metertextlocation
   {
     /// <summary>
     /// the none
     /// </summary>
     none,
     /// <summary>
     /// the top
     /// </summary>
     top,
     /// <summary>
     /// the bottom
     /// </summary>
     bottom
   }

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

// ***********************************************************************
// assembly     : hzh_controls
// created     : 2019-09-03
//
// ***********************************************************************
// <copyright file="ucmeter.cs">
//   copyright by huang zhenghui(黄正辉) all, qq group:568015492 qq:623128629 email:623128629@qq.com
// </copyright>
//
// blog: https://www.cnblogs.com/bfyx
// github:https://github.com/kwwwvagaa/netwinformcontrol
// gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
//
// if you use this code, please keep this note.
// ***********************************************************************
using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.windows.forms;
using system.drawing;
using system.drawing.drawing2d;
using system.componentmodel;
namespace hzh_controls.controls
{
  /// <summary>
  /// class ucmeter.
  /// implements the <see cref="system.windows.forms.usercontrol" />
  /// </summary>
  /// <seealso cref="system.windows.forms.usercontrol" />
  public class ucmeter : usercontrol
  {
    private int splitcount = 10;
    /// <summary>
    /// gets or sets the split count.
    /// </summary>
    /// <value>the split count.</value>
    [description("分隔刻度数量,>1"), category("自定义")]
    public int splitcount
    {
      get { return splitcount; }
      set
      {
        if (value < 1)
          return;
        splitcount = value;
        refresh();
      }
    }
    private int meterdegrees = 150;
    /// <summary>
    /// gets or sets the meter degrees.
    /// </summary>
    /// <value>the meter degrees.</value>
    [description("表盘跨度角度,0-360"), category("自定义")]
    public int meterdegrees
    {
      get { return meterdegrees; }
      set
      {
        if (value > 360 || value <= 0)
          return;
        meterdegrees = value;
        refresh();
      }
    }
    private decimal minvalue = 0;
    /// <summary>
    /// gets or sets the minimum value.
    /// </summary>
    /// <value>the minimum value.</value>
    [description("最小值,<maxvalue"), category("自定义")]
    public decimal minvalue
    {
      get { return minvalue; }
      set
      {
        if (value >= maxvalue)
          return;
        minvalue = value;
        refresh();
      }
    }
    private decimal maxvalue = 100;
    /// <summary>
    /// gets or sets the maximum value.
    /// </summary>
    /// <value>the maximum value.</value>
    [description("最大值,>minvalue"), category("自定义")]
    public decimal maxvalue
    {
      get { return maxvalue; }
      set
      {
        if (value <= minvalue)
          return;
        maxvalue = value;
        refresh();
      }
    }
    /// <summary>
    /// 获取或设置控件显示的文字的字体。
    /// </summary>
    /// <value>the font.</value>
    /// <permissionset>
    ///  <ipermission class="system.security.permissions.environmentpermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" />
    ///  <ipermission class="system.security.permissions.fileiopermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" />
    ///  <ipermission class="system.security.permissions.securitypermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" flags="unmanagedcode, controlevidence" />
    ///  <ipermission class="system.diagnostics.performancecounterpermission, system, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" />
    /// </permissionset>
    [description("刻度字体"), category("自定义")]
    public override font font
    {
      get
      {
        return base.font;
      }
      set
      {
        base.font = value;
        refresh();
      }
    }
    private decimal m_value = 0;
    /// <summary>
    /// gets or sets the value.
    /// </summary>
    /// <value>the value.</value>
    [description("值,>=minvalue并且<=maxvalue"), category("自定义")]
    public decimal value
    {
      get { return m_value; }
      set
      {
        if (value < minvalue || value > maxvalue)
          return;
        m_value = value;
        refresh();
      }
    }
    private metertextlocation textlocation = metertextlocation.none;
    /// <summary>
    /// gets or sets the text location.
    /// </summary>
    /// <value>the text location.</value>
    [description("值和固定文字显示位置"), category("自定义")]
    public metertextlocation textlocation
    {
      get { return textlocation; }
      set
      {
        textlocation = value;
        refresh();
      }
    }
    private string fixedtext;
    /// <summary>
    /// gets or sets the fixed text.
    /// </summary>
    /// <value>the fixed text.</value>
    [description("固定文字"), category("自定义")]
    public string fixedtext
    {
      get { return fixedtext; }
      set
      {
        fixedtext = value;
        refresh();
      }
    }
    private font textfont = defaultfont;
    /// <summary>
    /// gets or sets the text font.
    /// </summary>
    /// <value>the text font.</value>
    [description("值和固定文字字体"), category("自定义")]
    public font textfont
    {
      get { return textfont; }
      set
      {
        textfont = value;
        refresh();
      }
    }
    private color externalroundcolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the external round.
    /// </summary>
    /// <value>the color of the external round.</value>
    [description("外圆颜色"), category("自定义")]
    public color externalroundcolor
    {
      get { return externalroundcolor; }
      set
      {
        externalroundcolor = value;
        refresh();
      }
    }
    private color insideroundcolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the inside round.
    /// </summary>
    /// <value>the color of the inside round.</value>
    [description("内圆颜色"), category("自定义")]
    public color insideroundcolor
    {
      get { return insideroundcolor; }
      set
      {
        insideroundcolor = value;
        refresh();
      }
    }
    private color boundarylinecolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the boundary line.
    /// </summary>
    /// <value>the color of the boundary line.</value>
    [description("边界线颜色"), category("自定义")]
    public color boundarylinecolor
    {
      get { return boundarylinecolor; }
      set
      {
        boundarylinecolor = value;
        refresh();
      }
    }
    private color scalecolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the scale.
    /// </summary>
    /// <value>the color of the scale.</value>
    [description("刻度颜色"), category("自定义")]
    public color scalecolor
    {
      get { return scalecolor; }
      set
      {
        scalecolor = value;
        refresh();
      }
    }
    private color scalevaluecolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the scale value.
    /// </summary>
    /// <value>the color of the scale value.</value>
    [description("刻度值文字颜色"), category("自定义")]
    public color scalevaluecolor
    {
      get { return scalevaluecolor; }
      set
      {
        scalevaluecolor = value;
        refresh();
      }
    }
    private color pointercolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the pointer.
    /// </summary>
    /// <value>the color of the pointer.</value>
    [description("指针颜色"), category("自定义")]
    public color pointercolor
    {
      get { return pointercolor; }
      set
      {
        pointercolor = value;
        refresh();
      }
    }
    private color textcolor = color.fromargb(255, 77, 59);
    /// <summary>
    /// gets or sets the color of the text.
    /// </summary>
    /// <value>the color of the text.</value>
    [description("值和固定文字颜色"), category("自定义")]
    public color textcolor
    {
      get { return textcolor; }
      set
      {
        textcolor = value;
        refresh();
      }
    }
    rectangle m_rectworking;
    public ucmeter()
    {
      this.setstyle(controlstyles.allpaintinginwmpaint, true);
      this.setstyle(controlstyles.doublebuffer, true);
      this.setstyle(controlstyles.resizeredraw, true);
      this.setstyle(controlstyles.selectable, true);
      this.setstyle(controlstyles.supportstransparentbackcolor, true);
      this.setstyle(controlstyles.userpaint, true);
      this.sizechanged += ucmeter1_sizechanged;
      this.autoscalemode = system.windows.forms.autoscalemode.none;
      this.size = new size(350, 200);
    }
    void ucmeter1_sizechanged(object sender, eventargs e)
    {
      m_rectworking = new rectangle(10, 10, this.width - 20, this.height - 20);
    }
    protected override void onpaint(painteventargs e)
    {
      base.onpaint(e);
      var g = e.graphics;
      g.setgdihigh();
      //外圆
      float fltstartangle = -90 - (meterdegrees) / 2 + 360;
      var r1 = new rectangle(m_rectworking.location, new size(m_rectworking.width, m_rectworking.width));
      g.drawarc(new pen(new solidbrush(externalroundcolor), 1), r1, fltstartangle, meterdegrees);
      //内圆
      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);
      g.drawarc(new pen(new solidbrush(insideroundcolor), 1), r2, fltstartangle, meterdegrees);
      //边界线
      if (meterdegrees != 360)
      {
        float fltangle = fltstartangle - 180;
        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))));
        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)))));
        float flty1 = (float)(m_rectworking.top + m_rectworking.width / 2 - (m_rectworking.width / 8 * math.sin(math.pi * (fltangle / 180.00f))));
        float fltx1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - (m_rectworking.width / 8 * math.cos(math.pi * (fltangle / 180.00f)))));
        g.drawline(new pen(new solidbrush(boundarylinecolor), 1), new pointf(intx, inty), new pointf(fltx1, flty1));
        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));
      }
      //分割线
      int _splitcount = splitcount * 2;
      float fltsplitvalue = (float)meterdegrees / (float)_splitcount;
      for (int i = 0; i <= _splitcount; i++)
      {
        float fltangle = (fltstartangle + fltsplitvalue * i - 180) % 360;
        float flty1 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2) * math.sin(math.pi * (fltangle / 180.00f))));
        float fltx1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2) * math.cos(math.pi * (fltangle / 180.00f)))));
        float flty2 = 0;
        float fltx2 = 0;
        if (i % 2 == 0)
        {
          flty2 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 10) * math.sin(math.pi * (fltangle / 180.00f))));
          fltx2 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 10) * math.cos(math.pi * (fltangle / 180.00f)))));
          if (!(meterdegrees == 360 && i == _splitcount))
          {
            decimal decvalue = minvalue + (maxvalue - minvalue) / _splitcount * i;
            var txtsize = g.measurestring(decvalue.tostring("0.##"), this.font);
            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))));
            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)))));
            g.drawstring(decvalue.tostring("0.##"), font, new solidbrush(scalevaluecolor), fltfx1, fltfy1);
          }
        }
        else
        {
          flty2 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 5) * math.sin(math.pi * (fltangle / 180.00f))));
          fltx2 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 5) * math.cos(math.pi * (fltangle / 180.00f)))));
        }
        g.drawline(new pen(new solidbrush(scalecolor), i % 2 == 0 ? 2 : 1), new pointf(fltx1, flty1), new pointf(fltx2, flty2));
      }
      //值文字和固定文字
      if (textlocation != metertextlocation.none)
      {
        string str = m_value.tostring("0.##");
        var txtsize = g.measurestring(str, textfont);
        float flty = m_rectworking.top + m_rectworking.width / 4 - txtsize.height / 2;
        float fltx = m_rectworking.left + m_rectworking.width / 2 - txtsize.width / 2;
        g.drawstring(str, textfont, new solidbrush(textcolor), new pointf(fltx, flty));
        if (!string.isnullorempty(fixedtext))
        {
          str = fixedtext;
          txtsize = g.measurestring(str, textfont);
          flty = m_rectworking.top + m_rectworking.width / 4 + txtsize.height / 2;
          fltx = m_rectworking.left + m_rectworking.width / 2 - txtsize.width / 2;
          g.drawstring(str, textfont, new solidbrush(textcolor), new pointf(fltx, flty));
        }
      }
      //画指针
      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));
      g.fillellipse(brushes.red, new rectangle(m_rectworking.left + m_rectworking.width / 2 - 5, m_rectworking.top + m_rectworking.width / 2 - 5, 10, 10));
      float fltvalueangle = (fltstartangle + ((float)(m_value - minvalue) / (float)(maxvalue - minvalue)) * (float)meterdegrees - 180) % 360;
      float intvaluey1 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 30) * math.sin(math.pi * (fltvalueangle / 180.00f))));
      float intvaluex1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 30) * math.cos(math.pi * (fltvalueangle / 180.00f)))));
      g.drawline(new pen(new solidbrush(pointercolor), 3), intvaluex1, intvaluey1, m_rectworking.left + m_rectworking.width / 2, m_rectworking.top + m_rectworking.width / 2);
    }
  }
  /// <summary>
  /// enum metertextlocation
  /// </summary>
  public enum metertextlocation
  {
    /// <summary>
    /// the none
    /// </summary>
    none,
    /// <summary>
    /// the top
    /// </summary>
    top,
    /// <summary>
    /// the bottom
    /// </summary>
    bottom
  }
}

最后的话

如果你喜欢的话,请到 点个星星吧

总结

以上所述是小编给大家介绍的c# winform自定义控件-仪表盘功能,希望对大家有所帮助