精华内容
下载资源
问答
  • winform 双缓冲技术解决闪硕

    千次阅读 2013-05-16 09:11:04
    项目中,控件在大小变化时会有闪烁现象。 以双缓冲技术解决。  this.SetStyle(ControlStyles.OptimizedDoubleBuffer  | ControlStyles.ResizeRedraw  | ControlStyles.Selec

    项目中,控件在大小变化时会有闪烁现象。

    以双缓冲技术解决。

                this.SetStyle(ControlStyles.OptimizedDoubleBuffer
                           | ControlStyles.ResizeRedraw
                           | ControlStyles.Selectable
                           | ControlStyles.AllPaintingInWmPaint
                           | ControlStyles.UserPaint
                           | ControlStyles.SupportsTransparentBackColor,
                         true);

    或:

                this.SetStyle(ControlStyles.UserPaint, true);//自绘
                this.SetStyle(ControlStyles.DoubleBuffer, true);// 双缓冲
                this.SetStyle(ControlStyles.ResizeRedraw, true);//调整大小时重绘
                this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
                this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);// 双缓冲
                this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);   //透明效果
          

    成员名称           说明

     

     

       
      UserPaint 如果为 true,控件将自行绘制,而不是通过操作系统来绘制。如果为 false,将不会引发 Paint事件。此样式仅适用于派生自 Control 的类。
      Opaque 如果为 true,则控件被绘制为不透明的,不绘制背景。
      ResizeRedraw 如果为 true,则在调整控件大小时重绘控件。
      FixedWidth 如果为 true,则自动缩放时,控件具有固定宽度。例如,如果布局操作试图重新缩放控件以适应新的 Font,则控件的 Width 将保持不变。
      FixedHeight 如果为 true,则自动缩放时,控件具有固定高度。例如,如果布局操作试图重新缩放控件以适应新的 Font,则控件的 Height 将保持不变。
      StandardClick 如果为 true,则控件将实现标准 Click 行为。
      Selectable 如果为 true,则控件可以接收焦点。
      UserMouse 如果为 true,则控件完成自己的鼠标处理,因而鼠标事件不由操作系统处理。
      SupportsTransparentBackColor 如果为 true,控件接受 alpha 组件小于 255 的 BackColor 以模拟透明。仅在 UserPaint 位设置为 true 并且父控件派生自 Control 时才模拟透明。
      StandardDoubleClick 如果为 true,则控件将实现标准 DoubleClick 行为。如果 StandardClick 位未设置为true,则忽略此样式。
      AllPaintingInWmPaint 如果为 true,控件将忽略 WM_ERASEBKGND 窗口消息以减少闪烁。仅当 UserPaint 位设置为 true 时,才应当应用该样式。
      CacheText 如果为 true,控件保留文本的副本,而不是在每次需要时从 Handle 获取文本副本。此样式默认为 false。此行为提高了性能,但使保持文本同步变得困难。
      EnableNotifyMessage 如果为 true,则为发送到控件的 WndProc 的每条消息调用 OnNotifyMessage 方法。此样式默认为 falseEnableNotifyMessage 在部分可信的情况下不工作。
      DoubleBuffer 如果为 true,则绘制在缓冲区中进行,完成后将结果输出到屏幕上。双重缓冲区可防止由控件重绘引起的闪烁。如果将 DoubleBuffer 设置为 true,则还应当将 UserPaint 和AllPaintingInWmPaint 设置为 true
      OptimizedDoubleBuffer 如果为 true,则该控件首先在缓冲区中绘制,而不是直接绘制到屏幕上,这样可以减少闪烁。如果将此属性设置为 true,则还应当将 AllPaintingInWmPaint 设置为 true
      UseTextForAccessibility 指定该控件的 Text 属性的值,如果已设置,则可确定该控件的默认 Active Accessibility 名称和快捷键。

    展开全文
  • 缓存不知道如何下手... 网上找了一些例子,有很多不能用: private void Form1_Load(object sender, EventArgs e)//这里写这些 对不对呀?肿么感觉效果不明显啊 { this.SetStyle(ControlStyles....
  • winform双缓冲

    2017-05-07 16:57:00
    搜搜winform双缓冲,就会发现网络上有很多文章,乱七八糟说的不明不白。第一种方案:   SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景....

           搜搜winform的双缓冲,就会发现网络上有很多文章,乱七八糟说的不明不白。第一种方案:

       

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

      第二种方案:

      

    this.DouleBuffered=true
    

      第三种方案:

      Bitmap bimtBitmap = new Bitmap(width, height);
                Graphics g = Graphics.FromImage(bimtBitmap);
                //绘制区域
                g.Drawxxxx();
                g.DrawImage(bimtBitmap,this.ClientRectangle);
    

      当然还有其他,就是以上代码混杂着来,丝毫不清楚这些代码的具体含义,在此我解释一下,第一种方案=第二种方案=第三种方案+userPaint和AllPaintingInVmPaint设置为true。

         首先说明一下为什么闪烁?比如说你要画两条线,但是写的绘制算法复杂度比较高,导致中间过程较慢,就会导致先出了一条,后出了一条,但是你的目标是一下子出现两条,所以就闪烁了,类似以下代码。

        protected override void OnPaint(PaintEventArgs e)
            {
                base.OnPaint(e);
                Pen pen = new Pen(Color.Red);
                e.Graphics.DrawLine(pen,0,0,this.Width,this.Height);
                Thread.Sleep(500);
                e.Graphics.DrawLine(pen,10,0,this.Width,this.Height);
               Thread.Sleep(500);
    
            }
    

      这种问题怎么解决呢? 1,2,3方案都可以解决。试试就会发现,不用上述一二三方案,线条一条一条出,用了之后肯定是两条一起出,无闪烁。但是闪烁并不是说唯一这种原因发生的,发生绘制之前还会绘制背景的,假如说OnPaintBackground和OnPaint之间时间过长呢?  背景把颜色擦成控件色,你再画,之间时间过长照样闪烁,此时能解决问题的是1,2。第三种方案解决不了问题,想让第三种方案解决问题得加上第一种方案前两行。

           为什么会这样呢? 其实第三种方案是我们程序本身实现的双缓冲,但是假如OnPaintBackground和OnPaint之间时间过长,不论你在OnPaint里咋搞双缓冲,闪烁的是中间的间隔而已,解决不了问题。那1,2方案怎么就解决了?那我下边说明一下。看看第三种方案发生了什么。

          首先当我们不开双缓冲的时候,在Control类的WndProc函数中,当消息号是20时,发生背景擦除,具体代码反编译即可。

        

         这是一次完整的消息处理,之后会进行走OnPaint,消息号是15

      那么这两次函数之间的间隔就会导致闪烁,不过一般程序也看不出来,假如是这种闪烁,人工模拟的双缓冲是解决不了问题的,那么为什么说1,2是等价方式呢?当我们开启双缓冲之后,看下Control类内代码:

    protected virtual bool DoubleBuffered
        {
          get
          {
            return this.GetStyle(ControlStyles.OptimizedDoubleBuffer);
          }
          set
          {
            if (value == this.DoubleBuffered)
              return;
            if (value)
              this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, value);
            else
              this.SetStyle(ControlStyles.OptimizedDoubleBuffer, value);
          }
        }
    

      其实是开了AllPaintingInWmPaint ,这个是禁止背景擦除的,当我们设置这个为true之后,在上边的那个WmErasebkGnd函数中,是不会进行背景擦出的

     那背景就不绘制了吗?当然不是,此时先收到15号消息:

     

     进入这个函数之后:

     

    首先看到一个flag1,这个其实是判断是否双缓冲的,可以看出来它是由DoubuleBuffered属性或者后边的this.GetStyle(ControlStyles.AllPaintingInWmPaint) && this.DoubleBufferingEnabled;而DoubleBufferingEnabled是什么呢?看源码:

    所以flag1是DoubleBuffered属性|| UserPaint |DoubleBuffer|AllPaintingInWmPaint都为true的情况,所以我说1,2种两种方案其实是一致的,至于说1,2两种方案好于3的原因在于,1,2两种方案都禁止了擦除消息,然而在这个函数中是进行了背景绘制的,首先将Graphics保存起来,然后先画背景,再画Paint中代码,最后Render,是一次性绘制上去的,所以没有闪烁,而单纯用第三种方案,虽然自己实现了缓冲,然并卵,如果背景和前景时间过长照样闪烁,所以应该将ALLPaintInWmPaint设置了才能达到一样的效果。这个函数的具体相关代码如下:

      

    至于UserPaint还有那些属性,文档上也含糊不清,其实多看源码就懂了,UserPaint几乎都是true,它不是true,OnPaint函数都不会走,Control类的构造里其实将UserPaint和AllPaintingInWmPaint都设置为true了,子类控件会有更改。AllPaintingInWmPaint可以让控件消息处理忽略擦除背景消息,控件的douleBuffered属性设置和你直接设置那三个枚举到达的是一个效果。

     

    转载于:https://www.cnblogs.com/shiling/p/6821331.html

    展开全文
  • winform双缓冲绘图

    2019-11-18 20:01:54
    如果在使用双缓冲的过程中有一些疑问可以参考这个帖子https://bbs.csdn.net/topics/390673684/他的问题问的...很多人应该都熟悉win32的双缓冲,但是c#的却比较诡异。比如这段代码 //绘图完毕 都应该调用这段代码。...

    如果在使用双缓冲的过程中有一些疑问可以参考这个帖子https://bbs.csdn.net/topics/390673684/ 他的问题问的非常好,解决了我心中的一些疑惑。 另外写winform的gdi的代码可以参考一本书上的代码《GDI+图形程序设计》书中有一个项目GDIPainter

    很多人应该都熟悉win32的双缓冲,但是c#的却比较诡异。比如这段代码

    //绘图完毕 都应该调用这段代码。比如你绘制直线,你mousemove的时候是直接在显示器上绘制的,并没有绘制在位图

    上(win32里面可能叫兼容位图) ,你mouseup的时候才去真实绘制在内存里(位图或者说画布或者你的理解)的 ,

    在mouseup绘制在位图上之后调用下面的这个方法。

     private void RefreshFormBackground()
            {
                curBitmap = m_bitmap.Clone(  // 刚开始不太理解这里为什么要clone位图 new一个新内存出来 而不是引用
                  new Rectangle(0, 0, width, height), //那个贴里就说了 如果是同样的内存地址(同样的对象)那么无法触发界面的paint绘//制 事件 
                  m_bitmap.PixelFormat);
                m_parentWnd.BackgroundImage = curBitmap; // 必须创建一个新的对象
               //对backgroudImage赋新的对象 会导致界面刷新 调用OnPaint方法
            }

    //简单代码示意

     public void Form_Load()

    {

              //这几个SetStyle方法得添加上 使用winform的双缓存

               SetStyle(ControlStyles.UserPaint, true);
                SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 避免
                SetStyle(ControlStyles.DoubleBuffer, true);
     

                 m_bitmap = new Bitmap(width, height);            
                m_memGraphic = Graphics.FromImage(m_bitmap);
                m_memGraphic.Clear(this.BackColor); //用窗体的 背景色去清位图,假如之前有绘制线条那么会被擦除,如果后续还想显示需要再次调用绘制函数 然后RefreshFormBackground()方法 方可显示

    }

     

    //鼠标左键点击表示要开始实时绘制图元了,这里会设定一个标记 方便在mousemove中 做一些逻辑

    //真正的保存绘制是在mouseup中执行的 绘制到缓存(位图)上,然后将缓存(位图)设置窗口背景显示出来 

        private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

    {
          m_lineStart.X = e.X;
          m_lineStart.Y = e.Y;     
          isRuntimeDraw = true;
        }

    public void OnMouseMove(object sender, MouseEventArgs e)
            {
                if(isRuntimeDraw) // 这是一个标记 当鼠标点下的时候 设置一个标记  你需要监听mouseDown的消息
                {//我那边是鼠标右键触发的绘制开始,所以这里不列出来  这里挡一下避免额外的cpu开销
                    m_lineEnd.X = e.X;
                    m_lineEnd.Y = e.Y;              
                    this.Refresh(); // 触发onpaint 界面重绘 
                }
            }

    public void OnMouseMove(object sender, MouseEventArgs e)

    {

               if(isRuntimeDraw) // 和上面要一一对应 
                        {

                            isRuntimeDraw = false; //在onpaint方法中会判断这个标记  如果是false什么都不做 如果为true onpaint那边会直接在Graphic上绘制 图元

                            //这里是我自己的逻辑大概就是给2个按钮添加了一个“连接线” 并且调用Draw绘制这个连接线

    //                          //最后一定不忘 调用RefreshFormBackground()方法
                            m_connectLineManager.Add(LineStartEnd.Instance.StartNode.m_node,
                                LineStartEnd.Instance.EndNode.m_node);
                            m_connectLineManager.Draw(m_memGraphic, pen);
                            RefreshFormBackground(); 
                        }


    }

      public void OnPaint(object sender, PaintEventArgs e)
            {
                if(isRuntimeDraw)
                {
                    e.Graphics.DrawLine(pen, LineStartEnd.Instance.StartNode.m_node.PT
                        , m_lineEnd);
                }
            }

     

    可能我们要绘制的是树形结点之间的连线,使用gdi绘制的那种,每个节点对应了一个数据结构 ,连线也是一种数据结构,并且设计了一个管理类来管理。比如你的绘制是这样的

    //添加连接线 (选中的结点A和结点B之间 ) Add内部会做一些逻辑 比如设定他们的父子关系 构建连接线映射(2个map c#中叫Dictionary 称呼不同而已)。

    m_connectLineManager.Add(LineStartEnd.Instance.StartNode.m_node,
                                LineStartEnd.Instance.EndNode.m_node);

    //调用绘制线条函数 
                            m_connectLineManager.Draw(m_memGraphic, pen);

    如果你使用了删除 你就需要重新调用m_connectLineManager.Draw(m_memGraphic, pen); 这个方法绘制 ,不过切记你需要首先

    清理一下位图 使用 m_memGraphic.Clear(this.BackColor) 就可以做到。

    这整个流程不爽的地方在于RefreshFormBackground 有重新分配内存,如果这个做的比较频繁系统会越来越慢的,这是让人比较难过的地方。

    展开全文
  • C# Winform ListView 双缓冲开启

    千次阅读 2017-03-21 10:45:55
    class ListViewNF : System.Windows.Forms.ListView { public ListViewNF() { // 开启双缓冲 this.SetStyle(ControlStyles.OptimizedDoubleBuffer | Co
            class ListViewNF : System.Windows.Forms.ListView
            {
                public ListViewNF()
                {
                    // 开启双缓冲
                    this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
    
                    // Enable the OnNotifyMessage event so we get a chance to filter out 
                    // Windows messages before they get to the form's WndProc
                    this.SetStyle(ControlStyles.EnableNotifyMessage, true);
                }
    
                protected override void OnNotifyMessage(Message m)
                {
                    //Filter out the WM_ERASEBKGND message
                    if (m.Msg != 0x14)
                    {
                        base.OnNotifyMessage(m);
                    }
                }
            }


    使用ListView之前 声明下 然后替换掉就启用双缓冲了。


     private System.Windows.Forms.ListView listView1;  --->   private ListViewNF listView1;


    this.listView1 = new System.Windows.Forms.ListView();  --->   this.listView1 = new ListViewNF();

    展开全文
  • Winform中的双缓冲

    2018-12-05 14:51:02
    (1)在应用程序中使用双缓冲的最简便的方法是使用 .NET Framework 为窗体和控件提供的默认双缓冲。通过将 DoubleBuffered 属性设置为 true。 this.DoubleBuffered=true; (2)使用 SetStyle 方法可以为 Windows ...
  • //设置双缓冲,解决图片刷新闪烁问题 protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x02000000;//用双缓冲绘制窗口的所有子控件 return cp; ...
  • C# winform双缓冲画图

    2018-04-04 16:46:02
    画图都是从OnPaint中触发的: protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); DrawItems(e); } private void DrawItems(PaintEventArgs e) ...
  • 下面小编就为大家分享一篇.net WINFORM的GDI双缓冲的实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 窗体的构造函数中,开启窗体的双缓冲 public ssss() { //设置窗体的双缓冲 this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);...
  • 这个问题很影响人机交互的效果,最后通过一个大佬了解到了“双缓冲”技术,在大佬给的示例中我稍微修改了一下,现在分享给大家: 1、首先我重写了panel控件,项目(右键)–>添加新项–>自定义控件 2、添加...
  • 最近新做了一个项目,项目的界面好多的控件,然后在进入界面的时候会刷新好多次,而且每次操作都有不必要的刷新,研究发现了需要配置双缓冲才能避免闪屏,代码如下。 1 //获取当前系统的环境版本,不同的环境...
  • WinForm中的双缓冲技术

    2011-01-31 10:52:00
    关于WinForm中的双缓冲,是为了防止窗体呈现或刷新时的闪烁,平滑的为用户显示UI,从而曾强用户体验。 第一种,是WinForm自身去应用双缓冲模式。在窗体中的构造器中直接输入下面的代码 DoubleBuffered=true;//...
  • Winform中为窗口设置双缓冲

    千次阅读 2018-06-04 15:07:16
    双缓冲为了解决控件刷新时,闪烁的问题。请在构造函数里面底下加上如下几行:[csharp] view plain copySetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); // ...
  • 1. 修改DoubleBuffered属性 ...通过开启二级缓冲可以有效解决这个问题: 利用反射机制修改TableLayoutPanel的Protected的DoubleBuffered属性 tableLayout.GetType().GetProperty("DoubleBuffered", System...
  • 有时候在窗体中执行不断的GDI+操作的时候会出现闪速的状况,除了修改窗体的参数,更应该解决刷新本身的问题,双缓冲可能就是这样来的。 方法1: 用GDI绘制在位图上,然后再重新生成位图 Bitmap bt = new ...
  • private  void  button1_Click( ... //最后就是我们手动双缓冲技术的 最后一步了,就是将内存中的bmp的图像一次性的展示到窗口中的picturebox中 } 转载于:https://www.cnblogs.com/jmy9/p/10782266.html
  • 再次记录双缓冲,是因为之前理解得不透彻。前段时间项目又得用到,而对BufferedGraphics不熟,又再鄙视自已无耻一次。再次记录,希望以后能随手用上撒。。 双缓冲其实没啥,就是因为刷屏造成了闪烁,而闪烁的原因有...
  • WinFormListBox控件实现自绘制,双缓冲,实现方法,特别是解决了横向滚动时的绘制问题,解决更新时闪动的问题。
  • C#_Winform中使用GDI+及双缓冲技术绘制正弦波形图,移动正弦波形,实时截图,暂停、开始、停止功能。
  • ListView 中的DoubleBuffered 属性是 protected 的,外部不能直接修改,但实际使用中,我们一般都需要开启双缓冲来避免控件闪烁。 网上很多人都是通过自定义 ListView 来实现的,虽然也不复杂,但其实用反射是更...
  • Control.SetStyle(ControlStyles ,bool) 控件样式位标志用于对支持的行为进行分类。控件可以通过调用 SetStyle 方法并传入适当的 ControlStyles 位以及设置该位的 Boolean 值来启用样式。若要确定分配给指定的 ...
  • 一 引子 为了让更多的编程初学者,轻松愉快地掌握面向对象的思考...二 本节内容---画墙(砖块集合)以及双缓冲实现 1.界面截图如下: 三 砖块类设计 砖块类的定义代码和之前的挡板类差不多,代码如下: 1 ...

空空如也

空空如也

1 2 3 4 5 6
收藏数 117
精华内容 46
关键字:

winform双缓冲