官网

http://www.hzhcontrols.com

前提

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

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

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

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

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

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

NuGet

Install-Package HZH_Controls

目录

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

用处及效果

准备工作

依然是GDI+  不了解请先百度一下

开始

添加一个类UCBottle,继承UserControl

添加几个控制属性

 //瓶身区域
/// <summary>
/// The m working rect
/// </summary>
Rectangle m_workingRect; /// <summary>
/// The title
/// </summary>
string title = "瓶子1"; /// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>The title.</value>
[Description("标题"), Category("自定义")]
public string Title
{
get { return title; }
set
{
title = value;
ResetWorkingRect();
Refresh();
}
} /// <summary>
/// The bottle color
/// </summary>
private Color bottleColor = Color.FromArgb(, , ); /// <summary>
/// Gets or sets the color of the bottle.
/// </summary>
/// <value>The color of the bottle.</value>
[Description("瓶子颜色"), Category("自定义")]
public Color BottleColor
{
get { return bottleColor; }
set
{
bottleColor = value;
Refresh();
}
} /// <summary>
/// The bottle mouth color
/// </summary>
private Color bottleMouthColor = Color.FromArgb(, , ); /// <summary>
/// Gets or sets the color of the bottle mouth.
/// </summary>
/// <value>The color of the bottle mouth.</value>
[Description("瓶口颜色"), Category("自定义")]
public Color BottleMouthColor
{
get { return bottleMouthColor; }
set { bottleMouthColor = value; }
} /// <summary>
/// The liquid color
/// </summary>
private Color liquidColor = Color.FromArgb(, , ); /// <summary>
/// Gets or sets the color of the liquid.
/// </summary>
/// <value>The color of the liquid.</value>
[Description("液体颜色"), Category("自定义")]
public Color LiquidColor
{
get { return liquidColor; }
set
{
liquidColor = 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;
ResetWorkingRect();
Refresh();
}
} /// <summary>
/// 获取或设置控件的前景色。
/// </summary>
/// <value>The color of the fore.</value>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
[Description("文字颜色"), Category("自定义")]
public override System.Drawing.Color ForeColor
{
get
{
return base.ForeColor;
}
set
{
base.ForeColor = value;
Refresh();
}
} /// <summary>
/// The maximum value
/// </summary>
private decimal maxValue = ; /// <summary>
/// Gets or sets the maximum value.
/// </summary>
/// <value>The maximum value.</value>
[Description("最大值"), Category("自定义")]
public decimal MaxValue
{
get { return maxValue; }
set
{
if (value < m_value)
return;
maxValue = value;
Refresh();
}
} /// <summary>
/// The m value
/// </summary>
private decimal m_value = ; /// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
[Description("值"), Category("自定义")]
public decimal Value
{
get { return m_value; }
set
{
if (value <= || value > maxValue)
return;
m_value = value;
Refresh();
}
} /// <summary>
/// The m no
/// </summary>
private string m_NO;
/// <summary>
/// Gets or sets the NO.
/// </summary>
/// <value>The no.</value>
[Description("编号"), Category("自定义")]
public string NO
{
get { return m_NO; }
set
{
m_NO = value;
Refresh();
}
}

重绘

  protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var g = e.Graphics;
