Diskuze: ListView OwnerDraw, VirtualMode, View=Details

C# .NET .NET (C# a Visual Basic) ListView OwnerDraw, VirtualMode, View=Details American English version English version

Avatar
jt.e
Člen
Avatar
jt.e:

Zdravím, potřeboval bych pomoct s vykreslováním ListView.
Vytvořil jsem aplikaci ve které, jsem nejprve data zobrazoval v klasickém ListView, ale při přejení myší nad listem nepříjemně blikal, tak jsem na netu našel návod jak se toho blikání zbavit:

public partial class NiceList : ListView
{
    private const int WM_ERASEBKGND = 0x0014;

    public NiceList()
    {
        InitializeComponent();
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
        SetStyle(ControlStyles.EnableNotifyMessage, true);
        DoubleBuffered = true;
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }
    /// <summary>
    /// Notifies the control of Windows messages.
    /// </summary>
    /// <param name="m">A System.Windows.Forms.Message that represents the Windows message.
    protected override void OnNotifyMessage(Message m)
    {
        if (m.Msg != WM_ERASEBKGND)
            base.OnNotifyMessage(m);
    }
}

teď to sice nebliká, ale při najetí myší na položku někdy mizí text

vykreslování položek mám takto:

private void lvLst_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    SolidBrush brush_back = new SolidBrush(color_back);
    SolidBrush brush_fore = new SolidBrush(color_fore);
    StringFormat sformat = new StringFormat(StringFormatFlags.NoWrap);

    e.Graphics.FillRectangle(brush_back, e.SubItem.Bounds);
    e.Graphics.DrawString(e.SubItem.Text, lvLst.Font, brush_fore, e.SubItem.Bounds, sformat);
}
Editováno 30.12.2015 16:30
 
Odpovědět 30.12.2015 16:28
Avatar
jt.e
Člen
Avatar
jt.e:

Ještě musím dodat, že mám nastaveno FullRowSelect=tru­e.
A mizení textu se projevuje pouze u SubItems, 1. sloupec funguje dobře;

 
Nahoru Odpovědět 31.12.2015 10:57
Avatar
jt.e
Člen
Avatar
jt.e:

Tak už jsem na to přišel.

Tady je kód zkušební aplikace:

public partial class Form1 : Form
{
    public static readonly Color clDefault1 = Color.FromArgb(20, 20, 20);
    public static readonly Color clDefault2 = Color.FromArgb(16, 16, 16);
    public static readonly Color clSelected = Color.FromArgb(36, 36, 56);
    public static readonly Color clActived = Color.MidnightBlue;

    private List<int> lst = new List<int>();

    public Form1()
    {
        InitializeComponent();
        lvLst.BackColor = clDefault2;
        lst = new List<int>();

        Random ran = new Random();
        while (lst.Count < 1000) lst.Add(ran.Next(1, int.MaxValue));
        lvLst.VirtualListSize = lst.Count;
    }
    //(lvLst je ListView)
    private void lvLst_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
    {
        e.DrawDefault = true;
    }

    private void lvLst_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
    {
        int r = e.ItemIndex + 1;

        ListViewItem lvi = new ListViewItem();

        lvi.Text = r.ToString();
        lvi.ForeColor = Color.White;
        lvi.BackColor = ((e.ItemIndex & 0x00000001) == 0x00000001) ? clDefault1 : clDefault2;

        lvi.SubItems.Add(DateTime.Now.ToLongTimeString(), Color.YellowGreen, lvi.BackColor, lvLst.Font);

        lvi.SubItems.Add(lst[e.ItemIndex].ToString("X8"),
                        (lst[e.ItemIndex] > 0x40404040) ? Color.DodgerBlue : Color.DeepSkyBlue,
                        lvi.BackColor, lvLst.Font);


        e.Item = lvi;
    }

    private void lvLst_DrawItem(object sender, DrawListViewItemEventArgs e)
    {
        Color color_back = e.Item.BackColor;
        if (lvLst.SelectedIndices.Count > 0)
        {
            if (lvLst.SelectedIndices[0] == e.ItemIndex) color_back = clActived;
            else if (e.Item.Selected) color_back = clSelected;
        }

        SolidBrush brush_back = new SolidBrush(color_back);
        e.Graphics.FillRectangle(brush_back, e.Item.Bounds);

        SolidBrush brush_fore = new SolidBrush(e.Item.ForeColor);
        e.Graphics.DrawString(e.Item.Text, lvLst.Font, brush_fore, e.Item.Bounds);

        for(int i=1; i<e.Item.SubItems.Count; i++)
        {
            SolidBrush brush = new SolidBrush(e.Item.SubItems[i].ForeColor);
            e.Graphics.DrawString(e.Item.SubItems[i].Text, lvLst.Font, brush, e.Item.SubItems[i].Bounds);
        }
    }
}

součástí je i tento kód upravené komponenty ListView:

public partial class NiceList : ListView
{
    private const int WM_ERASEBKGND = 0x0014;

    public NiceList()
    {
        InitializeComponent();
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
        SetStyle(ControlStyles.EnableNotifyMessage, true);
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }
    /// <summary>
    /// Notifies the control of Windows messages.
    /// </summary>
    /// <param name="m">A System.Windows.Forms.Message that represents the Windows message.
    protected override void OnNotifyMessage(Message m)
    {
        if (m.Msg != WM_ERASEBKGND)
            base.OnNotifyMessage(m);
    }
}
Akceptované řešení
+5 Zkušeností
Řešení problému
 
Nahoru Odpovědět 1. ledna 22:37
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 3 zpráv z 3.