【问题标题】:Handle MouseMove, MouseDown, MouseUp Events in a ListView to drag a borderless Form处理 ListView 中的 MouseMove、MouseDown、MouseUp 事件以拖动无边框 Form
【发布时间】:2022-04-30 18:58:06
【问题描述】:

我正在使用MouseMoveMouseUpMouseDown 事件来移动无边界表单(此处以示例为例)。

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

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

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;
}

【问题讨论】:

  • 我想你会为包含 ListView 的容器使用这些事件处理程序,无论是你想移动它的表单还是只是容器。
  • 不清楚你想在那里做什么。显然,您处理 ListView 的鼠标事件,但随后尝试移动 this(表单)- ListView 在其所有客户端区域表面上引发鼠标事件,无论是否被某些项目占用。
  • ListView 鼠标事件的提升/处理有点奇怪;例如,如果您在非项目区域上启动 MouseDown,则不会引发 MouseMove 事件。另一个例子,当你在一个项目上启动一个 MouseDown,然后将鼠标按钮释放到控件的区域之外,那么它会在你下次将鼠标移到控件上时引发一个 MouseUp 事件,而忽略鼠标按钮的状态。
  • 这是一个非常好的实现@Jimi。对于ListView 控件,您需要设置MultiSelect = false 以使其工作,即使您开始在非项目区域中拖动控件。 (或者也许您可以找到更好的解决方法。)
  • @RezaAghaei 您的意思是,设置MultiSelect = false,然后您可以拖动表单单击ListView 上的任意位置?是的,就可以了。我会留下一个注释,很可能 选择矩形 在 OP 的场景中没有那么有用。 -- 谢谢,顺便说一句:) -- 如果我有空闲时间,我会看看是否有可能避免它(我这次很忙)。

标签: c# .net winforms listview


【解决方案1】:

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

当消息为WM_LBUTTONDOWN 时存储当前鼠标位置,当它为WM_MOUSEMOVE 时移动窗体,如果左按钮仍被按下(当前按下的按钮在WParam 中指定,请参阅有关此的文档) .

使用Application.AddMessageFilter 注册实现接口的类(在本例中为表单本身)。在这里,它被称为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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    相关资源
    最近更新 更多