本文转载: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容器,将程序的背景图片放到里面,再运行程序,程序背景闪烁的问题就完美解决了!

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

  1. 在WinForm应用程序中快速实现多语言的处理

    在国际化环境下,越来越多的程序需要做多语言版本,以适应各种业务需求的变化.在Winform应用程序中实现多语言也有常规的处理方式处理,不过需要针对每个语言版本,重新修改Winform界面的显示,对一些 ...

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

    我在上篇随笔<在WinForm应用程序中快速实现多语言的处理>里面介绍了Winform开发中多语言的处理解决方案,整个多语言解决方案是以实际需求为驱动,以减少代码改动,高效处理为目的,通过 ...

  3. C#WinForm应用程序中嵌入ECharts图表

    C#WinForm应用程序中嵌入ECharts图表 程序运行效果: 下载ECharts: 官网下载ECharts :http://echarts.baidu.com/download.html 或者直 ...

  4. 在WinForm应用程序中嵌入WPF控件

    我们知道,在WPF界面上添加WinForm的控件需要使用WindowsFormHost类.而在WinForm界面上添加WPF控件该如何做呢?有没有类似的类呢?明显是有的,ElementHost就是为了 ...

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

    WinForm应用程序中实现自动更新功能 编写人:左丘文 2015-4-20 近来在给一客户实施ECM系统,但他们使用功能并不是我们ECM制造版提供的标准功能,他们要求对系统作一些定制功能,为了避免因 ...

  6. 一招解决微信小程序中的H5缓存问题

    一招解决微信小程序中的H5缓存问题1.问题描述开发过程中,为了更新代码方便,往往会在小程序中嵌入H5页面.但问题来了,小程序原生代码更新版本后,简单的从微信中删除或者代码强刷就可以解决缓存问题,但小程 ...

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

    TabPage tp=new TabPage(); your选项卡控件.Controls.Add(tp); From1 frm=new Form1(); frm.TopLevel = false; f ...

  8. (转)C#.NET WINFORM应用程序中控制应用程序只启动一次

    原文地址 :http://www.cnblogs.com/emanlee/archive/2009/08/31/1557379.html using System; using System.Thre ...

  9. 解决微信小程序中Date.parse()获取时间戳IOS不兼容的问题(IOS为NaN的问题)

    前端同事在做微信小程序时发现IOS获取的时间戳为空的问题,后来通过跟踪发现,原来是因为IOS系统不支持2017-01-01格式的时间导致的, var mydata = '2017-01-01 11:0 ...

随机推荐

  1. MyEclipse基础配置

    1.设置默认工作空间编码 window/preferences/general/workspace/Text file encoding 2.设置文件默认打开方式 xml建议设置 html建议设置 j ...

  2. js中cookie的使用

    js中并没有封装好的存储cookie,取得cookie和删除cookie的函数,所以必须得自己手动处理,并且cookie中也只能存储字符串,不能存储数组等复杂的数据类型. // 添加cookie fu ...

  3. javascript函数中的三个技巧【二】

    技巧二: [惰性载入函数] 因为浏览器之间的行为的差异,我们经常会在函数中包含了大量的if语句,以检查浏览器特性,解决不同浏览器的兼容问题,比如,我们最常见的为dom节点添加时间的函数 functio ...

  4. Quoit Design

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission ...

  5. Java邮件服务学习之二:SMTP和POP3

    一.SMTP SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则.SMTP协议属于TCP/IP协议簇,它帮助每台计算 ...

  6. __construct()和__initialize()

    ThinkPHP中的__initialize()和类的构造函数__construct()网上有很多关于__initialize()的说法和用法,总感觉不对头,所以自己测试了一下.将结果和大家分享.不对 ...

  7. Benefits of Cold Showers: 7 Reasons Why Taking Cool Showers Is Good For Your Health

    Benefits of Cold Showers: 7 Reasons Why Taking Cool Showers Is Good For Your Health Most of us have ...

  8. C++和MATLAB混合编程-DLL

    先小话一下DLL,DLL是动态链接库,是源代码编译后的二进制库文件和程序接口,和静态链接库不同的是,程序在编译时并不链接动态链接库的执行体,而是在文件中保留一个调用标记,在程序运行时才将动态链接库文件 ...

  9. linux高级技巧:heartbeat+lvs(一)

    1.heartbeat一个简短的引论:        Heartbeat 项目是 Linux-HA project的一个组成部分,它实现了一个高可用集群系统.心跳服务和集群通信是高可用集群的两个关键组 ...

  10. (转)发现两个有用的C函数_alloca()、_msize()

    转自: http://blog.csdn.net/pony12/article/details/8678071 (1)_alloca()alloca也是用来分配存储空间的,它和malloc的区别是它是 ...