解决Winform应用程序中窗体背景闪烁的问题

本文转载:https://my.oschina.net/Tsybius2014/blog/659742

我的操作系统是Win7,使用的VS版本是VS2012,文中的代码都是C#代码。

这几天遇到一个问题,即我用一个嵌入图片的Panel作为Winform应用程序的背景,如下图所示:

这是一个Winform窗体,里面放置了一个Panel,Dock属性为Fill,BackgroundImage使用了《少年电世界》2003年第02期的封面图片,BackgroundImageLayout使用了Stretch。

这个界面现在有两个问题:

1、在窗体第一次被打开时,背景图片会出现明显的闪烁

2、在拉动窗体的边界以调整窗体大小时,背景图片非出现明显的闪烁

为了处理这一问题,我查了一些资料,也都逐个试过了,下面先说下其中的两个有代表性方法:

方法1:直接使用双缓冲

SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲

我尝试着将这段代码加到窗体的构造函数中,并不能解决问题,闪烁依然非常明显

在MSDN上还有一篇文章《如何通过对窗体和控件使用双缓冲来减少图形闪烁》

地址:https://msdn.microsoft.com/zh-cn/library/3t7htc9c%28v=vs.80%29.aspx

这篇文章中也介绍了一个方法使用双缓冲:

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

这个方法依然不能解决问题

方法2:重写CreateParams方法

方法2需要将以下这段代码放在Form类的代码内

protected override CreateParams CreateParams
{
    get
    {
        CreateParams paras = base.CreateParams;
        paras.ExStyle |= 0x02000000;
        return paras;
    }
}

这个方法我一开始尝试的时候一度认为是有效的,但使用了一段时间后还是发现了问题:

1、这个方法可以解决问题1,但不能解决问题2

2、这个方法会影响一些其他控件、组件的重绘(这点才是致命的)

因此,这个方法也不能解决问题

上面两个方法都不能解决问题,于是我继续求助度娘,终于在下面这个页面找到了解决方法:

方法3:封装Panel类

http://blog.chinaunix.net/uid-14414741-id-2814313.html

这个方法,需要新建一个PanelEnhanced类继承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容器,将程序的背景图片放到里面,再运行程序,程序背景闪烁的问题就完美解决了!

时间: 2024-10-22 05:03:41

解决Winform应用程序中窗体背景闪烁的问题的相关文章

WinForm应用程序中实现自动更新功能

WinForm应用程序中实现自动更新功能 编写人:左丘文 2015-4-20 近来在给一客户实施ECM系统,但他们使用功能并不是我们ECM制造版提供的标准功能,他们要求对系统作一些定制功能,为了避免因程序的bug而带来频繁让用户更新程序的不良影响,就想给ECM增加一个winform自动更新功能,今天在这里,我想与大家一起分享代码,在此做个小结,以供参考.有兴趣的同学,可以一同探讨与学习一下,否则就略过吧.   1. 首先我们在这里先分析一下其它程序猿的一些基本情况: 相信有许多程序猿都喜欢用Wi

在WinForm应用程序中快速实现多语言的处理(2)--开发框架模块的整合

我在上篇随笔<在WinForm应用程序中快速实现多语言的处理>里面介绍了Winform开发中多语言的处理解决方案,整个多语言解决方案是以实际需求为驱动,以减少代码改动,高效处理为目的,通过基类继承的方式减少代码修改,通过引入翻译API方式减少翻译处理时间,本随笔继续深化这个多语言处理方案的介绍,是指整合在开发框架中进行无缝的使用. 1.多语言的处理步骤 1)提取多语言处理JSON文件 我们通过把程序界面或者代码里面的中文提取出来,放到JSON文件中,对不同模块可以分为不同的JSON文件,如下所

解决winform应用程序在不同分辨率系统下界面错乱的问题

首先,遇到的问题是这样的,当已经ok的程序在我电脑上运行时出现了界面很小,而且错乱无章的情况,如下图: 记得上一次我的解决办法是每个控件每个控件拖动修改,到最后perfect!可是??修改之后呢?半天时间没有了,要做的事没有挪动一步..... 后来在网上查了查这是什么原因: 问题分析: 产生界面混乱的主要原因是,winform程序的坐标是基于点(point)的,而point与DPI(分辨率,每英寸所打印点数)相关,一英寸等于72 Point,当DPI发生变化时,显示在界面上的尺寸根据DPI自动变

解决SharePoint “/”应用程序中的服务器错误。

"/"应用程序中的服务器错误. 访问被拒绝. 说明:访问服务此请求所需的资源时出错.服务器可能未配置为访问所请求的 URL. 错误消息 401.2.: 未经授权: 服务器配置导致登录失败.请验证您是否有权基于您提供的凭据和 Web 服务器上启用的身份验证方法查看此目录或页.请与 Web 服务器的管理员联系以获得其他帮助. 解决方法--管理中心--应用程序管理--选择当前应用程序--单击--身份验证提供程序--默认--弹出的页面里选中集成的Windows验证 如下图 然后就OK了. 版权

在WinForm应用程序中,使用选项卡控件来加载不同的Form界面!

1 TabPage tp=new TabPage(); 2 your选项卡控件.Controls.Add(tp); 3 4 From1 frm=new Form1(); 5 frm.TopLevel = false; 6 frm.Dock = DockStyle.Fill; 7 frm.FormBorderStyle =FormBorderStyle.None; 8 9 tp.Controls.Add(frm); 10 frm.Visible = true; 最近想了一些关于子窗体嵌套显示在父窗

.Net学习 第3季02 winform应用程序 MDI窗体设计 menuStrip

窗体2.3.4...只落在窗体1(父窗体)的范围内并且可以全部显示的设计---MDI窗体设计 在窗体1中创建menuStrip类的对象(菜单栏),设置其中一个的点击事件为显示窗体2.3.4 private void 显示子窗体ToolStripMenuItem_Click(object sender, EventArgs e) { Form2 f2 = new Form2(); f2.Show(); Form3 f3 = new Form3(); f3.Show(); Form4 f4 = ne

promise解决微信小程序中的request回调地狱

//使用 request(url,methods ,data).then(res => { //服务器返回数据 console.log(res ); }).catch(res => { //报错 console.log(res); }).finally(()=>{ //完成 console.log("结束"); }) //封装request方法 const request = (url, method, data) => { var promise = new

开源组件NanUI一周年 - 使用HTML/CSS/JS来构建.Net Winform应用程序界面

NanUI是什么 NanUI基于ChromiumFX项目进行开发,它能让你在你的Winform应用程序中使用HTML5/CSS3/Javascript等网页技术来呈现用户界面(类似Electron).同时NanUI提供了原生窗口和定制化的无标题栏无边框窗口,你能使用全部的网页技术来设计和呈现你的应用程序界面. 开源方式 NanUI基于MIT协议,所以无论你使用NanUI来开发商业项目或者开源.免费项目都将不受任何限制,只需要遵照协议文件中规定的,在你的软件中声明使用了NanUI技术即可. 系列文

解决winform窗体闪烁问题

如果你在Form中绘图的话,不论是不是采用的双缓存,都会看到图片在更新的时候都会不断地闪烁,解决方法就是在这个窗体的构造函数中增加以下三行代码: 请在构造函数里面底下加上如下几行: SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景. SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲 参数说明