0

継承されたリストビューがあり、列ヘッダーをクリックするとかなりちらつきます。リストは詳細ビューにあります。

    public ListViewEx()
    {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
        this.DoubleBuffered = true;
    }

    int sortColumn = -1;
    protected override void OnColumnClick(ColumnClickEventArgs e)
    {
        if(e.Column != sortColumn)
        {
            sortColumn = e.Column;
            this.Sorting = SortOrder.Ascending;
        }
        else
        {
            if(this.Sorting == SortOrder.Ascending)
                this.Sorting = SortOrder.Descending;
            else
                this.Sorting = SortOrder.Ascending;
        }
        this.Sort();
    }

リストにデータを入力してもちらつきはありません。

        for(int i = 0; i < 10; i++)
        {
            ListViewItem lvi = new ListViewItem("this is column 1 " +i);
            lvi.SubItems.Add("...
            lvi.SubItems.Add("...
            lvi.SubItems.Add("...
            lvi.SubItems.Add("...
            lvi.SubItems.Add("...

            listViewEx1.Items .Add (lvi);
        }

WM_ERASEBKGND を編集しても問題は解決しませんでした。
リストビューをホストするフォームにこのコードを追加したところ、ちらつきがなくなりました

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x02000000;  // Turn on WS_EX_COMPOSITED
            return cp;
        }
    }
4

2 に答える 2

5

このコードをクラスに追加すると、ここで何が問題なのかを確認できます。

protected override void OnHandleCreated(EventArgs e) {
    Console.WriteLine("Listview window created");
    base.OnHandleCreated(e);
}

プログラムを実行して列ヘッダーをクリックし、出力ウィンドウに注意してください。クリックするたびに、「リストビュー ウィンドウが作成されました」というメッセージが表示されます。つまり、並べ替えるたびに ListView ウィンドウが再作成されます。使用するダブルバッファリングに関係なく、常にちらつきます。

これは、ListView.Sorting プロパティを割り当てるコードが原因です。その基礎となるネイティブ実装はスタイル フラグであり、ウィンドウの作成時にのみ指定できます。したがって、変更すると、Winforms は強制的にウィンドウを再作成します。ちらつきは避けられない副作用です。

これを行うためのより良い方法があります。ListViewItemSorter プロパティを使用して、コントロールのカスタム並べ替えメソッドを実装することもできます。IComparable インターフェイスを実装するクラスを提供するだけです。ListView 自体に実装させることもできます。コードを次のようにすると、並べ替えが滑らかになります。

using System;
using System.Windows.Forms;

class ListViewEx : ListView, System.Collections.IComparer {
    public ListViewEx() {
        this.DoubleBuffered = true;
        this.ListViewItemSorter = this;
    }

    public int Compare(object x, object y) {
        var item1 = (ListViewItem)x;
        var item2 = (ListViewItem)y;
        int compare = String.Compare(item1.SubItems[this.sortColumn].Text, item2.SubItems[this.sortColumn].Text);
        if (sortOrder == SortOrder.Descending) compare = -compare;
        return compare;
    }

    protected override void OnColumnClick(ColumnClickEventArgs e) {
        if (e.Column != sortColumn) {
            sortColumn = e.Column;
            this.sortOrder = SortOrder.Ascending;
        }
        else {
            if (this.sortOrder == SortOrder.Ascending)
                this.sortOrder = SortOrder.Descending;
            else
                this.sortOrder = SortOrder.Ascending;
        }
        this.Sort();
    }

    private int sortColumn = 0;
    private SortOrder sortOrder = SortOrder.Ascending;
}
于 2013-05-27T11:07:09.120 に答える
1
class ListViewNF : System.Windows.Forms.ListView
{
    public ListViewNF()
    {
        //Activate double buffering
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

        //Enable the OnNotifyMessage event so we get a chance to filter out 
        // Windows messages before they get to the form's WndProc
        this.SetStyle(ControlStyles.EnableNotifyMessage, true);
    }

    protected override void OnNotifyMessage(Message m)
    {
        //Filter out the WM_ERASEBKGND message
        if(m.Msg != 0x14)
        {
            base.OnNotifyMessage(m);
        }
    }
}

これがソースです

于 2013-05-27T09:38:14.273 に答える