11

この質問は、 ownerdraw と virtualmode を使用したリストビューでのちらつきのフォローアップと見なされる場合があります。

ListViewコントロールがありVirtual mode、カスタム描画を実行しようとしています。アイテムのレンダリングは、次のメソッド オーバーライドを介して行われます。

protected override void OnDrawItem(DrawListViewItemEventArgs eventArgs) 

参照されている質問で述べたように、カスタム描画では、マウス オーバー イベントでちらつきが発生します。デバッガーは、発生するカスタム描画イベントが過剰なために発生することを教えてくれます。


今 - 参照された質問に対する受け入れられた回答は、次のことを示しています。

これは .NET の ListView のバグであり、ダブル バッファリングでは回避できません。

  • では、その情報はどの程度信頼できるのでしょうか。それは本当にバグですか?それとも、単にメッセージの一部を切り取り、目に見える動作が変わらないことを願っているのでしょうか?

  • 所有者の描画ルーチンがある場合、これらのイベントを抑制ListViewして描画のみを実行できるというのは本当ですか?Virtual Mode,Custom DrawWM_PAINT

  • コントロールが初期動作を変更せずSystem.Windows.Formsにすべての描画を実行できるようにするための前提条件は何ですか?WM_PAINT

4

3 に答える 3

10

少なくとも OnDrawItem のダブル バッファリングについては、バグがあるというのは正しくありませんが、少しばかげています。設定できる保護された属性がありますが、ListView をオーバーライドする必要があります。私はこの種のクラスを作成しました:

public class MyListView : ListView
{
    public MyListView()
        : base()
    {
        DoubleBuffered = true;
    }
}

次に、MyForm.Designer.cs ファイルで、ListView のインスタンス化を次の行で変更します。

private ListView myListView;

this.myListView = new MyListView();

そして、OnDrawItem は魔法のように機能します!

于 2012-05-08T15:44:20.493 に答える
4

ここのこの答えのように、確かではありませんが、

私はそれを考えてListView.BeginUpdate()ListView.EndUpdate()問題を解決します。

これについてのMSDNスレッド

多分このように:

protected override void OnDrawItem(DrawListViewItemEventArgs eventArgs)
{
    ListView.BeginUpdate();
    //Do Works Here
    ListView.EndUpdate();
}

アップデート

もう1つの方法は、新しいスレッドを使用してListViewを更新することです...これを/BackgroundWorkerと一緒にアプリケーションに実装したところ、 /だけよりも比較的高速であることがわかりました。BeginUpdate()EndUpDate()BeginUpdate()EndUpDate()

アップデート

はSOで別の実用的なソリューションを見つけました。これは、以下によって提供されるヘルパークラスBrian Gillespieです。

public enum ListViewExtendedStyles
{
    /// <summary>
    /// LVS_EX_GRIDLINES
    /// </summary>
    GridLines = 0x00000001,
    /// <summary>
    /// LVS_EX_SUBITEMIMAGES
    /// </summary>
    SubItemImages = 0x00000002,
    /// <summary>
    /// LVS_EX_CHECKBOXES
    /// </summary>
    CheckBoxes = 0x00000004,
    /// <summary>
    /// LVS_EX_TRACKSELECT
    /// </summary>
    TrackSelect = 0x00000008,
    /// <summary>
    /// LVS_EX_HEADERDRAGDROP
    /// </summary>
    HeaderDragDrop = 0x00000010,
    /// <summary>
    /// LVS_EX_FULLROWSELECT
    /// </summary>
    FullRowSelect = 0x00000020,
    /// <summary>
    /// LVS_EX_ONECLICKACTIVATE
    /// </summary>
    OneClickActivate = 0x00000040,
    /// <summary>
    /// LVS_EX_TWOCLICKACTIVATE
    /// </summary>
    TwoClickActivate = 0x00000080,
    /// <summary>
    /// LVS_EX_FLATSB
    /// </summary>
    FlatsB = 0x00000100,
    /// <summary>
    /// LVS_EX_REGIONAL
    /// </summary>
    Regional = 0x00000200,
    /// <summary>
    /// LVS_EX_INFOTIP
    /// </summary>
    InfoTip = 0x00000400,
    /// <summary>
    /// LVS_EX_UNDERLINEHOT
    /// </summary>
    UnderlineHot = 0x00000800,
    /// <summary>
    /// LVS_EX_UNDERLINECOLD
    /// </summary>
    UnderlineCold = 0x00001000,
    /// <summary>
    /// LVS_EX_MULTIWORKAREAS
    /// </summary>
    MultilWorkAreas = 0x00002000,
    /// <summary>
    /// LVS_EX_LABELTIP
    /// </summary>
    LabelTip = 0x00004000,
    /// <summary>
    /// LVS_EX_BORDERSELECT
    /// </summary>
    BorderSelect = 0x00008000,
    /// <summary>
    /// LVS_EX_DOUBLEBUFFER
    /// </summary>
    DoubleBuffer = 0x00010000,
    /// <summary>
    /// LVS_EX_HIDELABELS
    /// </summary>
    HideLabels = 0x00020000,
    /// <summary>
    /// LVS_EX_SINGLEROW
    /// </summary>
    SingleRow = 0x00040000,
    /// <summary>
    /// LVS_EX_SNAPTOGRID
    /// </summary>
    SnapToGrid = 0x00080000,
    /// <summary>
    /// LVS_EX_SIMPLESELECT
    /// </summary>
    SimpleSelect = 0x00100000
}

public enum ListViewMessages
{
    First = 0x1000,
    SetExtendedStyle = (First + 54),
    GetExtendedStyle = (First + 55),
}

/// <summary>
/// Contains helper methods to change extended styles on ListView, including enabling double buffering.
/// Based on Giovanni Montrone's article on <see cref="http://www.codeproject.com/KB/list/listviewxp.aspx"/>
/// </summary>
public class ListViewHelper
{
    private ListViewHelper()
    {
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr handle, int messg, int wparam, int lparam);

    public static void SetExtendedStyle(Control control, ListViewExtendedStyles exStyle)
    {
        ListViewExtendedStyles styles;
        styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0);
        styles |= exStyle;
        SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles);
    }

    public static void EnableDoubleBuffer(Control control)
    {
        ListViewExtendedStyles styles;
        // read current style
        styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0);
        // enable double buffer and border select
        styles |= ListViewExtendedStyles.DoubleBuffer | ListViewExtendedStyles.BorderSelect;
        // write new style
        SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles);
    }
    public static void DisableDoubleBuffer(Control control)
    {
        ListViewExtendedStyles styles;
        // read current style
        styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0);
        // disable double buffer and border select
        styles -= styles & ListViewExtendedStyles.DoubleBuffer;
        styles -= styles & ListViewExtendedStyles.BorderSelect;
        // write new style
        SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles);
    }
}
于 2012-05-13T05:46:37.297 に答える
4

カスタム レンダリング イベント ハンドラー (DrawItem、DrawSubItem) の ListView コントロールで、このちらつきの問題を確認しました。BeginUpdate()/EndUpdate() とダブル バッファリングを試しましたが、成功しませんでした。.NETは、カスタム描画された列の右側にあるすべての列に追加の WM_PAINT をトリガーすると思います。

ただし、カスタムレンダリングされた単一の列 ListView に対するこの回避策を見つけました。それはうまく動作します!

  1. 列ヘッダー エディターで、カスタム描画列を最後の列として設定します。
  2. 必要な位置の「DisplayIndex」を変更します

これにより、マウスオーバーまたはランタイム レンダリングでのちらつきが解決されます。

于 2012-05-14T18:01:58.150 に答える