ListBox - 未選択のアイテムのDrawItemの上書きは再描画されません
-
17-09-2020 - |
質問
これはC#デスクトップアプリケーションです。My DrawStyle
のListBox
プロパティはOwnerDrawFixed
に設定されています。
問題: DrawItemを上書きさせると、さまざまなフォントでテキストを描画し、機能します。しかし、実行時にフォームのサイズ変更を開始すると、選択したアイテムが正しく描画されますが、それらの残りの部分は再描画されず、テキストが選択されていないアイテムのために破損しているテキストが発生します。
これが私のコードです:
private void listDevices_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
string textDevice = ((ListBox)sender).Items[e.Index].ToString();
e.Graphics.DrawString(textDevice,
new Font("Ariel", 15, FontStyle.Bold), new SolidBrush(Color.Black),
e.Bounds, StringFormat.GenericDefault);
// Figure out where to draw IP
StringFormat copy = new StringFormat(
StringFormatFlags.NoWrap |
StringFormatFlags.MeasureTrailingSpaces
);
copy.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(0, textDevice.Length)});
Region[] regions = e.Graphics.MeasureCharacterRanges(
textDevice, new Font("Ariel", 15, FontStyle.Bold), e.Bounds, copy);
int width = (int)(regions[0].GetBounds(e.Graphics).Width);
Rectangle rect = e.Bounds;
rect.X += width;
rect.Width -= width;
// draw IP
e.Graphics.DrawString(" 255.255.255.255",
new Font("Courier New", 10), new SolidBrush(Color.DarkBlue),
rect, copy);
e.DrawFocusRectangle();
}
listDevices.Items.Add("Device001");
listDevices.Items.Add("Device002");
.
また、正しく描画されている項目(選択された1つ)はフォームのサイズ変更にちらつきです。Biggieはありませんが、誰かが理由を知っていれば...... tnx
解決
リサイズイベントに次のコードを入れる:
private void listDevices_Resize(object sender, EventArgs e) {
listDevices.Invalidate();
}
.
これはすべて再描画されるようにするべきです。
ちらつきを止めるには、二重バッファリングが必要です。
これを行うには、ListBoxから派生した新しいクラスを作成し、コンストラクタに次のようにします。
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
.
またはこれをコードファイルに貼り付けるだけです。
using System.Windows.Forms;
namespace Whatever {
public class DBListBox : ListBox {
public DBListBox(): base() {
this.DoubleBuffered = true;
// OR
// this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
}
}
}
.
プロジェクトのネームスペースを使用して「何でも置き換えるか、またはそれをより便利にしてください。コンパイル後、フォームデザイナにDBListBoxを追加できるはずです。
他のヒント
問題を再現します。コードにはいくつかの間違いがあり、フォント名は「arial」で、rect.widthを調整しないでください。フォント、ブラシ、地域でdispose()を呼び出すのを忘れます。しかし、彼らは行動を説明していません。クリッピング領域が正しく更新されないようにするクリッピング領域に問題があります。それが発生したのかわかりません、グラフィックスオブジェクトの状態は問題ありません。
graphics.drawString()は非常に問題のある方法です、あなたは本当にそれを避けるべきです。 ListBoxを含むすべてのWindowsフォームコントロール、Textrenderer.DrawText()を使用します。それを使うときに問題を解決します。私は測定がより難しいことを知っています、あなたはIPアドレスを固定オフセットで表示することによってそれを回避することができます。もっと良く見えます、彼らはそのように列に並んでいます。
e.drawbackground()を使用するため、ちらつきます。既存のテキストを消去すると、そのテキストを右に戻します。ダブルバッファリングが修正されているとは思わないことは、背景を描く必要がないようにアイテム全体を描く必要があります。トリッキーなフォントでテキストの正確なサイズを取得できない場合、回避策は最初にビットマップに描画されます。