C# winform界面闪屏问题解决方法
登录以及切换界面时,界面不停闪烁的问题
将下面代码添加到窗体代码中:
protected override CreateParams CreateParams //防止界面闪烁 { get { CreateParams paras = base.CreateParams; paras.ExStyle |= 0x02000000; return paras; } }
重载消息发送函数操作,禁掉每次重绘清除画布
protected override void WndProc(ref Message m) { if (m.Msg == 0x0014) // 禁掉清除背景消息 return; base.WndProc(ref m); }
使用Form的双缓存可以减少闪屏,但效果不明显,可以在Form的Load事件里添加以下代码
1 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
2 this.SetStyle(ControlStyles.DoubleBuffer, true);
3 this.SetStyle(ControlStyles.UserPaint, true);
4 this.SetStyle(ControlStyles.ResizeRedraw, true);
1)使用setStyle
网上有说使用setStyle函数去设置该控件的参数,具体为:
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
这三个选项参数后者是依赖前者的,必须并存,否则无效。并且这个函数本身是protected的,所以首先需要继承某控件再使用。
这个目标是跟前面正确解决方案一致,也是禁止清除背景并开启双缓冲,但需要使用用户绘制选项,而且是全部交由用户绘制。这需要自己实现控件的全部绘制,比较麻烦。所以这个方法不是完全不可行,但是需要额外工作量,不推荐。我也没有使用。
2)使用BeginUpdate和EndUpdate
这一对操作对于需要批量操作更新控件的情景有比较好的效果,比如初始化时批量添加了大量节点。坏处就在于不能即时更新。所以,对于频繁的更新节点并希望立即反映到界面的情况不适用。如果使用并且没有禁掉清除界面消息的话,则控件看起来就会不停的闪烁,而且以白底为主,内容几乎不可见。因为界面更新都在EndUpdate处完成,操作太多导致EndUpdate阻塞时间过长,且清空在先,更新在后,导致界面看起来长时间处于空白状态。
3)使用ControlStyles.EnableNotifyMessage选项
这个选项的作用和正确解决方案也是一致的。使用方法是:
SetStyle(ControlStyles.EnableNotifyMessage, true);
protected override void onNotifyMessage(Message m)
{
// 此处书写过滤消息代码
}
窗体背景闪烁的问题
封装 Panel 类
/// <summary> /// 加强版 Panel /// </summary> class PanelEnhanced : Panel { /// <summary> /// OnPaintBackground 事件 /// </summary> /// <param name="e"></param> protected override void OnPaintBackground(PaintEventArgs e) { // 重载基类的背景擦除函数, // 解决窗口刷新,放大,图像闪烁 return; } /// <summary> /// OnPaint 事件 /// </summary> /// <param name="e"></param> protected override void OnPaint(PaintEventArgs e) { // 使用双缓冲 this.DoubleBuffered = true; // 背景重绘移动到此 if (this.BackgroundImage != null) { e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; e.Graphics.DrawImage( this.BackgroundImage, new System.Drawing.Rectangle(0, 0, this.Width, this.Height), 0, 0, this.BackgroundImage.Width, this.BackgroundImage.Height, System.Drawing.GraphicsUnit.Pixel); } base.OnPaint(e); } }
将之前我们建立窗体中的 Panel 容器换为我们新封装的 PanelEnhanced 容器,将程序的背景图片放到里面,再运行程序,程序背景闪烁的问题就完美解决了
/// <summary>/// 加强版 Panel/// </summary>classPanelEnhanced : Panel { /// <summary>/// OnPaintBackground 事件/// </summary>/// <param name="e"></param>protected override void OnPaintBackground(PaintEventArgs e) { // 重载基类的背景擦除函数,// 解决窗口刷新,放大,图像闪烁return; } /// <summary>/// OnPaint 事件/// </summary>/// <param name="e"></param>protected override void OnPaint(PaintEventArgs e) { // 使用双缓冲this.DoubleBuffered = true; // 背景重绘移动到此if (this.BackgroundImage != null) { e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; e.Graphics.DrawImage( this.BackgroundImage, new System.Drawing.Rectangle(0, 0, this.Width, this.Height), 0, 0, this.BackgroundImage.Width, this.BackgroundImage.Height, System.Drawing.GraphicsUnit.Pixel); } base.OnPaint(e); } }