在ListView中绘制水平线以显示下降位置

时间:2017-09-11 01:28:08

标签: c# winforms

当我在Foobar2000中将文件拖放到播放列表中时,ListView会显示删除曲目的位置:

enter image description here

我正在寻找实现此功能的方法。它只是由Graphics库绘制,还是我有一些实现的方法在ListView上显示水平线?

1 个答案:

答案 0 :(得分:4)

至少使用ListView控件,通过InsertionMark property提供了一些有限的内置支持,但这仅适用于图标视图,小图标视图和平铺视图。当项目被排序或打开组时,它不起作用,它需要comctrl32.dll版本6(因此意味着Windows XP或更高版本,启用了视觉样式)。

如果您想要更通用的解决方案,可以在DragOver事件中自行绘制一条线:

animated demo of effect

为了避免闪烁,我们记得最后一个索引:

int prevItem = -1;

事件使用HitTest来确定光标下的项目..:

private void listView1_DragOver(object sender, DragEventArgs e)
{
    Point mLoc = listView1.PointToClient(Cursor.Position);
    var hitt = listView1.HitTest(mLoc);
    if (hitt.Item == null) return;

    int idx = hitt.Item.Index;
    if (idx == prevItem) return;

    listView2.Refresh();
    using (Graphics g = listView1.CreateGraphics())
    {
        Rectangle rect = listView1.GetItemRect(idx);
        g.DrawLine(Pens.Red, rect.Left, rect.Top, rect.Right, rect.Top);
    }
    prevItem = idx;
}

如果您想使用ListBox,代码几乎相同:

private void listBox1_DragOver(object sender, DragEventArgs e)
{
    Point mLoc = listBox1.PointToClient(Cursor.Position);
    int idx = listBox1.IndexFromPoint(mLoc);
    if (idx  < 0) return;
    if (idx == prevItem) return;

    listBox1.Refresh();
    using (Graphics g = listBox1.CreateGraphics())
    {
        Rectangle rect = listBox1.GetItemRectangle(idx);
        g.DrawLine(Pens.Red, rect.Left, rect.Top, rect.Right, rect.Top);
    }
    prevItem = idx;
}

同时执行Refresh清除DragLeave事件以及DragDrop事件中的行!

请注意,这是您想要使用control.CreateGraphics的罕见情况之一,因为绘图是非持久性的!通常,应使用e.Graphics事件中的Paint对象绘制所有图形!