C# WinForm控件随窗体大小改变闪屏问题

发布时间 2023-08-01 08:12:07作者: BK小鬼

WinForm开发过程中UI设计是非常寻常,也是必不可少的。有些主窗体或子窗体以及自定义控件等控件会很多,加载或重绘时会导致闪屏,最大化及最小化也会导致闪屏,极度的影响用户体验。故根据此问题做一个分析研究,网上资料也找了很多,尝试了各种方式,但依然效果不明显,无法彻底解决。很多人提出是Donet框架底层问题(JAVA,C++不会有此问题),网上博客及论坛没有能够彻底解决的帖子。最终我依照处理方式相互结合,功夫不负有心人最终完美解决闪屏问题

多控件重绘导致闪屏,目前已经是许多开发者头疼的难题,研究该问题可以极大帮助更多开发者,下面我讲各种处理方式梳理一遍:

1.使用双缓存

public static void SetControlDoubleBuffer(Control ctl)
{

ctl.GetType().GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(ctl, true, null);
}
效果:肉眼无法看到调整的结果,可能对自定义控件有效果,没尝试

2.通过消息命令,控制刷新频率

SendMessage(this.Handle, WM_SETREDRAW, 0, IntPtr.Zero); //禁止重绘刷新
--控件重绘
SendMessage(this.Handle, WM_SETREDRAW, 1, IntPtr.Zero);//启动重绘刷新

效果:运行UI直接会卡死

3.重写CreateParams,防止WinForm切换闪屏

/// <summary>
/// 封装创建控件时所需的信息
/// </summary>
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}

}

效果:有显著效果,可以看到已经改善很多,但未彻底

4. 使用pictureBox替换panel 控件

效果:无任何效果

5.使用自定义控件Panel

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);
}
}

效果:无任何效果

6.更改窗体透明度

使用TransparencyKey更改窗体透明度,这是一个很好的方向

this.TransparencyKey = System.Drawing.Color.LightGray;

效果:效果不明显

总结:通过以上各种方式,任然存在闪屏,可以得到一定效果,但仍然无法彻底解决闪屏问题,然后挑出有效果的方式两两结合使用,最后我结合重写CreateParams外加更改窗体透明度,完美解决。


/// <summary>
/// 封装创建控件时所需的信息
/// </summary>
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}

}

private void Form4_Resize(object sender, EventArgs e)
{
//SendMessage(this.Handle, WM_SETREDRAW, 0, IntPtr.Zero);
float WidthChangeProportion = (this.Width) / CurrentWidth;//宽度变化比例
float HeightChangeProportion = (this.Height) / CurrentHeight;//高度变化比例

UpdateControlsSize(WidthChangeProportion, HeightChangeProportion, pictureBox1);
this.TransparencyKey = System.Drawing.Color.LightGray;
}

效果:微小的闪屏,肉眼几乎可以忽略
————————————————
版权声明:本文为CSDN博主「Byron.Huang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mageting20/article/details/132021968