五月综合缴情婷婷六月,色94色欧美sute亚洲线路二,日韩制服国产精品一区,色噜噜一区二区三区,香港三级午夜理伦三级三

您現(xiàn)在的位置: 365建站網(wǎng) > 365文章 > 解決C#/vb.net winform中的panel重繪導(dǎo)致界面閃爍問題

解決C#/vb.net winform中的panel重繪導(dǎo)致界面閃爍問題

文章來(lái)源:365jz.com     點(diǎn)擊數(shù):3751    更新時(shí)間:2018-06-22 21:07   參與評(píng)論

首先我們需要重新創(chuàng)建一個(gè)Panel類,其繼承系統(tǒng)自帶的Panel類,然后充新寫一個(gè)構(gòu)造函數(shù),對(duì)其中的部分樣式進(jìn)行更改。

代碼:


public class NewPanel:Panel  
{  
    public NewPanel()  
    {  
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);  
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);  
        this.SetStyle(ControlStyles.UserPaint, true);  
    }  
}

  


然后在窗口初始化的代碼塊中更改為我們當(dāng)前新建的Panel類即可,其它代碼都不必用~。

個(gè)人認(rèn)為是非常棒的一種解決方案,可以完全解決閃爍的問題。


利用winform開發(fā)時(shí),可能都會(huì)遇到一個(gè)問題,就是在panel中不停的重繪圖形時(shí),圖形會(huì)不停的閃爍。要解決這個(gè)辦法只需要開啟雙緩沖即可,由于初學(xué)c#,理解的不是很深,所以不多做解釋。以下代碼親測(cè)可以解決這個(gè)問題:

首先創(chuàng)建一個(gè)自己的panel類:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Windows.Forms;  
   
namespace Test  
{  
    //開啟雙緩沖  
    class MyPanel:Panel  
    {  
        public MyPanel()  
        {  
            SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, true);  
        }  
    }  
}

  


然后重新生成解決方法,就會(huì)發(fā)現(xiàn)工具箱中多了一個(gè)自己寫的panel控件,在畫圖形的時(shí)候,畫在自己的panel上就可以了。由于自己的panel繼承自Panel類,所以Panel中的方法都可以使用。


vb.net版本:

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Namespace Test
    
    '開啟雙緩沖   
    Class MyPanel
        Inherits Panel
        
        Public Sub New()
            MyBase.New
            SetStyle((ControlStyles.UserPaint  _
                            Or (ControlStyles.AllPaintingInWmPaint  _
                            Or (ControlStyles.OptimizedDoubleBuffer  _
                            Or (ControlStyles.ResizeRedraw Or ControlStyles.SupportsTransparentBackColor)))), true)
        End Sub
    End Class
End Namespace


另外技術(shù)文章說(shuō)明:


一、通過(guò)對(duì)窗體和控件使用雙緩沖來(lái)減少圖形閃爍(當(dāng)繪制圖片時(shí)出現(xiàn)閃爍時(shí),使用雙緩沖)

對(duì)于大多數(shù)應(yīng)用程序,.NET Framework 提供的默認(rèn)雙緩沖將提供最佳效果。默認(rèn)情況下,標(biāo)準(zhǔn) Windows 窗體控件是雙緩沖的。可以通過(guò)兩種方法對(duì)窗體和所創(chuàng)作的控件啟用默認(rèn)雙緩沖。一種方法是將 DoubleBuffered 屬性設(shè)置為 true,另一種方法是通過(guò)調(diào)用 SetStyle 方法將 OptimizedDoubleBuffer 標(biāo)志設(shè)置為 true。兩種方法都將為窗體或控件啟用默認(rèn)雙緩沖并提供無(wú)閃爍的圖形呈現(xiàn)。建議僅對(duì)已為其編寫所有呈現(xiàn)代碼的自定義控件調(diào)用 SetStyle 方法。

在構(gòu)造函數(shù)里加上以下代碼:

this.DoubleBuffered = true;//設(shè)置本窗體
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
SetStyle(ControlStyles.DoubleBuffer, true); // 雙緩沖
//SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
//UpdateStyles();

 

二、C#控件的閃爍問題解決方法總結(jié)
最近對(duì)代碼作了一些優(yōu)化,試驗(yàn)后效果還可以,但是發(fā)現(xiàn)界面會(huì)閃爍,具體是TreeView控件會(huì)閃爍,語(yǔ)言為C#,IDE為VS2005。在查閱一些資料,使用了一些基本技術(shù)后(如開啟雙緩沖),發(fā)現(xiàn)沒什么效果。
        于是使用Profiler工具,查找出瓶頸在于每次更新完界面的EndUpdate操作(使用這個(gè)是為了減少界面更新次數(shù),但這里不理想是因?yàn)榭丶兄械脑睾芏啵孪氪蟾琶看胃拢?Net底層都會(huì)更新重繪每個(gè)圖元,所以速度會(huì)慢,造成閃爍。但是如果這樣,使用雙緩沖應(yīng)該會(huì)有較好效果。再看代碼,發(fā)現(xiàn)可能是更新動(dòng)作太過(guò)頻繁,于是降低速度,有所好轉(zhuǎn),但還是不行。
       繼續(xù)在網(wǎng)上查閱,最終找到一個(gè)方案比較合適。原來(lái)底層重繪每次會(huì)清除畫布,然后再全部重新繪制,這才是導(dǎo)致閃爍最主要的原因。于是重載消息發(fā)送函數(shù)操作,禁掉這條消息。代碼如下:

protected override void WndProc(ref Message m)
 {
     if (m.Msg == 0x0014) // 禁掉清除背景消息
        return;
     base.WndProc(ref m);
 }

  

