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

Ch3*_*ire 3 c# winforms

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

在此处输入图片说明

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

TaW*_*TaW 5

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

如果你想要一个更通用的解决方案,你可以很容易地在DragOver事件中自己画一条线:

效果动画演示

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

int prevItem = -1;
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)

如果你想使用 a 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;
}
Run Code Online (Sandbox Code Playgroud)

也做一个RefreshDragLeave事件和事件中清除线路DragDrop

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