一、防闪烁的两种方法
1.直接设置窗体的 DoubleBuffered 属性:
publicpartialclassMyForm : Form
{
publicMyForm()
{
InitializeComponent();
this.DoubleBuffered =true;// 启用双缓冲
}
}
2.通过 SetStyle 方法启用双缓冲:
publicpartialclassMyForm : Form
{
publicMyForm()
{
InitializeComponent();
SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint,true);
}
}
3.修改窗体的扩展样式(WS_EX_COMPOSITED)
通过设置 CreateParams 的 ExStyle 属性,启用系统级别的双缓冲。
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // WS_EX_COMPOSITED
return cp;
}
}
4.禁用清除背景消息(WM_ERASEBKGND)
窗体在重绘时会频繁清除背景(WM_ERASEBKGND),禁用此消息可减少闪烁
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0014) // WM_ERASEBKGND 消息
{
return; // 直接返回,不处理清除背景
}
base.WndProc(ref m);
}
二、自定义控件,扩展控件如何建立
1.扩展控件建立
1.1添加用户控件或者窗体控件
1.2将继承的UserCotrol改为继承Button
public partial class ButtonExtension : Button
{
public ButtonExtension()
{
InitializeComponent();
}// 给Button扩展事件,属性,方法。
。。。。。。。
}
1.3生成解决方案
1.4双击错误列表中的错误内容,跳转到ButtonExtension.Designer,删除或注释错误代码 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;