成功!

 

注:雙緩沖還是有用的,在更新不是很頻繁且控件內(nèi)含元素不是特別多的時(shí)候。一旦元素過(guò)多,每次更新時(shí)間都比較長(zhǎng),即便使用了雙緩沖,仍解決不了閃爍問題。個(gè)人認(rèn)為最終比較理想的方法還是禁掉清除背景消息。


附:一些嘗試過(guò)但失敗的記錄
1)使用setStyle
      網(wǎng)上有說(shuō)使用setStyle函數(shù)去設(shè)置該控件的參數(shù),具體為:
      SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
      這三個(gè)選項(xiàng)參數(shù)后者是依賴前者的,必須并存,否則無(wú)效。并且這個(gè)函數(shù)本身是protected的,所以首先需要繼承某控件再使用。
      這個(gè)目標(biāo)是跟前面正確解決方案一致,也是禁止清除背景并開啟雙緩沖,但需要使用用戶繪制選項(xiàng),而且是全部交由用戶繪制。這需要自己實(shí)現(xiàn)控件的全部繪制,比較麻煩。所以這個(gè)方法不是完全不可行,但是需要額外工作量,不推薦。我也沒有使用。


2)使用BeginUpdate和EndUpdate
      這一對(duì)操作對(duì)于需要批量操作更新控件的情景有比較好的效果,比如初始化時(shí)批量添加了大量節(jié)點(diǎn)。壞處就在于不能即時(shí)更新。所以,對(duì)于頻繁的更新節(jié)點(diǎn)并希望立即反映到界面的情況不適用。如果使用并且沒有禁掉清除界面消息的話,則控件看起來(lái)就會(huì)不停的閃爍,而且以白底為主,內(nèi)容幾乎不可見(這個(gè)視頻繁程度而定)。因?yàn)榻缑娓露荚贓ndUpdate處完成,操作太多導(dǎo)致EndUpdate阻塞時(shí)間過(guò)長(zhǎng),且清空在先,更新在后,導(dǎo)致界面看起來(lái)長(zhǎng)時(shí)間處于空白狀態(tài)。


3)使用ControlStyles.EnableNotifyMessage選項(xiàng)
      這個(gè)選項(xiàng)的作用和正確解決方案也是一致的。使用方法是:
      SetStyle(ControlStyles.EnableNotifyMessage, true);
      protected override void onNotifyMessage(Message m)
      {
               // 此處書寫過(guò)濾消息代碼
      }
      但是實(shí)際實(shí)驗(yàn)顯示無(wú)效果,不知是什么原因,沒有細(xì)究。

 

三、個(gè)人在一個(gè)winfrom中測(cè)試?yán)胻imer控件對(duì)要刷新的控件進(jìn)行定時(shí)刷新,可能也能起到作用。

 

四、C# winform 局部刷新
做winform界面程序時(shí),經(jīng)常會(huì)遇到后臺(tái)處理占用大量時(shí)間的情況,這就會(huì)造成界面假死狀態(tài)。一般解決界面假死有兩種方式:要么把占用大量時(shí)間的處理方式放入其他線程;要么把界面顯示放入其他線程。第一種方式應(yīng)該比較簡(jiǎn)單,開單獨(dú)的線程,處理數(shù)據(jù),將處理數(shù)據(jù)顯示到界面就好。但是我們經(jīng)常需要在主程序運(yùn)算一些內(nèi)容,否則可能會(huì)改動(dòng)比較大。因此,這里講講第二種方式。
同樣是使用多線程,但是c#在其他線程刷新有一點(diǎn)點(diǎn)問題,即不能跨線程操作界面。這可以使用控件的Invoke方法解決:

private delegate void CrossThread();
 Control control = ....;
 CrossThread cross = delegate()
 {
      control.Refresh();
 };
 control.Invoke(cross);

這樣可以讓控件在其它線程刷新界面。


再加上開新線程后的通用方法:

 private void InvaliateControl(Control control)
  {
      Thread t = new Thread(
          new ThreadStart(delegate()
          {
              CrossThread cross = delegate()
              {
                  control.Refresh();
              };
             control.Invoke(cross);
         }
     ));
 }

這樣就可以在任何時(shí)候,調(diào)用此方法對(duì)控件進(jìn)行刷新,而不將整個(gè)界面刷新。如果對(duì)于同一個(gè)控件,連續(xù)多次刷新,可以添加一個(gè)成員變量作為標(biāo)記,以免同一控件連續(xù)多次刷新,提升部分性能。


補(bǔ)充:在主線程調(diào)用耗時(shí)操作用此方法可能會(huì)有問題,經(jīng)過(guò)驗(yàn)證調(diào)用Invoke函數(shù),其實(shí)是在主線程刷新界面。



如對(duì)本文有疑問,請(qǐng)?zhí)峤坏浇涣髡搲瑥V大熱心網(wǎng)友會(huì)為你解答??! 點(diǎn)擊進(jìn)入論壇

發(fā)表評(píng)論 (3751人查看,0條評(píng)論)
請(qǐng)自覺遵守互聯(lián)網(wǎng)相關(guān)的政策法規(guī),嚴(yán)禁發(fā)布色情、暴力、反動(dòng)的言論。
昵稱:
最新評(píng)論
------分隔線----------------------------

其它欄目

· 建站教程
· 365學(xué)習(xí)

業(yè)務(wù)咨詢

· 技術(shù)支持
· 服務(wù)時(shí)間:9:00-18:00
365建站網(wǎng)二維碼

Powered by 365建站網(wǎng) RSS地圖 HTML地圖

copyright © 2013-2024 版權(quán)所有 鄂ICP備17013400號(hào)