【问题标题】:Is it possible to highlight a specific column header of a winforms listview?是否可以突出显示 winforms 列表视图的特定列标题?
【发布时间】:2021-05-27 18:25:48
【问题描述】:

类似这样的:

我发现了一些关于突出显示单元格或列,甚至所有列标题的主题,但我只需要突出显示单个列标题以向用户指示排序。

相关但没有答案: Programmatically focus/highlight a ListView column header in WinForms VB.NET/C#

【问题讨论】:

    标签: .net winforms listview


    【解决方案1】:

    您可以设置ListView.OwenerDraw = true,然后像这样处理DrawItemDrawSubItemDrawHeader

    private void listView1_DrawColumnHeader(object sender, 
        DrawListViewColumnHeaderEventArgs e)
    {
        VisualStyleRenderer renderer;
        if (e.Bounds.Contains(this.PointToClient(Cursor.Position)))
            if (MouseButtons == MouseButtons.Left)
                renderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Pressed);
            else
                renderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Hot);
        else if (e.ColumnIndex == 1) /* YOUR CRITERIA FOR SELECTED COLUMN*/
            renderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Pressed);
        else
            renderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Normal);
        renderer.DrawBackground(e.Graphics, e.Bounds);
        var d = 3;
        var r = new Rectangle(e.Bounds.X + d, e.Bounds.Y + d,
            e.Bounds.Width - d, e.Bounds.Height - d);
        if (e.Header.ImageList != null && e.Header.ImageIndex > -1)
        {
            e.Header.ImageList.Draw(e.Graphics, r.Location, e.Header.ImageIndex);
            r.X += e.Header.ImageList.ImageSize.Width + d - 2;
            r.Width -= (e.Header.ImageList.ImageSize.Width + d - 2);
        }
        TextRenderer.DrawText(e.Graphics, e.Header.Text, e.Font,
            r, e.ForeColor, TextFormatFlags.Left);
    }
    private void listView1_OnDrawItem(object sender, DrawListViewItemEventArgs e)
    {
        e.DrawDefault = true;
    }
    private void OnDrawSubItem(object sender, DrawListViewSubItemEventArgs e)
    {
        e.DrawDefault = true;
    }
    

    要支持列的热跟踪,请使用以下派生的ListView

    public class MyListView : ListView
    {
        public MyListView()
        {
            DoubleBuffered = true;
        }
        HeaderControl headerControl;
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            if (headerControl != null)
                headerControl.ReleaseHandle();
            headerControl = new HeaderControl(this);
        }
        private class HeaderControl : NativeWindow
        {
            const int LVM_GETHEADER = 0x1000 + 31;
            const int WM_MOUSEMOVE = 0x0200;
            const int WM_LBUTTONDOWN = 0x0201;
            const int WM_LBUTTONUP = 0x0202;
            const int WM_MOUSELEAVE = 0x02A3;
            [DllImport("user32.dll")]
            static extern bool InvalidateRect(IntPtr hWnd, 
                IntPtr lpRect, bool erase);
            [DllImport("user32.dll")]
            static extern IntPtr SendMessage(IntPtr hWnd, 
                int Msg, IntPtr wParam, IntPtr lParam);
            ListView listview;
            void Invalidate()
            {
                InvalidateRect(this.Handle, IntPtr.Zero, true);
            }
            public HeaderControl(ListView listview)
            {
                this.listview = listview;
                var handle = SendMessage(listview.Handle, 
                    LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
                this.AssignHandle(handle);
                listview.HandleDestroyed += (sender, e) => this.ReleaseHandle();
            }
            protected override void WndProc(ref Message m)
            {
                if (m.Msg == WM_MOUSEMOVE ||
                    m.Msg == WM_LBUTTONDOWN ||
                    m.Msg == WM_LBUTTONUP ||
                    m.Msg == WM_MOUSELEAVE)
                {
                    this.Invalidate();
                }
                base.WndProc(ref m);
            }
        }
    }
    

    【讨论】:

    • 亮点取决于操作系统(和主题)。
    • 感谢它有效,但列的文本未对齐,或者使用了不同的字体。你知道有什么方法可以解决这个问题吗?基本上是为了保留除突出显示之外的列的确切外观。
    • e.DrawText 预计会绘制默认文本渲染。如果由于任何原因不符合您的要求,您可以使用TextRender.DrawText
    • @JoanVenge '向用户指示排序。'
    • 排序图标是什么?
    猜你喜欢
    • 2012-06-10
    • 2016-01-25
    • 1970-01-01
    • 2014-09-14
    • 2015-03-19
    • 2012-11-21
    • 2020-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多