首先来个金属仪表盘图

金属仪表盘、车载仪表盘 源代码下载 


纯代码实现GDI绘制仪表盘,效果在代码下面。



public partial class HalfDashboardUc : UserControl
{
/// <summary>
/// 仪表盘背景图片
/// </summary>
private Image dashboardImage; /// <summary>
/// 定义该仪表盘画布的最大值为371
/// </summary>
private int maxSize = ; /// <summary>
/// 仪表盘画布的放大倍数,默认1
/// </summary>
private float multiple = ; /// <summary>
/// 定义该仪表盘的直径大小
/// </summary>
private float diameter; /// <summary>
/// 每个间隔值
/// </summary>
private int intervalValue; /// <summary>
/// 仪表盘显示的最小值,默认为0
/// </summary>
private float minValue = ; /// <summary>
/// 仪表盘显示的最小值
/// </summary>
[Category("wyl")]
[Description("仪表盘显示的最小值")]
public float MinValue
{
get
{
return minValue;
}
set
{
if (value >= MaxValue)
{
MessageBox.Show("最小值不能超过最大值!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
minValue = ;
}
else
{
minValue = value;
//drawBackImage();
}
} } /// <summary>
/// 仪表盘上显示的最大值,默认123。
/// </summary>
private float maxValue = ; /// <summary>
/// 仪表盘上显示的最大值
/// </summary>
[Category("wyl")]
[Description("仪表盘上显示的最大值")]
public float MaxValue
{
get
{
return maxValue;
}
set
{
if (value <= MinValue)
{
MessageBox.Show("最大值不能低于最小值!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
maxValue = ;
}
else
{
maxValue = value;
//drawBackImage();
}
}
} // <summary>
/// 仪表盘变换的值,默认为0;
/// </summary>
private float changeValue = ; /// <summary>
/// 仪表盘变换的值
/// </summary>
public float ChangeValue
{
get
{
return changeValue;
}
set
{
changeValue = value;
}
} /// <summary>
/// 指针颜色
/// </summary>
private Color pinColor = Color.FromArgb(, , ); public Color PinColor
{
get
{
return pinColor;
}
set
{
pinColor = value;
}
} public HalfDashboardUc()
{
InitializeComponent();
//双缓存防止屏幕抖动
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.UpdateStyles();
//设置背景颜色为透明
this.BackColor = Color.Transparent;
} //private int uintfontsize = 40;
/// <summary>
/// 初始化仪表盘画布
/// </summary>
private void InitialCanvas()
{
//对比控件的长高,以最小值为仪表盘的半径
if (this.Width > * this.Height)
{
diameter = * this.Height - ;
}
else
{
diameter = this.Width - ;
}
multiple = (float)diameter / maxSize;//计算仪表盘放大倍数
//如果半径大于仪表盘的最大值,则设定放大倍数为默认值
if (multiple > )
{
multiple = ;
diameter = maxSize;
}
intervalValue = (int)((MaxValue - minValue) / );//计算每个间隔之间的值
} /// <summary>
/// 画底图
/// </summary>
private void drawBackImage()
{ Bitmap bit = new Bitmap(this.Width, this.Height);
Graphics gp = Graphics.FromImage(bit);
gp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
float radius = diameter / ;//半径
float cerX = this.Width / ;
float cerY = this.Height / + radius / - * multiple;
//float cerY = this.Height - 20 ;
gp.TranslateTransform(cerX, cerY);//以中心点为画布的起始点
//gp.DrawPie(new Pen(new SolidBrush(Color.FromArgb(19,20,25)),3), -radius, -radius, diameter, diameter, 175, 190);
gp.DrawArc(new Pen(new SolidBrush(Color.FromArgb(, , )), ), -radius, -radius, diameter, diameter, , );
float x1 = (float)((radius) * Math.Cos( * Math.PI / ));
float y1 = (float)((radius) * Math.Sin( * Math.PI / ));
float x2 = (float)((radius) * Math.Cos( * Math.PI / ));
float y2 = (float)((radius) * Math.Sin( * Math.PI / ));
gp.DrawLine(new Pen(new SolidBrush(Color.FromArgb(, , )), ), x1, y1, x2, y2); //gp.DrawEllipse(new Pen(Brushes.Red), -5, -5, 10, 10);
float startRad = ;//起始角度
float sweepShot = ;//旋转角度
//gp.DrawLine(new Pen(Brushes.Red), -radius, 0, -(radius - 10), 0);
for (int i = ; i <= ; i++)
{
double rad = (sweepShot + startRad) * Math.PI / ;
if (i % == )
{
float px1 = (float)((radius - ) * Math.Cos(rad));
float py1 = (float)((radius - ) * Math.Sin(rad)); float px2 = (float)((radius - ) * Math.Cos(rad));
float py2 = (float)((radius - ) * Math.Sin(rad));
gp.DrawLine(new Pen(new SolidBrush(Color.FromArgb(, , )), ), px1, py1, px2, py2); }
else
{ float px1 = (float)((radius - ) * Math.Cos(rad));
float py1 = (float)((radius - ) * Math.Sin(rad)); float px2 = (float)((radius - ) * Math.Cos(rad));
float py2 = (float)((radius - ) * Math.Sin(rad));
gp.DrawLine(new Pen(new SolidBrush(Color.FromArgb(, , )), ), px1, py1, px2, py2);
}
sweepShot += ;
}
//刻度字体
Font scaleFont = new Font("宋体", , FontStyle.Bold);
startRad = ;//起始角度
sweepShot = ;//旋转角度
Color c1 = Color.FromArgb(, , );
for (int i = ; i < ; i++)
{
int tempValue = i * intervalValue;
SizeF tempSf = gp.MeasureString(tempValue.ToString(), scaleFont);
//计算角度值
double rad = (sweepShot + startRad) * Math.PI / ;
float px = (float)((radius - ) * Math.Cos(rad));
float py = (float)((radius - ) * Math.Sin(rad));
if (sweepShot == )
{
gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Wheat, px - tempSf.Width / , py);
}
else if (sweepShot == )
{
gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width + * multiple, py - tempSf.Height / + * multiple);
}
else if (sweepShot == )
{
gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width, py - tempSf.Height / + * multiple);
}
else if (sweepShot == )
{
gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width, py - tempSf.Height / ); }
//else if (sweepShot == 120)
//{
// gp.DrawString(tempValue.ToString(), scaleFont, new SolidBrush(c1), px - tempSf.Width, py - tempSf.Height / 2);
//}
sweepShot += ;
}
startRad = ;//起始角度
sweepShot = ;//旋转角度
for (int i = ; i < ; i++)
{
int tempValue = -i * intervalValue;
SizeF tempSf = gp.MeasureString(tempValue.ToString(), scaleFont);
//计算角度值
double rad = (sweepShot + startRad) * Math.PI / ;
float px = (float)((radius - * multiple) * Math.Cos(rad));
float py = (float)((radius - * multiple) * Math.Sin(rad));
if (sweepShot == -)
{
gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Red, px, py + tempSf.Height / );
}
else if (sweepShot == -)
{
gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Red, px + tempSf.Width / - * multiple, py + tempSf.Height / - * multiple);
}
else if (sweepShot == -)
{
gp.DrawString(tempValue.ToString(), scaleFont, Brushes.Red, px + tempSf.Width/ , py - tempSf.Height / ); } sweepShot -= ;
} gp.Dispose();
this.BackgroundImage = bit;
} /// <summary>
/// 画图
/// </summary>
/// <param name="g"></param>
private void DrawPin(Graphics g)
{
Bitmap bit = new Bitmap(this.Width, this.Height);
Graphics gp = Graphics.FromImage(bit);
gp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
float radius = diameter / ;//半径
float startRad = ;//起始角度
float sweepShot = (float)(ChangeValue / MaxValue * );//旋转角度
float cerX = this.Width / ;
float cerY = this.Height / + radius / - * multiple;
gp.TranslateTransform(cerX, cerY);//以中心点为画布的起始点
//gp.DrawEllipse(new Pen(PinColor, 1), -5, -5, 10, 10);//画中心圆圈
double rad = (sweepShot + startRad) * Math.PI / ;//计算角度
float px = (float)((radius - ) * Math.Cos(rad));
float py = (float)((radius - ) * Math.Sin(rad));
PointF[] pf = new PointF[] { new PointF(, -radius + ), new PointF(-, ), new PointF(, ) };
gp.RotateTransform(sweepShot);
//PointF[] pf = new PointF[] { new PointF(px, py), new PointF(-4, 0), new PointF(4, 0) };
gp.FillPolygon(new SolidBrush(PinColor), pf); //gp.DrawLine(new Pen(new SolidBrush(PinColor), 3f), 0, 0, px, py); g.DrawImage(bit, , );
gp.Dispose();
} private void HalfDashboardUc_Load(object sender, EventArgs e)
{
InitialCanvas();
drawBackImage();
} private void HalfDashboardUc_Paint(object sender, PaintEventArgs e)
{
DrawPin(e.Graphics);
} private void HalfDashboardUc_Resize(object sender, EventArgs e)
{
InitialCanvas();
drawBackImage();
}
}