g.SetGDIHigh();
//写文字
var size = g.MeasureString(title, Font);
g.DrawString(title, Font, new SolidBrush(ForeColor), new PointF((this.Width - size.Width) / , )); //画空瓶子
GraphicsPath pathPS = new GraphicsPath();
Point[] psPS = new Point[]
{
new Point(m_workingRect.Left, m_workingRect.Top),
new Point(m_workingRect.Right - , m_workingRect.Top),
new Point(m_workingRect.Right - , m_workingRect.Bottom - ),
new Point(m_workingRect.Right - - m_workingRect.Width / , m_workingRect.Bottom),
new Point(m_workingRect.Left + m_workingRect.Width / , m_workingRect.Bottom),
new Point(m_workingRect.Left, m_workingRect.Bottom - ),
};
pathPS.AddLines(psPS);
pathPS.CloseAllFigures();
g.FillPath(new SolidBrush(bottleColor), pathPS);
//画液体
decimal decYTHeight = (m_value / maxValue) * m_workingRect.Height;
GraphicsPath pathYT = new GraphicsPath();
Rectangle rectYT = Rectangle.Empty;
if (decYTHeight < )
{
PointF[] psYT = new PointF[]
{
new PointF((float)(m_workingRect.Left+(-decYTHeight))+,(float)(m_workingRect.Bottom-decYTHeight)),
new PointF((float)(m_workingRect.Right-(-decYTHeight))-,(float)(m_workingRect.Bottom-decYTHeight)),
new PointF(m_workingRect.Right--m_workingRect.Width/, m_workingRect.Bottom),
new PointF(m_workingRect.Left+m_workingRect.Width/, m_workingRect.Bottom),
};
pathYT.AddLines(psYT);
pathYT.CloseAllFigures();
rectYT = new Rectangle((m_workingRect.Left + ( - (int)decYTHeight)) + , m_workingRect.Bottom - (int)decYTHeight - , m_workingRect.Width - (int)( - decYTHeight) * - , );
}
else
{
PointF[] psYT = new PointF[]
{
new PointF(m_workingRect.Left,(float)(m_workingRect.Bottom-decYTHeight)),
new PointF(m_workingRect.Right-,(float)(m_workingRect.Bottom-decYTHeight)),
new PointF(m_workingRect.Right-,m_workingRect.Bottom-),
new PointF(m_workingRect.Right--m_workingRect.Width/, m_workingRect.Bottom),
new PointF(m_workingRect.Left+m_workingRect.Width/, m_workingRect.Bottom),
new PointF(m_workingRect.Left,m_workingRect.Bottom-),
};
pathYT.AddLines(psYT);
pathYT.CloseAllFigures();
rectYT = new Rectangle(m_workingRect.Left, m_workingRect.Bottom - (int)decYTHeight - , m_workingRect.Width, );
} g.FillPath(new SolidBrush(liquidColor), pathYT);
g.FillPath(new SolidBrush(Color.FromArgb(, bottleMouthColor)), pathYT);
//画液体面
g.FillEllipse(new SolidBrush(liquidColor), rectYT);
g.FillEllipse(new SolidBrush(Color.FromArgb(, Color.White)), rectYT); //画高亮
int intCount = m_workingRect.Width / / ;
int intSplit = ( - ) / intCount;
for (int i = ; i < intCount; i++)
{
int _penWidth = m_workingRect.Width / - * i;
if (_penWidth <= )
_penWidth = ;
g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(, Color.White)), _penWidth), new Point(m_workingRect.Width / , m_workingRect.Top), new Point(m_workingRect.Width / , m_workingRect.Bottom - ));
if (_penWidth == )
break;
} //画瓶底
g.FillEllipse(new SolidBrush(bottleColor), new RectangleF(m_workingRect.Left, m_workingRect.Top - , m_workingRect.Width - , ));
g.FillEllipse(new SolidBrush(Color.FromArgb(, Color.White)), new RectangleF(m_workingRect.Left, m_workingRect.Top - , m_workingRect.Width - , ));
//画瓶口
g.FillRectangle(new SolidBrush(bottleMouthColor), new Rectangle(m_workingRect.Left + m_workingRect.Width / , m_workingRect.Bottom, m_workingRect.Width / , ));
//画瓶颈阴影
GraphicsPath pathPJ = new GraphicsPath();
Point[] psPJ = new Point[]
{
new Point(m_workingRect.Left, m_workingRect.Bottom-),
new Point(m_workingRect.Right-, m_workingRect.Bottom-),
new Point(m_workingRect.Right--m_workingRect.Width/, m_workingRect.Bottom),
new Point(m_workingRect.Left+m_workingRect.Width/, m_workingRect.Bottom)
};
pathPJ.AddLines(psPJ);
pathPJ.CloseAllFigures();
g.FillPath(new SolidBrush(Color.FromArgb(, bottleMouthColor)), pathPJ); //写编号
if (!string.IsNullOrEmpty(m_NO))
{
var nosize = g.MeasureString(m_NO, Font);
g.DrawString(m_NO, Font, new SolidBrush(ForeColor), new PointF((this.Width - nosize.Width) / , m_workingRect.Top + ));
}
}