2.自定义控件建立
1.1添加用户控件或者窗体控件
1.2将继承的UserCotrol改为继承Button
public partial class MyButton : Control
{
public MyButton()
{
InitializeComponent();
}
}
1.3生成解决方案
1.4双击错误列表中的错误内容,跳转到MyButton.Designer,删除或注释错误代码
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
三、SetStyle()给自定义控件设置风格
UserPaint: 指定控件必须调用 OnPaint 方法来绘制自己,而不是使用默认的绘制逻辑。这通常用于自定义控件的绘制。
AllPaintingInWmPaint: 指定所有的绘制操作都应该在 WM_PAINT 消息处理中完成。这有助于减少闪烁,因为它确保了所有的绘制都通过一个单一的绘制消息进行。
DoubleBuffer: 启用双缓冲,减少闪烁和图形失真。在.NET Framework 2.0之前,这是实现双缓冲的常用方法。
OptimizedDoubleBuffer: 启用优化的双缓冲。这是在.NET Framework 2.0及更高版本中推荐的方法,因为它提供了更好的性能。
ResizeRedraw: 当控件调整大小时,控件将重绘自身。默认情况下,控件在调整大小时不会重绘,除非设置了这个样式。
SupportsTransparentBackColor: 允许控件的背景色是透明的。
StandardClick: 指定控件响应标准的鼠标点击。如果未设置此样式,控件可能不会响应点击事件。
Selectable: 指定控件可以被选中,通常用于键盘导航。
UserMouse: 指定控件将处理鼠标事件,即使鼠标不在控件的区域内。
UseAntiAlias: 指定控件使用抗锯齿技术来绘制文本和图形。
UseSmoothScrolling: 指定控件使用平滑滚动。
this.SetStyle(ControlStyles.UserPaint, true); //***
this.SetStyle(ControlStyles.ResizeRedraw, true); //***
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.StandardClick, true);
this.SetStyle(ControlStyles.Selectable, true); //*** 能交互时,尽量让能选中,不能交互时,就不要设置这个样式。// 简写成如下代码:
/*this.SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.StandardClick | ControlStyles.Selectable | ControlStyles.UserMouse , true);
}
四、使用GDI+对控件进行完全重绘步骤
protected override void OnPaint(PaintEventArgs e)
{
// base表示基类
base.OnPaint(e);// 1.拿到要绘制的“画板,画布”,目的:将来在此处绘制图形
Graphics g = e.Graphics;// 2.画板的一些配置参数(省略) Smooth平滑,“锯齿,毛边”
g.SmoothingMode = SmoothingMode.AntiAlias; // 平滑模式 AntiAlias抗锯齿,HighSpeed高速度,HighQuality高质量
g.InterpolationMode = InterpolationMode.HighQualityBicubic; // 插补模式
g.TextRenderingHint = TextRenderingHint.AntiAlias; // 文本渲染g.PixelOffsetMode = PixelOffsetMode.HighQuality; // 像素偏移模式
g.CompositingQuality = CompositingQuality.HighQuality; // 合成质量
g.CompositingMode = CompositingMode.SourceOver; // 合成模式//3.绘制图形 DrawXXX()绘制 FillXXX()填充
// 参数:绘制的文字,字体,画笔,绘制的位置
// Graphics,Font,Brush|Color,Point|F,Rectangle|F
//g.DrawString("文字", new Font("宋体", 12, FontStyle.Underline), Brushes.Red, new Point(10, 10));
//g.DrawImage(Properties.Resources.a, new Point(10, 10));g.FillRectangle(Brushes.Red, new Rectangle(10, 10, 100, 100));
}
五、圆角按钮案例
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace MYN_DGI_622.UserControls
{
public partial class RoundButton : Button
{
public RoundButton()
{
InitializeComponent();
//防闪烁
SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
}
private float radius = 10;
[Description("圆角半径"), DefaultValue(10)]
public float Radius
{
get { return radius; }
set { radius = value; Refresh(); }
}
private Color borderColor = Color.Red;
[Description("边框颜色"), DefaultValue(typeof(Color), "Red")]
public Color BorderColor
{
get { return borderColor; }
set { borderColor = value; Refresh(); }
}
private float borderWidth = 1;
[Description("边框宽度"), DefaultValue(1)]
public float BorderWidth
{
get { return borderWidth; }
set { borderWidth = value; Refresh(); }
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g=e.Graphics;
RectangleF rect=new RectangleF (BorderWidth, BorderWidth, this.Width-2*BorderWidth, this.Height-2*BorderWidth);
GraphicsPath path = GetRoundedRect(rect, Radius); // 获取圆角矩形路径
SolidBrush brush = new SolidBrush(this.BackColor); // 实体画刷
if (BorderWidth>0)
{
var pen = new Pen(BorderColor, BorderWidth); // 创建画笔
g.DrawPath(pen, path); // 绘制圆角矩形边框
this.Region = new Region(rect);
}
else
{
g.FillPath(brush, path); // 填充圆角矩形区域
SizeF textSize = g.MeasureString(this.Text, this.Font);
float x = (rect.Width - textSize.Width) / 2F;
float y = (rect.Height - textSize.Height) / 2F;
// 3。绘制文字
g.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), x, y);
this.Region = new Region(path);
}
}
private GraphicsPath GetRoundedRect(RectangleF rect, float radius)
{
GraphicsPath path=new GraphicsPath();
if (radius == 0)
{
path.AddRectangle(rect);
}
else
{
float diameter = radius * 2; // 直径等于半径的两倍。
int arcAngle = 90; // 圆弧的角度为90度。可以根据需要调整这个值以改变圆角的弧度。
path.AddArc(rect.X + BorderWidth, rect.Y + BorderWidth, diameter, diameter, 180, arcAngle); // 左上角圆弧。
path.AddArc(rect.Right - diameter - BorderWidth, rect.Y + BorderWidth, diameter, diameter, 270, arcAngle); // 右上角圆弧(电脑Y坐标上面为负,是270°,下面为正,是90°)
path.AddArc(rect.Right - diameter - BorderWidth, rect.Bottom - diameter - BorderWidth, diameter, diameter, 0, arcAngle); // 右下角圆弧
path.AddArc(rect.X + BorderWidth, rect.Bottom - diameter - BorderWidth, diameter, diameter, 90, arcAngle); // 左下角圆弧
path.CloseFigure();
}
return path;
}
}
}

364

被折叠的 条评论
为什么被折叠?



