2012-06-08 69 views
0

由於篇幅較短且易於理解,我將首先發布我的代碼,然後我會問我的問題。如何在自定義控件中使用Control.Update方法

public class BatteryLabel : Control 
{ 
    private Color _captionColor = SystemColors.Control; 
    private Color _textColor = SystemColors.Info; 
    private Color _failColor = Color.Red; 
    private Color _passColor = Color.Green; 
    private string _caption; 
    string text2; 
    string text3; 
    bool battery1Fail = false; 
    bool battery2Fail = false; 
    bool battery3Fail = false; 

    public BatteryLabel() 
    { 

    } 

    public Color BackgroundTextColor 
    { 
     get{ return _textColor;} 
     set{_textColor = value; Invalidate();} 
    } 

    public string Caption 
    { 
     get 
     { 
      return _caption; 
     } 
     set 
     { 
      _caption = value; 
      Invalidate(); 
     } 
    } 

    public override string Text 
    { 
     get 
     { 
      return base.Text; 
     } 
     set 
     { 
      base.Text = value; 
      Invalidate(); 
     } 
    } 

    public string Text2 
    { 
     get { return text2; } 
     set { text2 = value; Invalidate(); } 
    } 

    public string Text3 
    { 
     get { return text3; } 
     set { text3 = value; Invalidate(); } 
    } 

    public bool Battery1Fail 
    { 
     get { return battery1Fail; } 
     set { battery1Fail = value; Invalidate(); } 
    } 

    public bool Battery2Fail 
    { 
     get { return battery2Fail; } 
     set { battery2Fail = value; Invalidate(); } 
    } 

    public bool Battery3Fail 
    { 
     get { return battery3Fail; } 
     set { battery3Fail = value; Invalidate(); } 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     base.OnPaint(e); 

     e.Graphics.DrawRectangle(Pens.Black, 0,0, Width-1, Height-1); 

     var x1 = 50; 
     var x2 = 98; 
     var x3 = 146; 
     var color1 = battery1Fail?_failColor:BackgroundTextColor; 
     var color2 = battery2Fail?_failColor:BackgroundTextColor; 
     var color3 = battery3Fail?_failColor:BackgroundTextColor; 

     e.Graphics.FillRectangle(new SolidBrush(color1),x1+1, 1, 47, Height-2); 
     e.Graphics.FillRectangle(new SolidBrush(color2),x2+1, 1, 47, Height-2); 
     e.Graphics.FillRectangle(new SolidBrush(color3),x3+1, 1, 47, Height-2); 

     e.Graphics.DrawLine(Pens.Black, x1,0, x1, Height-1); 
     e.Graphics.DrawLine(Pens.Black, x2,0, x2, Height-1); 
     e.Graphics.DrawLine(Pens.Black, x3,0, x3, Height-1); 

     var BoldFont = new Font(this.Font, FontStyle.Bold); 

     e.Graphics.DrawString(Caption, BoldFont, new SolidBrush(ForeColor), 0,0); 
     e.Graphics.DrawString(Text, this.Font, new SolidBrush(ForeColor), x1,0); 
     e.Graphics.DrawString(Text2, this.Font, new SolidBrush(ForeColor), x2,0); 
     e.Graphics.DrawString(Text3, this.Font, new SolidBrush(ForeColor), x3,0); 

    } 
} 

如果您決定嘗試使用它,控件大小應該是195,14。我有8個這樣的面板,它是在一個1.6Ghz原子處理器上運行的200,200。它用於顯示計算機上最多3個電池的數值。標籤每500ms刷新一次。正如你可能聚集的那樣,有一點點閃爍,但它是可以忍受的。如果可能,我只想更少。所以我開始研究使用Update,並移動我的一些代碼(比如背景位),我想也許我應該將它移動到OnPaintBackground(),但是在構建Update方法的測試框架中不會更改任何內容,並且當我使用Invalidate方法時,它同時運行OnPaintBackground和OnPaint。這是我在這種情況下所嘗試的。

public class InformationLabel : Control 
{ 
    Random r = new Random(); 
    protected override void OnPaintBackground(PaintEventArgs e) 
    { 
     base.OnPaintBackground(e); 
     Color randomCOlor = Color.FromArgb(r.Next()); 
     e.Graphics.FillRectangle(new SolidBrush(randomCOlor),0,0, Width-1, Height-1); 
    } 
    protected override void OnPaint(PaintEventArgs e) 
    { 
     base.OnPaint(e); 
     Color randomCOlor = Color.FromArgb(r.Next()); 
     e.Graphics.FillPie(new SolidBrush(randomCOlor),15,15,15,15, 0.0f, 120.0f); 
    } 
} 

public partial class MainForm : Form 
{ 
    public MainForm() 
    { 
     InitializeComponent(); 
    } 

    void Button1Click(object sender, EventArgs e) 
    { 
     informationLabel1.Update(); 
    } 

    void Button2Click(object sender, EventArgs e) 
    { 
     informationLabel1.Invalidate(); 
    } 
} 

我做了一個usercontrol約300,300,所以我可以肯定我所看到的。我忘了提及在我的500毫秒計時器的電池控制中,我只是更新文本,text2和text3。我在想,如果該文本的價值超出規格,我會設置電池失效標誌,然後無效..但我不知道。那麼我應該如何去更新文本?

回答

2

我相信你正在尋找錯誤的地方消除閃爍。我可以使用您的BatteryLabel基本上只用一行來無閃爍地更新文本。改變你的構造函數是這樣的:

public BatteryLabel() 
{ 
    this.SetStyle(ControlStyles.OptimizedDoubleBuffer,true); 
} 

這告訴控制提供雙重緩衝其圖形,這使得閃爍消失。

要使用100毫秒刷新間隔測試:

Timer t; 
public Form1() 
{ 
    InitializeComponent(); 

    t = new Timer(); 
    t.Interval = 100; 
    t.Tick += new EventHandler(t_Tick); 
    t.Start(); 
} 

void t_Tick(object sender, EventArgs e) 
{ 
    string ticks = DateTime.Now.Ticks.ToString(); 
    string ticks1 = ticks.Substring(ticks.Length-4), 
     ticks2 = ticks.Substring(ticks.Length - 5,4), 
     ticks3 = ticks.Substring(ticks.Length - 6,4); 

    batteryLabel1.Text = ticks1; 
    batteryLabel1.Text2 = ticks2; 
    batteryLabel1.Text3 = ticks3; 
    batteryLabel1.Battery1Fail = ticks1.StartsWith("1"); 
    batteryLabel1.Battery2Fail = ticks2.StartsWith("1"); 
    batteryLabel1.Battery3Fail = ticks3.StartsWith("1"); 
} 

這是否幫助,或者有我誤解你了?

+0

@Tergiver下面給出了基本相同的解決方案,但增加了一些可能會提高操作效率的附加標誌。不是一個壞主意,因爲你實際上在做你自己的繪畫。你會發現,如果你只用最小的ControlStyles.OptimizedDoubleBuffer來嘗試它,即使刷新率比你實際使用的刷新率高得多,但是沒有理由不設置其他標誌。 –

+0

好吧,我現在有家庭,所以我無法測試它。但是當我這樣做,我會讓你知道。這看起來很有希望。 –

3

您可以通過添加在你的構造這條線擺脫閃爍:

SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint, true); 

現在,油漆背景和在您的油漆處理一切。

優化可以通過只爲需要重新繪製的區域傳遞一個Rectangle來使Invalidate完成。然後在你的OnPaint覆蓋中,使用e.ClipRectangle來確定要繪製的內容。對於這樣簡單的繪圖來說,這可能不是必需的。

相關問題