C#窗口闪烁问题解决

https://www.cnblogs.com/AndyDai/p/5203798.html

开发WinForm 程序时经常会遇到闪屏的问题,这会给用户造成很差的使用体验,所以必须妥善解决好这个问题。

首先,我们先要找出闪屏的原因,就我目前遇到的问题而言,其原因真是五花八门。

主要的原因有:使用了很多的组件导致加载缓慢,使用了性能差的组件(PictureBox、Button等)。

所以,不论开发者的水平如何,微软给我们也挖了坑的。

对于控件太多造成的闪屏,其原因有两个:

1. 绘制控件时,Windows 会给控件发送两个消息。第一个是WM_ERASEBKGND消息,它会触发OnPaintBackground方法,绘制控件背景。

第二个是WM_PAINT消息,它会触发 OnPaint()方法,绘制控件界面。当绘制很慢的时候,会先看到背景,然后才看到界面,这样造成闪烁。

解决方案:在构造方法中设置 ControlStyles 的OptimizedDoubleBuffer 和AllPaintingInWmPaint为True,完全启用双缓冲。

启用双缓冲的首选方法是将该控件的 DoubleBuffered 属性设置为 true,这会产生同样的结果,原因不细说了。

this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);

this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

2. 有很多控件的窗体需要很长时间来绘制。特别是在它使用性能很差的PictureBox、Button等时。一旦你加上50多个的控件,闪屏就开始变得明显了。

窗体会先绘制其自身背景,并在控件所在地方留下"洞"。这些"洞"通常是白色的,当你使用Opacity 或Transparency是黑色的。

然后每个控件被绘制后,就填充在"洞"中。这种视觉效果是很丑陋的,而且在WinForm 中没有现成的解决方案。

双缓冲也不能解决它,因为它只适用于一个单一的控件,而不是一组复合控件。

解决方案:设置CreateParams的ExStyle为ExStyle  为 0x02000000 (WS_EX_COMPOSITED)。

设置了这个值之后XP(其他系统好像也可以,没有考证)会把窗体和它的子窗体都开启双缓冲

protected override CreateParams CreateParams {

      get {

        CreateParams cp = base.CreateParams;

        cp.ExStyle |= 0x02000000;

        return cp;

      }

 }

这里有一些需要注意的地方:这种方式并不会加快绘制的过程。当发生绘制时,窗体只是停留在不可见的状态,当绘制完成后就会在屏幕上弹出。

这时窗体的Opacity or TransparencyKey 是不会起作用的,窗体的轮廓是可见的,在绘制区域会出现一个丑陋的黑色矩形框。

要解决这个问题,最好使用计时器来增加不透明度值到99%,以使其在绘制后可见,这样用户就不会看到黑色矩形了。

public partial class FormDemo : Form
    {
        private Timer Timer = null;
        public FormDemo()
        {
            InitializeComponent();
            Timer = new Timer() { Interval = 100 };
            Timer.Tick += new EventHandler(Timer_Tick);
            base.Opacity = 0;
            Timer.Start();
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            if (this.Opacity >= 1)
            {
                Timer.Stop();
            }
            else
            {
                base.Opacity += 0.2;
            }
        }
    }

先写这么多,慢慢补充吧

原文地址:https://www.cnblogs.com/zhaogaojian/p/8618012.html

时间: 2024-11-02 20:45:15

C#窗口闪烁问题解决的相关文章

主窗口刷新,子窗口闪烁

问题:主窗口刷新,子窗口闪烁 解决方案:主窗口创建时,传WS_CLIPCHILDREN

C# Windows API应用之FlashWindowEx ——实现窗口闪烁的方法

Windows API Windows 这个多作业系统除了协调应用程序的执行.分配内存.管理资源-之外, 它同时也是一个很大的服务中心,调用这个服务中心的各种服务(每一种服务就是一个函数),可以帮应用程式达到开启视窗.描绘图形.使用周边设备等目的,由于这些函数服务的对象是应用程序(Application), 所以便称之为 Application Programming Interface,简称 API 函数.WIN32 API也就是Microsoft Windows 32位平台的应用程序编程接口

Android ListView滑动过程中图片显示重复错位闪烁问题解决[转载]

转自:here 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及ListView的缓存机制.1.原因分析ListView item缓存机制:为了使得性能更优,ListView会缓存行item(某行对应的View).ListView通过adapter的getView函数获得每行的item.滑动过程中, a. 如果某行item已经滑出屏幕,若该item不在缓存内,则put进缓存,否则更新缓存:b. 获取滑入屏幕的行item之前会先判断缓存中是否有可

.net4.6版本前设置window子窗口位置主窗口闪烁

原文:.net4.6版本前设置window子窗口位置主窗口闪烁 在安装了.net4.6的版本是不会出现该问题的,但是在4.6以下的版本会出现,当设置之窗体的left和top属性时,会让主窗体闪烁一下. 之前是在load事件下写的: child_window.loaded+=(sender,e)=> { child_window.WindowStartupLocation=WindowStartupLocation.Manul; child_window.Left= ***; child_wind

在窗口闪烁产生的原因

一般的windows 复杂的界面需要使用多层窗口而且要用贴图来美化,所以不可避免在窗口移动或者改变大小的时候出现闪烁. 先来谈谈闪烁产生的原因 原因一: 如果熟悉显卡原理的话,调用GDI函数向屏幕输出的时候并不是立刻就显示在屏幕 上只是写到了显存里,而显卡每隔一段时间把显存的内容输出到屏幕上,这就是刷新周期. 一般显卡的刷新周期是 1/80秒左右,具体数字可以自己设置的. 这样问题就来了,一般画图都是先画背景色,然后再把内容画上去,如果这两次操作不在同一个 刷新周期内完成,那么给人的视觉感受就是

ShowWindow(SW_HIDE)窗口闪烁问题

问题提出: 窗口创建时候实现直接隐藏,可是使用函数ShowWindow(SW_HIDE)窗口要闪烁一下: 查看解决办法: 论坛里看到很久之前的一个讨论,很受启发:具体可以参考链接地址:http://bbs.csdn.net/topics/10407927 解决办法: m_***.Create(_T("Empty Temp"),WS_CHILD|WS_VISIBLE,rcList,this,101); //m_***.ShowWindow(SW_HIDE);

Android ListView滑动过程中图片显示重复错乱闪烁问题解决

转自:http://www.oschina.net/question/221817_121051 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及ListView的缓存机制.1.原因分析ListView item缓存机制:为了使得性能更优,ListView会缓存行item(某行对应的View).ListView通过adapter的getView函数获得每行的item.滑动过程中, a. 如果某行item已经滑出屏幕,若该item不在缓存内,则p

angular ng-show 页面闪烁问题解决办法

问题:用ng-show条件判断控制dom显示隐藏 会出现页面初始加载页面闪烁问题 解决方案: 1. <div ng-show="conferenceInfo" class="ng-hide"> 加一个class ng-hide 2.在页面最外层加一个class ng-cloak

C# winfrom界面跳转闪烁问题解决方法

在窗体的构造函数中添加代码: SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景. SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲 然后在构造函数下面,写以下方法: #region 解决闪烁问题 protected override void WndProc(ref Message m) {