4

これは 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");

また、正しく描画されたアイテム (選択されたアイテム) は、フォームのサイズ変更時にちらつきます。大したことではありませんが、誰かが理由を知っていれば.... tnx

4

2 に答える 2

5

次のコードをResizeイベントに入れます。

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

「Whatever」をプロジェクトで使用する名前空間に置き換えるか、より便利なものにします。コンパイル後、フォームデザイナにDBListBoxを追加できるようになります。

于 2010-07-18T09:02:50.247 に答える
5

問題を再現します。コードにはいくつかの間違いがあります。フォント名は「Arial」です。rect.Width を調整しないでください。フォント、ブラシ、および領域で Dispose() を呼び出すのを忘れています。しかし、彼らはその行動を説明していません。クリッピング領域に問題があり、テキストが適切に更新されません。それがどこで発生するのかわかりません。Graphics オブジェクトの状態は問題ありません。

Graphics.DrawString() は非常に問題のあるメソッドです。本当に避けるべきです。ListBox を含むすべての Windows フォーム コントロールは、TextRenderer.DrawText() を使用します。これを使うと問題が解決します。測定がより難しいことはわかっていますが、固定オフセットで IP アドレスを表示することで回避できます。見栄えも良く、そのように列に並んでいます。

e.DrawBackground() を使用しているため、ちらつきます。これにより、既存のテキストが消去され、その上にテキストが再び描画されます。ダブルバッファリングでそれが修正されるとは思いません。アイテム全体を描画する必要があるため、背景を描画する必要はありません。大きなフォントでテキストの正確なサイズを取得できない場合は注意が必要です。回避策は、最初にビットマップに描画することです。

于 2010-07-18T17:20:52.737 に答える