C学习随笔—自定义控件(面板)

C学习随笔—自定义控件(面板)最近一直在研究 C 的自定义控件 因为在实际开发使用中发现 C winform 的自定义控件并不满足需求 因此 自己在逐步开始接触自定义控件 并将其记录

大家好,欢迎来到IT知识分享网。

最近一直在研究C#的自定义控件,因为在实际开发使用中发现C# winform的自定义控件并不满足需求。因此,自己在逐步开始接触自定义控件,并将其记录。

首先,先完成一个最基本控件的实现,即一个面板,说起来就是一个框,这个框,可以调节里面的填充颜色,设置框线的宽度,虚实线类型,是方形,圆形或者椭圆形等。

涉及的C#第一个概念:get和set访问器,我们在使用控件属性时,会经常用到,属性的设置以及读取,该访问器就帮助我们实现这一功能,举例如下:(如我想要设置是否显示边框)

private bool _isBorderShow = true; public bool IsBorderShow { get { return this._isBorderShow; } set { this._isBorderShow = value; } }

基本格式如上所示,首先肯定需要定义一个参数来存储该属性,get访问器就是会返回该参数,set访问器会设置该参数,注意,set访问器有一个隐式参数,即value。value持有需要保存的数据。因此,value可以直接使用,而不需要重新定义。当然,该属性是要外部访问的,因此设置为PUBLIC。

之后呢,只需要在Visual Studio建立用户控件即可,因为我们是要建基类控件,因此还需要继承IContainerControl类,默认的用户控件仅仅继承了UserControl类。因此修改如下:

public partial class SimplyCtrlBase: UserControl,IContainerControl //多接口控件,UserControl:作为该控件的模板接口,IContainerControl:可以使该自定义控件作为其他控件的父类 { //增加控件的属性和方法 //用户控件的初始化 public SimplyCtrlBase() { InitializeComponent();//控件的初始化 } }

用户控件的属性比较容易,只需要调用get和set访问器即可实现,那么控件的样子需要怎么弄呢?其实就是重绘,因此需要对控件的绘制函数进行重写。

那么我们需要实现怎么样的控件呢?见下图:

C学习随笔—自定义控件(面板)

同一个控件的4个设置

上面就是我想要实现的面板类型,可以给用户足够的开放度,选择圆形,长方形,椭圆形。可以设置渐变的背景色,可以设置框线的类型,可以设置框线的宽度,等等。

重绘函数的实现如下:

protected override void OnPaint(PaintEventArgs e) { //写自己的重绘图形即可。 base.OnPaint(e); }

剩下的也没啥好说的,直接上代码:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace MyLib_Simply { [Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(System.ComponentModel.Design.IDesigner))] public partial class SimplyCtrlBase: UserControl,IContainerControl //多接口控件,UserControl:作为该控件的模板接口,IContainerControl:可以使该自定义控件作为其他控件的父类 { //方形边框是否显示圆弧 private bool _isRoundCorner = true; [Description("Round Corner flag,Only available for RECTANGLE BLOCK"),Category("UserDefinedBase")]//Category:显示类别,Description:属性或者方法描述 public bool IsRoundCorner { get {return this._isRoundCorner;} set {this._isRoundCorner = value;} } //设置边框圆弧角度 private int _roundCorner = 20; [Description("Round Corner Property for Rectangle Block,In fact, it means diameter for round corner"),Category("UserDefinedBase")] public int RoundCorner { get {return this._roundCorner; } set {this._roundCorner = value;} } //设置是否显示框线 private bool _isBorderShow = true; [Description("Whether is Border showing or not"),Category("UserDefinedBase")] public bool IsBorderShow { get{return this._isBorderShow;} set{this._isBorderShow = value;} } //设置框线宽度 private int _borderWidth =2; [Description("Border Width"),Category("UserDefinedBase")] public int BorderWidth { get{return this._borderWidth;} set{ this._borderWidth = value;} } //设置框线颜色 private Color _borderColor = Color.Black; [Description("Border Color"), Category("UserDefinedBase")] public Color BorderColor { get{ return this._borderColor;} set{this._borderColor = value; } } //设置框线类型,实线还是虚线 private DashStyle _borderDashStyle = DashStyle.Solid; [Description("Border Line DashStyle"),Category("UserDefinedBase")] public DashStyle BorderDashStyle { get{return this._borderDashStyle;} set{this._borderDashStyle = value;} } //设置面板类型,方形还是椭圆形 public enum block_type_t { BLOCK_RECTANGLE, BLOCK_OVAL, } //设置边框类型 private block_type_t _blockType = block_type_t.BLOCK_RECTANGLE; [Description("Block Type"), Category("UserDefinedBase")] public block_type_t BlockType //必须有一个访问器,Get或者Set { get{ return this._blockType;} set {this._blockType = value;} } //设置面板背景色是否渐变 private bool _isKindsColor = true; [Description("Kinds of Color Flag for Block Back Color"), Category("UserDefinedBase")] public bool IsKindsColor { get { return this._isKindsColor; } set { this._isKindsColor = value; } } //渐变色的第二种颜色,BackColor为第一种颜色 private Color _alternateColor = SystemColors.Control; [Description("Alternate Color for linear kinds of color,i.e. from BackColor to Alternate Color"),Category("UserDefinedBase")] public Color AlternateColor { get{return this._alternateColor;} set{this._alternateColor = value;} } //控件初始化 public SimplyCtrlBase() { InitializeComponent(); base.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer|ControlStyles.ResizeRedraw, true); //开启双缓冲 } //控件重绘 protected override void OnPaint(PaintEventArgs e) { if (this.Visible) { switch (this._blockType) { case block_type_t.BLOCK_RECTANGLE: default: GraphicsPath path = new GraphicsPath(); Pen pen = new Pen(this._borderColor, (float)(this._borderWidth)); pen.DashStyle = this._borderDashStyle; if (this._isRoundCorner) { RectangleF rect = new Rectangle(0, 0, this.Width, this.Height); path = GetRoundRectPath(rect, this._roundCorner, 0); base.Region = new Region(path); Rectangle ClientRect = this.ClientRectangle; path = GetRoundRectPath(ClientRect, this._roundCorner, (float)((this._borderWidth)/2.0)); } else { path.AddRectangle(this.ClientRectangle); path.CloseFigure(); base.Region = new Region(path); path.AddRectangle(new RectangleF((float)((this._borderWidth)/2.0), (float)((this._borderWidth) / 2), this.ClientRectangle.Width - (this._borderWidth), this.ClientRectangle.Height - (this._borderWidth ))); path.CloseFigure(); } e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; if (this._isKindsColor) { //背景色的线性渐变 LinearGradientBrush brush = new LinearGradientBrush(e.ClipRectangle, this.BackColor, this._alternateColor, 90f); e.Graphics.FillRectangle(brush, e.ClipRectangle); brush.Dispose();// release resource } else { e.Graphics.FillPath(new SolidBrush(this.BackColor), path); } if (this._isBorderShow) { e.Graphics.DrawPath(pen, path); } pen.Dispose(); break; case block_type_t.BLOCK_OVAL: path = new GraphicsPath(); RectangleF rectf = new RectangleF(0, 0, this.Width, this.Height); path.AddEllipse(rectf); path.CloseFigure(); this.Region = new Region(path); e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; if (this._isKindsColor) { LinearGradientBrush brush = new LinearGradientBrush(e.ClipRectangle, this.BackColor, this._alternateColor, 90f); e.Graphics.FillEllipse(brush, e.ClipRectangle); brush.Dispose();// release resource } else { e.Graphics.FillPath(new SolidBrush(this.BackColor), path); } if (this._isBorderShow) { pen = new Pen(this._borderColor, this._borderWidth); rectf = new RectangleF((float)(this._borderWidth / 2.0), (float)((this._borderWidth) / 2.0), (float)(this.Width - this._borderWidth), (float)(this.Height - this._borderWidth)); path = new GraphicsPath(); path.AddEllipse(rectf); path.CloseFigure(); e.Graphics.DrawPath(pen, path); pen.Dispose(); } break; } } base.OnPaint(e); } //带弧线的方形边框 private GraphicsPath GetRoundRectPath(RectangleF rect, int num,float offset) { GraphicsPath path = new GraphicsPath(); RectangleF rect2 = new RectangleF(rect.Location, new Size(num, num)); rect2.X += offset; rect2.Y =rect2.Top+offset; path.AddArc(rect2, 180f, 90f);//左上角 rect2.X = rect.Right - num-offset; path.AddArc(rect2, 270f, 90f);//右上角 rect2.Y = rect.Bottom -num-offset; path.AddArc(rect2, 0f, 90f);//右下角 rect2.X = rect.Left+offset; path.AddArc(rect2, 90f, 90f);//左下角 path.CloseFigure(); return path; } protected override void WndProc(ref Message m) { if (m.Msg != 20) { base.WndProc(ref m); } } } } 

上面就是我显示的全部代码,实现效果就是图中所示。另外这个是最简单的一个自定义控件的实现,没有涉及事件,这个可以作为其他控件的基类,如按钮,标签等等。后面的文章我会对其他常用控件进行重绘。敬请期待,当然,如果大家有一些好的实现方式,也可以留言告诉我,大家共同学习进步。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/181361.html

(0)
上一篇 2025-06-19 07:10
下一篇 2025-06-19 07:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信