【问题标题】:Overriding the Drawitem event on a WinForm ListView control覆盖 WinForm ListView 控件上的 Drawitem 事件
【发布时间】:2013-11-15 22:57:18
【问题描述】:

我希望我的 ListView 的选定项目在失去焦点时保持清晰可见(在 Windows 7 上是暗灰色)。我确实将 HideSelection 属性设置为 False。

我想为 List View 做一些人在这里为 TreeView 控件所做的事情,即覆盖 Drawnode 事件:

C# WinForms highlight treenode when treeview doesnt have focus

我认为我需要将 OwnerDraw 属性设置为 True 以覆盖 DrawItem 事件,但我不确定在此事件中我需要做什么...... :-)

【问题讨论】:

    标签: c# winforms listview


    【解决方案1】:

    你需要这样的东西:

    private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
    {
        e.DrawDefault = true;
    }
    
    private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
    {
        const int TEXT_OFFSET = 1;    // I don't know why the text is located at 1px to the right. Maybe it's only for me.
    
        ListView listView = (ListView)sender;
    
        // Check if e.Item is selected and the ListView has a focus.
        if (!listView.Focused && e.Item.Selected)
        {
            Rectangle rowBounds = e.SubItem.Bounds;
            Rectangle labelBounds = e.Item.GetBounds(ItemBoundsPortion.Label);
            int leftMargin = labelBounds.Left - TEXT_OFFSET;
            Rectangle bounds = new Rectangle(rowBounds.Left + leftMargin, rowBounds.Top, e.ColumnIndex == 0 ? labelBounds.Width : (rowBounds.Width - leftMargin - TEXT_OFFSET), rowBounds.Height);
            TextFormatFlags align;
            switch (listView.Columns[e.ColumnIndex].TextAlign)
            {
                case HorizontalAlignment.Right:
                    align = TextFormatFlags.Right;
                    break;
                case HorizontalAlignment.Center:
                    align = TextFormatFlags.HorizontalCenter;
                    break;
                default:
                    align = TextFormatFlags.Left;
                    break;
            }
            TextRenderer.DrawText(e.Graphics, e.SubItem.Text, listView.Font, bounds, SystemColors.HighlightText,
                align | TextFormatFlags.SingleLine | TextFormatFlags.GlyphOverhangPadding | TextFormatFlags.VerticalCenter | TextFormatFlags.WordEllipsis);
        }
        else
            e.DrawDefault = true;
    }
    
    private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
    {
        ListView listView = (ListView)sender;
    
        // Check if e.Item is selected and the ListView has a focus.
        if (!listView.Focused && e.Item.Selected)
        {
            Rectangle rowBounds = e.Bounds;
            int leftMargin = e.Item.GetBounds(ItemBoundsPortion.Label).Left;
            Rectangle bounds = new Rectangle(leftMargin, rowBounds.Top, rowBounds.Width - leftMargin, rowBounds.Height);
            e.Graphics.FillRectangle(SystemBrushes.Highlight, bounds);
        }
        else
            e.DrawDefault = true;
    }
    

    编辑: 改进了 View = View.DetailsFullRowSelect = true
    EDIT2: 考虑了不同的列对齐类型,以及自动省略号标志已添加。

    【讨论】:

    • 不幸的是,我的列表有多列,文本在选择行时,除了第一列之外,文本会消失。我可以要求您也帮助实现绘制子项方法吗?我正在使用全行选择。
    • 我已根据您的需要更新了代码。现在所有 3 个事件都已处理:DrawItemDrawSubItemDrawColumnHeader
    • 除了一个小问题,即colimn不够大,无法显示全文并添加了省略号,它工作得很好。完整的列文本溢出到下一列。
    • 已修复。还考虑了不同的对齐类型的列。
    • 我已经找出问题所在,这是底层 Win32 控件中的错误。当鼠标指针移到行上时,在详细视图中的每行发生一次 DrawItem 事件,而没有伴随的 DrawSubItem 事件。如果有人遇到同样的问题,解决方案在这里:link
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 2013-02-11
    • 2014-09-02
    相关资源
    最近更新 更多