效果实现如下:

金属仪表盘下载地址 https://pan.baidu.com/s/1xANmSkQYnLGzUJ_X8Dbg0w   提取码:fi96

C# GDI绘制仪表盘(纯代码实现)的更多相关文章

  1. GDI绘制时钟效果,与系统时间保持同步,基于Winform

    2018年工作之余,想起来捡起GDI方面的技术,特意在RichCodeBox项目中做了两个示例程序,其中一个就是时钟效果,纯C#开发.这个CSharpQuartz是今天上午抽出一些时间,编写的,算是偷 ...

  2. 通过GDI+绘制 验证码

    只为了记录下自己的学习历程,方便日后查看 现在开始言归正传,以下为其完整代码附上 using System; using System.Collections.Generic; using Syste ...

  3. C#利用GDI+绘制旋转文字等效果

    C#中利用GDI+绘制旋转文本的文字,网上有很多资料,基本都使用矩阵旋转的方式实现.但基本都只提及按点旋转,若要实现在矩形范围内旋转文本,资料较少.经过琢磨,可以将矩形内旋转转化为按点旋转,不过需要经 ...

  4. C# 使用GDI+绘制漂亮的MenuStrip和ContextMenuStrip皮肤

    通过上面的效果截图可以看到,重绘后的MenuStrip和ContextMenuStrip可以添加自己的LOGO信息,实现了类似OFFICE2007的菜单显示效果. .NET对菜单控件的绘制提供了一个抽 ...

  5. MFC 用gdi绘制填充多边形区域

    MFC 用gdi绘制填充多边形区域 这里的代码是实现一个三角形的绘制,并用刷子填充颜色 在OnPaint()函数里面 运用的是给定的三角形的三个点,很多个点可以绘制多边形 CBrush br(RGB( ...

  6. 『备注』GDI+ 绘制文本有锯齿,透明背景文本绘制

    背景: GDI+ 绘制文本 时,如果 背景是透明的 —— 则会出现 锯齿. //其实,我不用这三个 属性 好多年了 //而且,这三个属性 在关键时刻还有可能 帮倒忙 //关键是:这三个属性,鸟用都没有 ...

  7. C#GDI+ 绘制线段(实线或虚线)、矩形、字符串、圆、椭圆

    C#GDI+ 绘制线段(实线或虚线).矩形.字符串.圆.椭圆 绘制基本线条和图形 比较简单,直接看代码. Graphics graphics = e.Graphics; //绘制实线 )) { pen ...

  8. Qt自定义控件之仪表盘2--QPaint绘制仪表盘

    0.前言 前面一篇文章写道了仪表盘的特点,实现了一个贴图的仪表盘,属于低配版本的仪表盘.    主要是有任何改动时候就需要重新设计图片,不能适配不同控件大小,即使让它自由拉伸,但仪表盘放大缩小时候显示 ...

  9. Qt5绘制仪表盘dashboard

    说明 本文演示Qt版本: Qt5.14. 本文将使用QPainter一步一步绘制仪表盘:刻度.指针.刻度值 注意: 绘制顺序,如果先绘制,则后来绘制的将会覆盖住先前绘制的. 如果需要绘制半透明, 请设 ...

随机推荐

  1. 动态调用WebService方法

      好像很多人做WebService的时候都是直接添加引用的方式,然后调用服务端的方法.这样就个问题,就是每次我服务端添加了方法或者修改了方法后都要更新Web引用,这样比较麻烦.下面给一个不用添加引用 ...

  2. Git Submodule 使用简介

    参考http://www.diguage.com/archives/146.html 一.添加子模块 从新建一个项目,或者从远处服务器上克隆一个项目,作为“顶级项目”.这里,从 Github 上新建一 ...

  3. js 获取高度

    网页可见区域宽 :document.body.clientWidth; 网页可见区域高:document.body.clientHeight;   网页可见区域高:document.body.offs ...

  4. springmvc使用list集合实现商品列表的批量修改

    1将表单的数据绑定到List 1.1 需求 实现商品数据的批量修改. 1.2 需求分析 要想实现商品数据的批量修改,需要在商品列表中可以对商品信息进行修改,饼干且可以批量提交修改后的商品数据. 1.3 ...

  5. MacOs安装mysql与修改root密码

    1.下载安装包 http://www.mysql.com/downloads/ 找到如下内容下载 mysql-5.7.21-1-macos10.13-x86_64.dmg下载地址是 https://c ...

  6. Linux wget命令

    一.简介 wget是一个Linux系统中的下载文件的工具,它用在命令行下.对于Linux用户是必不可少的工具,我们经常要下载一些软件或从远程服务器恢复备份到本地服务器.wget支持HTTP,HTTPS ...

  7. 构造函数constructor 与析构函数destructor(一)

    构造函数定义:构造函数c++中在创建对象时自动调用,用来初始化对象的特殊函数. (1)构造函数的名字必须与类的名字相同,不能有返回值,哪怕是void 也不行. (2)通常情况下构造函数应声明为公有函数 ...

  8. const与预处理宏#define的区别

    在c语言程序设计时,预处理器可以不受限制地建立宏并用它来替代值.因为预处理器只做一些文本替换,宏没有类型检测概念,也没有类型检测功能.所以预处理器的值替换会出现一些小的问题,出现的这些问题,在c++中 ...

  9. delphi XE7 数组操作中缺少的find(POS)功能

    delphi xe7 中对数组操作做了很多扩充,比如加入了类似字符串处理的功能. 例如,数组相加 var A: array of integer; B: TBytes = [1,2,3,4]; //I ...

  10. 2018.09.25 bzoj3572: [Hnoi2014]世界树(虚树+树形dp)

    传送门 虚树入门题? 好难啊. 在学习别人的写法之后终于过了. 这道题dp方程很好想. 主要是不好写. 简要说说思路吧. 显然最优值只能够从子树和父亲转移过来. 于是我们先dfs一遍用儿子更新父亲,然 ...