2009-10-11 18 views
7

私のWinFormsアプリケーションには、ログファイルとして使用しているTextBoxがあります。私はTextBox.AppendText(string);を使用してフォームを点滅させずにテキストを追加していますが、(コントロールの.Textプロパティが.MaxLengthの制限に達すると)古いテキストを消去しようとすると、ひどいちらつきが発生します。次のように更新中にTextBoxフリッカーを停止する

私が使用しているコードは次のとおりです。

public static void AddTextToConsoleThreadSafe(TextBox textBox, string text) 
{ 
    if (textBox.InvokeRequired) 
    { 
     textBox.Invoke(new AddTextToConsoleThreadSafeDelegate(AddTextToConsoleThreadSafe), new object[] { textBox, text }); 
    } 
    else 
    { 
     // Ensure that text is purged from the top of the textbox 
     // if the amount of text in the box is approaching the 
     // MaxLength property of the control 

     if (textBox.Text.Length + text.Length > textBox.MaxLength) 
     { 
      int cr = textBox.Text.IndexOf("\r\n"); 
      if (cr > 0) 
      { 
       textBox.Select(0, cr + 1); 
       textBox.SelectedText = string.Empty; 
      } 
      else 
      { 
       textBox.Select(0, text.Length); 
      } 
     } 


     // Append the new text, move the caret to the end of the 
     // text, and ensure the textbox is scrolled to the bottom 

     textBox.AppendText(text); 
     textBox.SelectionStart = textBox.Text.Length; 
     textBox.ScrollToCaret(); 
    } 
} 

はちらつきが発生しないコントロールの上部からテキストの行をパージする滑らかな印象方法はありますか?テキストボックスには、ListViewにはBeginUpdate()/ EndUpdate()メソッドがありません。

TextBoxコントロールはコンソールログに最適なコントロールですか?

編集:TextBoxのちらつきは、コントロールの上部にあるテキストをパージしている間に、テキストボックスがスクロールしているように見えますが、すぐにスクロールして下部にスクロールします。 - それはすべて非常に迅速に起こるので、私はちょうど繰り返し点滅を参照してください。

また、私はちょうどthis questionを見てきましたが、提案はListBoxを使用することでしたが、(ほとんどの場合)ListBoxのテキストを受け取っているので、一度に1文字。

+1

"if"を "while"に変更したい場合があります。新しいテキストをTextBoxに収めるにはテキストの最初の行を削除するだけでは不十分です。 –

+0

いいえ、よく見られるノアム。ありがとう。 – Bryan

+2

この投稿はこれに関するさらに詳しい情報があります - http://stackoverflow.com/questions/1333393/how-to-prevent-a-windows-forms-textbox-from-flickering-on-resize –

答えて

2

問題は、一度に1文字を繰り返してすばやく追加(削除)することです。 1つの解決策は、文字が追加されるときに文字をバッファリングし、文字の量に関係なく、例えば250ミリ秒ごとにテキストボックスをより大きな間隔で更新することである。

これが必要になります。

  • を彼らが実際に保存されている文字でアップデートを行うと、デリゲートを呼び出しますタイマーを持っている
  • を追加されます文字の配列またはスタックを持っていますスタック

もう1つの方法は、最初に何が起きても250msと100文字の両方を使用することです。しかし、これは実際にはっきりとした利益を得ることなく、コードをもっと複雑にするでしょう。

+0

ちらつきの割合を上げるだけではないでしょうか? – Bryan

+0

それは私に良い解決策が見つかるまで私が使用できるアイディアを私に与えました。コントロールがいっぱいになると、私はコンテンツの約20%をパージします(20%落とすことができますが、正しく動作させることができます)。この方法では、コントロールが一杯になったときにちらつきが絶えず見えるのではなく、ちらつきが1秒に数回ではなく1時間に1回しか発生しないため、目立たないでしょう。 – Bryan

+0

期間はあまり考えなかった、私は認めなければならない:) –

3

