c#绘制仪表

清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace GMapTest
{
    public partial class FrmMeter : Form
    {
        public FrmMeter()
        {
            InitializeComponent();
            MaxValue = 270;
            ChangeValue = 69;
            DrawBackImg();
            //this.BackgroundImage = GMapTest.Properties.Resources.bdi;
        }

        //为了方式绘制指针时产生的闪烁,PictureBox添加该事件方法

        private void pic_Paint(object sender, PaintEventArgs e)
        {
            //DrawForeImg(e.Graphics);
        }


        private double _maxValue;
        public double MaxValue {
            get { return _maxValue; }
            set { _maxValue = value; }
        }

        private double _changeValue;
        public double ChangeValue
        {
            get { return _changeValue; }
            set
            {
                if (value <= _maxValue)
                    _changeValue = value;
                else
                {
                    //完成自适应性
                    MaxValue = value;
                    _changeValue = value;
                }
                //通过该方法,可以使指针自动绘制(其实就是强制重绘)

                //pic.Invalidate();
            }
        }

        //指针的具体画法 

        private void DrawForeImg(Graphics gp)
        {
            Bitmap bit = new Bitmap(this.Width, this.Height);
            Graphics g = Graphics.FromImage(bit);
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            //画针
            DrawPin(g);
            DrawString(g);

            //注意此处的绘制方式,这样可以有效减少界面的闪烁问题。
            gp.DrawImage(bit, new Point(0, 0));
            g.Dispose();

        }
        private readonly int _diameter = 300;

        private Color _pinColor = Color.CornflowerBlue;

        private string _unitStr = "AUC";

        private Color _frameColor = Color.SkyBlue;

        private StringFormat strFormat = StringFormat.GenericTypographic;

        private double _PinLen = 130;

        private double NxPinLen =10;

        //画针
        private void DrawPin(Graphics g)
        {
            int cer = _diameter / 2;
            float start = 135;
            float sweepShot = (float)(_changeValue / _maxValue * 270);

            Pen linePen = new Pen(_pinColor, 1);
            Pen NxPen = new Pen(_pinColor, 2);
            Pen xPen = new Pen(_pinColor, 5);
            double rad = (sweepShot + start) * Math.PI / 180;
            float radius = _diameter / 2 - 5;
            int dx = (int)(cer + (_PinLen) * Math.Cos(rad));
            int dy = (int)(cer + (_PinLen) * Math.Sin(rad));

            int px = (int)(cer + (_PinLen * 0.4) * Math.Cos(rad));
            int py = (int)(cer + (_PinLen * 0.4) * Math.Sin(rad));

            int nx = (int)(cer - (NxPinLen) * Math.Sin(rad));
            int ny = (int)(cer - (NxPinLen) * Math.Cos(rad));
            g.DrawLine(linePen, new Point(cer, cer), new Point(dx, dy));
            g.DrawLine(NxPen, new Point(cer, cer), new Point(px, py));
            g.DrawLine(xPen, new Point(cer, cer), new Point(ny, nx));
        }

        //绘制在仪表下面的值

        private void DrawString(Graphics g)
        {
            int cer = _diameter / 2;
            string str = _changeValue.ToString("F2");
            g.DrawString(str, new Font("宋体", 9), new SolidBrush(_pinColor), new PointF(cer, (float)(cer + cer * 0.4)), strFormat);
        }

        // 绘制背景 用来总体控制背景的绘制
        private void DrawBackImg()
        {
            Bitmap bit = new Bitmap(this.Width, this.Height);
            Graphics gp = Graphics.FromImage(bit);
            gp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            #region 在这里可以扩展需要绘制的背景项目
           
            //外框
            drawFrame(gp);
            // 画刻度
            DrawRuling(gp);
            //画点
            drawPoint(gp);

            //绘制单位
            DrawUnitStr(gp);

            #endregion

            //当绘制完成后,直接直接设置为背景
            DrawForeImg(gp);
            this.panel1.BackgroundImage = bit;
           
        }

        //绘制单位
        private void DrawUnitStr(Graphics gp)
        {
            int cer = _diameter / 2;
            gp.DrawString(_unitStr, new Font("宋体", 10), new SolidBrush(_frameColor), new PointF(cer, (float)(cer - cer * 0.3)), strFormat);

        }

        /// <summary>
        /// 画外框
        /// </summary>
        /// <param name="gp"></param>
        private void drawFrame(Graphics gp)
        {
            Pen pen = new Pen(_frameColor, 2);
            Rectangle rec = new Rectangle(5, 5, _diameter - 10, _diameter - 10);
            Rectangle reci = new Rectangle(7, 7, _diameter - 14, _diameter - 14);
            gp.FillEllipse(Brushes.Black, rec);
            gp.DrawEllipse(pen, reci);
        }
        // 画刻度  此次较为复杂,主要是在绘制刻度值时需要处理
        private void DrawRuling(Graphics gp)
        {
            //刻度
            int cerX = _diameter / 2;
            int cerY = _diameter / 2;

            //这里需要注意,因外在上面的图中标识了rad=0的位置,而我们的仪表时270度的,0点在135度处,

            //为了符合该效果所以起始位置设为135度。
            float start = 135;
            float sweepShot = 0;
            int dx = 0;
            int dy = 0;
            int soildLenght = 8;
            Pen linePen = new Pen(Color.White, 1);
            float span = (float)(_maxValue / 30);
            float sp = 0;
            //用于右边数字右对齐
            StringFormat stf = new StringFormat();
            stf.Alignment = StringAlignment.Far;

            StringFormat stfMid = new StringFormat();
            stfMid.Alignment = StringAlignment.Center;
            stfMid.LineAlignment = StringAlignment.Center;
            for (int i = 0; i <= 30; i++)
            {
                //注意此处,C#提供的三角函数计算中使用的弧度值,而此处获取的是角度值,需要转化

                double rad = (sweepShot + start) * Math.PI / 180;
                float radius = _diameter / 2 - 5;
                int px = (int)(cerX + (radius-20) * Math.Cos(rad));
                int py = (int)(cerY + (radius - 20) * Math.Sin(rad));
                if (sweepShot % 15 == 0)
                {
                    linePen.Width = 2;

                    //计算刻度中的粗线
                    dx = (int)(cerX + (radius - 20 - soildLenght) * Math.Cos(rad));
                    dy = (int)(cerY + (radius - 20 - soildLenght) * Math.Sin(rad));

                    //绘制刻度值,注意字串对其方式
                    string str = sp.ToString("f0");
                    if (sweepShot <= 45)
                    {
                        gp.DrawString(str, new Font("宋体", 9), new SolidBrush(_frameColor), new PointF(dx, dy - 5));
                    }
                    else if (sweepShot > 45 && sweepShot < 135)
                    {
                        gp.DrawString(str, new Font("宋体", 9), new SolidBrush(_frameColor), new PointF(dx, dy));
                    }
                    else if (sweepShot == 135)
                    {
                        gp.DrawString(str, new Font("宋体", 9), new SolidBrush(_frameColor), new PointF(dx, dy + 10), stfMid);
                    }
                    else if (sweepShot > 135 && sweepShot < 225)
                    {
                        gp.DrawString(str, new Font("宋体", 9), new SolidBrush(_frameColor), new PointF(dx, dy), stf);
                    }
                    else if (sweepShot >= 225)
                    {
                        gp.DrawString(str, new Font("宋体", 9), new SolidBrush(_frameColor), new PointF(dx, dy - 5), stf);
                    }

                }
                else
                {

                    //计算刻度中细线

                    linePen.Width = 1;
                    dx = (int)(cerX + (radius - 20 - soildLenght + 2) * Math.Cos(rad));
                    dy = (int)(cerY + (radius - 20 - soildLenght + 2) * Math.Sin(rad));
                }

                //绘制刻度线
                gp.DrawLine(linePen, new Point(px, py), new Point(dx, dy));
                sp += span;
                sweepShot += 9;
            }
        }
        //画中间的点
        private void drawPoint(Graphics gp)
        {
            Pen p = new Pen(_frameColor);
            int tmpWidth = 6;
            int px = _diameter / 2 - tmpWidth;

            gp.DrawEllipse(p, new Rectangle(px, px, 2 * tmpWidth, 2 * tmpWidth));

            //在画点时,我使用了指针的颜色,这样看起来,更真实一点
            gp.FillEllipse(new SolidBrush(_pinColor), new Rectangle(px + 2, px + 2, 2 * tmpWidth - 4, 2 * tmpWidth - 4));
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            //DrawBackImg();
        }      
    }

 


}