处理 ListView 中的 MouseMove、MouseDown、MouseUp 事件以拖动无边框窗体

Handle MouseMove, MouseDown, MouseUp Events in a ListView to drag a borderless Form

我正在使用 MouseMoveMouseUpMouseDown 事件来移动无边界表单(如在此处找到的示例)。

效果很好,但对于 ListView,它只有在我单击列表中的项目(其文本)时才有效。如果我单击不包含项目的 ListView 的 space,它不起作用。

有没有办法解决这个问题?

private bool mouseDown;
private Point lastLocation;

private void ListView1_MouseDown(object sender, MouseEventArgs e)
{
    mouseDown = true;
    lastLocation = e.Location;
}

private void ListView1_MouseMove(object sender, MouseEventArgs e)
{
    if(mouseDown)
    {
        this.Location = new Point(
            (this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);

        this.Update();
    }
}

private void ListView1_MouseUp(object sender, MouseEventArgs e)
{
    mouseDown = false;
}

要移动窗体,单击并拖动任何控件,您可以实现IMessageFilter Interface。在将消息发送到目标控件之前,您会收到消息(可以选择抑制它们,返回 true)。
该实施要求您实施 PreFilterMessage.

当消息为WM_LBUTTONDOWN时存储当前鼠标位置,当消息为WM_MOUSEMOVE时移动表单,如果左按钮仍被按下(当前按下的按钮在[=14=中指定) ],请参阅有关此内容的文档)。

使用Application.AddMessageFilter注册实现接口的class(本例中为Form本身)。在这里,它在 OnHandleCreated.
中调用 调用 Application.RemoveMessageFilter 删除过滤器。在这里,调用 OnHandleDestroyed.

请注意,我在 WM_MOUSEMOVE 中使用了 Capture = true;,因此按下鼠标左键并拖动(例如,按钮控件)不会导致 - 在本例中 - Click 事件.
不喜欢就修改吧

注意: 正如 Reza Aghaei 所建议的那样,如果将 ListView 设置为 MultiSelect = false,则可以单击它的任意位置来拖动表单。

public partial class SomeForm : Form, IMessageFilter
{
    private const int WM_MOUSEMOVE = 0x0200;
    private const int WM_LBUTTONDOWN = 0x0201;

    Point mouseDownPos = Point.Empty;

    public bool PreFilterMessage(ref Message m) {
        switch (m.Msg) {
            case WM_LBUTTONDOWN:
                mouseDownPos = PointToClient(MousePosition);
                break;
            case WM_MOUSEMOVE:
                if ((m.WParam.ToInt32() & 1) != 1) break; 
                Capture = true;
                var p = PointToClient(MousePosition);
                Location = new Point(Left + p.X - mouseDownPos.X, Top + p.Y - mouseDownPos.Y);
                break;
        }
        return false;
    }

    protected override void OnHandleCreated(EventArgs e) {
        base.OnHandleCreated(e);
        if (!DesignMode) Application.AddMessageFilter(this);
    }

    protected override void OnHandleDestroyed(EventArgs e) {
        if (!DesignMode) Application.RemoveMessageFilter(this);
        base.OnHandleDestroyed(e);
    }
}