0

短くて理解しやすいので、最初にコードを投稿してから、質問します。

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 に設定されています。1.6Ghz アトム プロセッサで実行されている 200,200 のパネルに、これらのうちの 8 つがあります。コンピューターで最大 3 つのバッテリーの値を表示するために使用されます。ラベルは 500 ミリ秒ごとに更新されます。あなたが収集したかもしれないように、少しちらつきがありますが、許容範囲です. できればもっと少なくしたい。そこで私は 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();
    }
}

私はその1つのユーザーコントロールを約300,300にしたので、私が見ているものを確信することができました. 500ms タイマーのバッテリー制御で、テキスト、テキスト 2、およびテキスト 3 を更新したことを忘れていました。そのテキストの値が仕様から外れている場合は、バッテリー障害フラグを設定してから無効にすることを考えています..しかし、よくわかりません。では、テキストのみを更新するにはどうすればよいですか???

4

2 に答える 2

3

コンストラクターに次の行を追加することで、ちらつきを取り除くことができます。

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

ここで、ペイント ハンドラーで背景とその他すべてをペイントします。

Rectangle を Invalidate に渡して、再描画が必要な領域のみを最適化できます。次に、OnPaint オーバーライドで e.ClipRectangle を使用して、何を描画するかを決定します。これはおそらく、このような単純な図面には必要ありません。

于 2012-06-08T21:04:16.503 に答える
2

ちらつきをなくすために間違った場所を見ていると思います。あなたを使用してBatteryLabel、基本的に1行でテキストのちらつきのない更新を取得できます。コンストラクターを次のように変更します。

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");
}

これは役に立ちますか、それとも私はあなたを誤解していますか?

于 2012-06-08T21:03:50.547 に答える