代码就这么多

完整代码

 // ***********************************************************************
// Assembly : HZH_Controls
// Created : 2019-09-05
//
// ***********************************************************************
// <copyright file="UCBottle.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 UCBottle.
/// Implements the <see cref="System.Windows.Forms.UserControl" />
/// </summary>
/// <seealso cref="System.Windows.Forms.UserControl" />
public class UCBottle : UserControl
{
//瓶身区域
/// <summary>
/// The m working rect
/// </summary>
Rectangle m_workingRect; /// <summary>
/// The title
/// </summary>
string title = "瓶子1"; /// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>The title.</value>
[Description("标题"), Category("自定义")]
public string Title
{
get { return title; }
set
{
title = value;
ResetWorkingRect();
Refresh();
}
} /// <summary>
/// The bottle color
/// </summary>
private Color bottleColor = Color.FromArgb(, , ); /// <summary>
/// Gets or sets the color of the bottle.
/// </summary>
/// <value>The color of the bottle.</value>
[Description("瓶子颜色"), Category("自定义")]
public Color BottleColor
{
get { return bottleColor; }
set
{
bottleColor = value;
Refresh();
}
} /// <summary>
/// The bottle mouth color
/// </summary>
private Color bottleMouthColor = Color.FromArgb(, , ); /// <summary>
/// Gets or sets the color of the bottle mouth.
/// </summary>
/// <value>The color of the bottle mouth.</value>
[Description("瓶口颜色"), Category("自定义")]
public Color BottleMouthColor
{
get { return bottleMouthColor; }
set { bottleMouthColor = value; }
} /// <summary>
/// The liquid color
/// </summary>
private Color liquidColor = Color.FromArgb(, , ); /// <summary>
/// Gets or sets the color of the liquid.
/// </summary>
/// <value>The color of the liquid.</value>
[Description("液体颜色"), Category("自定义")]
public Color LiquidColor
{
get { return liquidColor; }
set
{
liquidColor = 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;
ResetWorkingRect();
Refresh();
}
} /// <summary>
/// 获取或设置控件的前景色。
/// </summary>
/// <value>The color of the fore.</value>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
/// </PermissionSet>
[Description("文字颜色"), Category("自定义")]
public override System.Drawing.Color ForeColor
{
get
{
return base.ForeColor;
}
set
{
base.ForeColor = value;
Refresh();
}
} /// <summary>
/// The maximum value
/// </summary>
private decimal maxValue = ; /// <summary>
/// Gets or sets the maximum value.
/// </summary>
/// <value>The maximum value.</value>
[Description("最大值"), Category("自定义")]
public decimal MaxValue
{
get { return maxValue; }
set
{
if (value < m_value)
return;
maxValue = value;
Refresh();
}
} /// <summary>
/// The m value
/// </summary>
private decimal m_value = ; /// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
[Description("值"), Category("自定义")]
public decimal Value
{
get { return m_value; }
set
{
if (value <= || value > maxValue)
return;
m_value = value;
Refresh();
}
} /// <summary>
/// The m no
/// </summary>
private string m_NO;
/// <summary>
/// Gets or sets the NO.
/// </summary>
/// <value>The no.</value>
[Description("编号"), Category("自定义")]
public string NO
{
get { return m_NO; }
set
{
m_NO = value;
Refresh();
}
} /// <summary>
/// Initializes a new instance of the <see cref="UCBottle" /> class.
/// </summary>
public UCBottle()
{
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.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.SizeChanged += UCBottle_SizeChanged;
this.Size = new Size(, );
} /// <summary>
/// Handles the SizeChanged event of the UCBottle control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
void UCBottle_SizeChanged(object sender, EventArgs e)
{
ResetWorkingRect();
} /// <summary>
/// Resets the working rect.
/// </summary>
private void ResetWorkingRect()
{
var g = this.CreateGraphics();
var size = g.MeasureString(title, Font);
m_workingRect = new Rectangle(, (int)size.Height + , this.Width, this.Height - ((int)size.Height + ) - );
} /// <summary>
/// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
/// </summary>
/// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var g = e.Graphics;
g.SetGDIHigh();
//写文字
var size = g.MeasureString(title, Font);
g.DrawString(title, Font, new SolidBrush(ForeColor), new PointF((this.Width - size.Width) / , )); //画空瓶子
GraphicsPath pathPS = new GraphicsPath();
Point[] psPS = new Point[]
{
new Point(m_workingRect.Left, m_workingRect.Top),
new Point(m_workingRect.Right - , m_workingRect.Top),
new Point(m_workingRect.Right - , m_workingRect.Bottom - ),
new Point(m_workingRect.Right - - m_workingRect.Width / , m_workingRect.Bottom),
new Point(m_workingRect.Left + m_workingRect.Width / , m_workingRect.Bottom),
new Point(m_workingRect.Left, m_workingRect.Bottom - ),
};
pathPS.AddLines(psPS);
pathPS.CloseAllFigures();
g.FillPath(new SolidBrush(bottleColor), pathPS);
//画液体
decimal decYTHeight = (m_value / maxValue) * m_workingRect.Height;
GraphicsPath pathYT = new GraphicsPath();
Rectangle rectYT = Rectangle.Empty;
if (decYTHeight < )
{
PointF[] psYT = new PointF[]
{
new PointF((float)(m_workingRect.Left+(-decYTHeight))+,(float)(m_workingRect.Bottom-decYTHeight)),
new PointF((float)(m_workingRect.Right-(-decYTHeight))-,(float)(m_workingRect.Bottom-decYTHeight)),
new PointF(m_workingRect.Right--m_workingRect.Width/, m_workingRect.Bottom),
new PointF(m_workingRect.Left+m_workingRect.Width/, m_workingRect.Bottom),
};
pathYT.AddLines(psYT);
pathYT.CloseAllFigures();
rectYT = new Rectangle((m_workingRect.Left + ( - (int)decYTHeight)) + , m_workingRect.Bottom - (int)decYTHeight - , m_workingRect.Width - (int)( - decYTHeight) * - , );
}
else
{
PointF[] psYT = new PointF[]
{
new PointF(m_workingRect.Left,(float)(m_workingRect.Bottom-decYTHeight)),
new PointF(m_workingRect.Right-,(float)(m_workingRect.Bottom-decYTHeight)),
new PointF(m_workingRect.Right-,m_workingRect.Bottom-),
new PointF(m_workingRect.Right--m_workingRect.Width/, m_workingRect.Bottom),
new PointF(m_workingRect.Left+m_workingRect.Width/, m_workingRect.Bottom),
new PointF(m_workingRect.Left,m_workingRect.Bottom-),
};
pathYT.AddLines(psYT);
pathYT.CloseAllFigures();
rectYT = new Rectangle(m_workingRect.Left, m_workingRect.Bottom - (int)decYTHeight - , m_workingRect.Width, );
} g.FillPath(new SolidBrush(liquidColor), pathYT);
g.FillPath(new SolidBrush(Color.FromArgb(, bottleMouthColor)), pathYT);
//画液体面
g.FillEllipse(new SolidBrush(liquidColor), rectYT);
g.FillEllipse(new SolidBrush(Color.FromArgb(, Color.White)), rectYT); //画高亮
int intCount = m_workingRect.Width / / ;
int intSplit = ( - ) / intCount;
for (int i = ; i < intCount; i++)
{
int _penWidth = m_workingRect.Width / - * i;
if (_penWidth <= )
_penWidth = ;
g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(, Color.White)), _penWidth), new Point(m_workingRect.Width / , m_workingRect.Top), new Point(m_workingRect.Width / , m_workingRect.Bottom - ));
if (_penWidth == )
break;
} //画瓶底
g.FillEllipse(new SolidBrush(bottleColor), new RectangleF(m_workingRect.Left, m_workingRect.Top - , m_workingRect.Width - , ));
g.FillEllipse(new SolidBrush(Color.FromArgb(, Color.White)), new RectangleF(m_workingRect.Left, m_workingRect.Top - , m_workingRect.Width - , ));
//画瓶口
g.FillRectangle(new SolidBrush(bottleMouthColor), new Rectangle(m_workingRect.Left + m_workingRect.Width / , m_workingRect.Bottom, m_workingRect.Width / , ));
//画瓶颈阴影
GraphicsPath pathPJ = new GraphicsPath();
Point[] psPJ = new Point[]
{
new Point(m_workingRect.Left, m_workingRect.Bottom-),
new Point(m_workingRect.Right-, m_workingRect.Bottom-),
new Point(m_workingRect.Right--m_workingRect.Width/, m_workingRect.Bottom),
new Point(m_workingRect.Left+m_workingRect.Width/, m_workingRect.Bottom)
};
pathPJ.AddLines(psPJ);
pathPJ.CloseAllFigures();
g.FillPath(new SolidBrush(Color.FromArgb(, bottleMouthColor)), pathPJ); //写编号
if (!string.IsNullOrEmpty(m_NO))
{
var nosize = g.MeasureString(m_NO, Font);
g.DrawString(m_NO, Font, new SolidBrush(ForeColor), new PointF((this.Width - nosize.Width) / , m_workingRect.Top + ));
}
}
}
}