メインウィンドウでダブルバッファリングを設定しましたか?

このコードは、InitializeComponent呼び出しの後にコンストラクタでダブルバッファリングを追加し、おそらくフリッカーを減らします。

this.SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer,true);

+0

私はこれを試しましたが、残念ながらそれは何の違いもありません。 – Bryan

+0

これは役に立ちません。 TextBoxは本質的にちらつきがあり、あなたが望むことができるものはそれを減らすことです。 http://stackoverflow.com/questions/1333393/how-to-prevent-a-windows-forms-textbox-from-flickering-on-resize –

2

あなたはすべての周りSuspendLayout()/ ResumeLayout()あなたの更新操作を試してみましたか?

また、テキストボックスでClear()を呼び出して、切り捨てられたテキストを再割り当てすることもできます。

ログファイルビューアを実装しようとすると、代わりにListBoxを使用できます。

+0

私はダブルバッファリングとSuspendLayout()/ ResumeLayout()を試しましたが、残念ながら何の違いもないようです。 私はListBoxの使用について質問を更新しました。私は(通常)一度に1文字ずつ追加するという事実のために動作するかどうかはわかりません。 – Bryan

+0

リストボックスの最後の項目を更新して文字を追加することができます。行がいっぱいであれば、新しいListBox項目を追加できます。 – codymanix

+0

SuspendLayout()/ ResumeLayout()に操作の* all *を含めましたか?ScrollToCaret呼び出しを含めましたか? – codymanix

1

SelectedText = textを使用すると、ちらつきが劇的に減少することがわかりました。非常に速いアップデートでは、フリッカーは新しいテキストのみにローカライズされ、スクロールバーから奇妙な動作を得ることはありません。あなたはまた、テキストは、以前に書かれた上書きするこれを使用することができ

void UpdateTextBox(string message) 
{ 
    myTextBox.SelectionStart = myTextBox.Text.Length; 
    myTextBox.SelectedText = message; 
} 

- あなたはカウンタを更新するために必要な、あるいは、例えば割合をダウンロードと同じように:

それ以外
void UpdateTextBox(string message, int jumpBack) 
{ 
    myTextBox.SelectionStart = Math.Max(myTextBox.Text.Length - jumpBack, 0); 
    myTextBox.SelectionLength = jumpBack; 
    myTextBox.SelectedText = message; 
} 

に存在していないようです.NET TextBoxのフリッカーを減らす簡単な方法です。

10

私はインターネット上で探して解決策を見つけた:

[System.Runtime.InteropServices.DllImport("user32.dll")] 

    public static extern bool LockWindowUpdate(IntPtr hWndLock); 

    internal void FillTB(TextBox tb, string mes) 
    { 
     try 
     { 
      LockWindowUpdate(tb.Handle); 

      // Do your thingies with TextBox tb 
     } 
     finally 
     { 
      LockWindowUpdate(IntPtr.Zero); 
     } 
    } 
+0

ありがとう、私のためにも働いています - 実際に私はmkajの拡張子を使用 –

9

Mathijsの答えは私のための作品です。だから、すべてを行う必要がある

namespace System.Windows.Forms 
{ 
    public static class ControlExtensions 
    { 
     [System.Runtime.InteropServices.DllImport("user32.dll")] 
     public static extern bool LockWindowUpdate(IntPtr hWndLock); 

     public static void Suspend(this Control control) 
     { 
      LockWindowUpdate(control.Handle); 
     } 

     public static void Resume(this Control control) 
     { 
      LockWindowUpdate(IntPtr.Zero); 
     } 

    } 
} 

myTextBox.Suspend(); 
// do something here. 
myTextBox.Resume(); 

がうまく動作制御の拡張 - 私はすべてのコントロールで使用できるように、私は少しそれを変更しました。すべてのちらつきが止まります。

+0

ありがとう、私のためにも働く –

+0

FYI、これは '/ /ここで何か 'がリサイズイベントであるとうまくいきません。 – Dan

関連する問題