Вопрос по c# – Мерцание в элементе управления ListView (OwnerDraw, Virtual)

12

Этот вопрос можно считать продолжениемМерцание в виде списка с ownerdraw и virtualmode.

Я получилListView контролировать вVirtual mode и я пытаюсь выполнить пользовательский рисунок. Рендеринг элемента выполняется с помощью следующего метода переопределения:

protected override void OnDrawItem(DrawListViewItemEventArgs eventArgs) 

Как упомянуто в упомянутом вопросе, пользовательский рисунок вводит мерцание при наведении мыши на события. Отладчик говорит мне, что это происходит из-заexcessive amount пользовательских событий розыгрыша, которые запускаются.


Теперь - принятый ответ на указанный вопрос говорит нам:

This is a bug in .NET's ListView and you cannot get around it by double buffering.

  • So, how reliable is that information? Is that really a bug? Or maybe we simply attempt to cut off a part of the messages and hope that it won't alter the visible behavior?

  • Is this true that if I have my owner drawing routine for the ListView in Virtual Mode, I can suppress these Custom Draw events and only perform my drawing in WM_PAINT or, maybe, this is incorrect for some cases?

  • What are the prerequisities for the System.Windows.Forms control to be able to do all the painting in WM_PAINT without altering it's initial behavior?

Образец MSDN это дерьмо. Внутри есть несколько ошибок. Я решил их, переопределив WndProc и отфильтровывая определенные сообщения NMHDR, которые имеют отношение к оперативному отслеживанию и другим вещам. У меня сейчас нет кода здесь, но я могу предоставить пример, который решает проблемы, с которыми вы тоже сталкивались. Alois Kraus

Ваш Ответ

3   ответа
4

Этот ответ здесьхоть и не уверен но

я думаю чтоListView.BeginUpdate() а такжеListView.EndUpdate() решит проблему.

MSDN Тема об этом

Может быть, таким образом:

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

Другой альтернативой может быть использование новой темы вBackgroundWorker обновить ListView ... Я реализовал это вместе сBeginUpdate()/EndUpDate() в моем приложении и нашел его относительно быстрее, чем толькоBeginUpdate()/EndUpDate()..

Update

Я нашел другую работуРешение в СОкласс Helper, предоставленный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);
    }
}
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededCPUError: User Rate Limit Exceeded Yippie-Ki-Yay
Error: User Rate Limit ExceededListviewError: User Rate Limit ExceededBeginUpdateError: User Rate Limit ExceededEndUpdateError: User Rate Limit ExceededEnableDoubleBufferError: User Rate Limit ExceededformLoadError: User Rate Limit ExceededDisableDoubleBufferError: User Rate Limit ExceededListViewExtendedStylesError: User Rate Limit ExceededDoubleBuffer = 0x00010000 value. – AaA Aug 3 '18 at 4:16
4

пользовательских обработчиках событий рендеринга (DrawItem, DrawSubItem). Я попытался BeginUpdate () / EndUpdate () и двойной буферизации, но безуспешно. Я думаю. NET вызывает дополнительные WM_PAINT для всех столбцов, чтобыthe right of the custom drawn column.

Однако я нашел этот обходной путь к одному настраиваемому визуализированному столбцу ListView. Работает просто отлично!

In the columnheader editor, set the custom drawn column as the last column Change the "DisplayIndex" of the position you want

Это должно устранить мерцание при наведении курсора мыши или во время выполнения.

10

это неправильно, что есть ошибка, но это немного глупо: есть защищенный атрибут, который вы можете установить, но вам нужно переопределить ListView. Я создал этот класс:

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

И затем в моем файле MyForm.Designer.cs я изменяю экземпляр ListView следующей строкой:

private ListView myListView;

this.myListView = new MyListView();

И OnDrawItem будет работать как шарм!

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededDoubleBufferedError: User Rate Limit ExceededWM_PAINTError: User Rate Limit Exceededuser32.dllError: User Rate Limit Exceeded Yippie-Ki-Yay
Error: User Rate Limit ExceededWM_PAINTError: User Rate Limit ExceededAnyway, thank you for you efforts. Yippie-Ki-Yay

Похожие вопросы