的WinForms ListView中选择绘图?WinForms、ListView

2023-09-04 00:51:57 作者:睫毛下的眼泪坠落花已枯萎

是否可以覆盖列表视图detault选择油漆?一个看起来半透明的蓝色叠加过的项目,就像在资源管理器窗口。

Is it possible to override the listview detault selection paint? The one that looks semi-transparent blue overlayed over the items, like in the explorer windows.

我想画的轮廓周围的选择表示选择。

I want to draw an outline around the selection to indicate selection.

没有办法做到这一点?例子是AP preciated。

Any way to do this? Examples are appreciated.

推荐答案

下面是一个快速的工作的例子,我是用插科打诨。

Here is a quick working example, i was messing around with.

第一个辅助结构和枚举。

First helper structs and enums.

  [StructLayout(LayoutKind.Sequential)]
    public struct DRAWITEMSTRUCT
    {
        public int CtlType;
        public int CtlID;
        public int itemID;
        public int itemAction;
        public int itemState;
        public IntPtr hwndItem;
        public IntPtr hDC;
        public RECT rcItem;
        public IntPtr itemData;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
        public int Width
        {
            get { return right - left; }
        }
        public int Height
        {
            get { return bottom - top; }
        }
    }

    public enum ListViewDefaults
    {
        LVS_OWNERDRAWFIXED = 0x0400
    }

    public enum WMDefaults
    {
        WM_DRAWITEM = 0x002B,
        WM_REFLECT = 0x2000
    }

现在创建一个自定义ListView和覆盖的CreateParams 和的WndProc

Now create a custom ListView and Override CreateParams and WndProc

public class CustomListView : ListView
    {
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                //add OwnerDraw style...i took this idea from Reflecting against ListView
                // bit OR is very important, otherwise you'll get an exception
                cp.Style |= (int)ListViewDefaults.LVS_OWNERDRAWFIXED; 

                return cp;
            }
        }

        protected override void WndProc(ref Message m)
        {

            base.WndProc(ref m);

            //if we are drawing an item then call our custom Draw.
            if (m.Msg == (int)(WMDefaults.WM_REFLECT | WMDefaults.WM_DRAWITEM))
                   ProcessDrawItem(ref m);
        }

现在是最重要的part..the图。 我是pretty的业余在绘画,但这应该让你做什么的想法。

Now for the most important part..the drawing. I am pretty amateur at drawing but this should get you an idea of what to do.

 private void ProcessDrawItem(ref Message m)
        {
            DRAWITEMSTRUCT dis = (DRAWITEMSTRUCT)Marshal.PtrToStructure(m.LParam, typeof(DRAWITEMSTRUCT));
            Graphics g = Graphics.FromHdc(dis.hDC);
            ListViewItem i = this.Items[dis.itemID];

            Rectangle rcItem = new Rectangle(dis.rcItem.left, dis.rcItem.top, this.ClientSize.Width, dis.rcItem.Height);
            //we have our rectangle.
            //draw whatever you want
            if (dis.itemState == 17)
            {
                //item is selected
                g.FillRectangle(new SolidBrush(Color.Red), rcItem);
                g.DrawString(i.Text, new Font("Arial", 8), new SolidBrush(Color.Black), new PointF(rcItem.X, rcItem.Y+1));
            }
            else
            {
                //regular item
                g.FillRectangle(new SolidBrush(Color.White), rcItem);
                g.DrawString(i.Text, new Font("Arial", 8), new SolidBrush(Color.Black), new PointF(rcItem.X, rcItem.Y+1));
            }

            //we have handled the message
            m.Result = (IntPtr)1;
        }

这是结果。