最后的话

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

最新文章

  1. WindowsCE project missing Microsoft.CompactFramework.CSharp.targets in Visual Studio 2008
  2. C#中常用的几种读取XML文件的方法
  3. Redis学习笔记~关于空间换时间的查询案例
  4. 用GruntJS合并、压缩CSS资源文件
  5. Scala 并行和并发编程-Futures 和 Promises【翻译】
  6. linux awk 内置函数详细介绍(实例)
  7. chrome 31删除输入框的历史记录
  8. 为Ubuntu配置ssh服务 方便远程登陆
  9. BZOJ 1037 [ZJOI2008]生日聚会Party
  10. cloud-init 工作原理 - 每天5分钟玩转 OpenStack(171)
  11. 一步一步学多线程-Timer
  12. VB.NET 打开窗体后关闭自己
  13. idea相关
  14. 目标检测(二)SSPnet--Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognotion
  15. 一文看懂python主要应用领域或应用场景
  16. AFNetworking 2.0使用(持续更新)
  17. HBase性能优化方法总结(转)
  18. 前端知识总结--js原型链
  19. 微信小程序 异步请求拿数据+使用外部js库
  20. PHP HTML DOM 解析器 中文手册

热门文章

  1. 吃透Python上下文管理器
  2. JS---案例:完整的轮播图---重点!
  3. iOS 和 H5 页面交互(WKWebview 和 UIWebview cookie 设置)
  4. 2018 经典的CVPR 关于ImageCaptioning论文
  5. DFA敏感词过滤实现
  6. python语言的鸭子类型和强类型语言的多态
  7. IDEA中使用Maven模板创建Servelet项目并使用Tomcat来运行项目
  8. vue如何debugger源码
  9. ionic + cordova安装指南
  10. Windows下RabbitMQ 的下载、配置、Java实现生产者和消费者例子