Home > OS >  Handle MouseMove, MouseDown, MouseUp Events in a ListView to drag a Form
Handle MouseMove, MouseDown, MouseUp Events in a ListView to drag a Form

Time:02-20

I'm using MouseMove, MouseUp, MouseDown events to move a borderless form (as found here as an example).

It works great, but for ListViews, it only works if I click on an item (its text) in the list. It does not work if I click in the space of the ListView containing no items.

Is there a possible way to fix this?

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

CodePudding user response:

To move a Form, clicking and dragging any Control, you can implement the IMessageFilter Interface. You'll receive messages before they're sent to the target Control (with the option to suppress them, returning true).
The implementation requires that you implement PreFilterMessage.

Store the current Mouse Position when the message is WM_LBUTTONDOWN and move the Form when it's WM_MOUSEMOVE, if the left Button is still pressed (the Buttons currently pressed are specified in WParam, see the Docs about this).

Use Application.AddMessageFilter to register the class that implements the interface (the Form itself, in this case). Here, it's called in OnHandleCreated.
Call Application.RemoveMessageFilter to remove the filter. Here, called in OnHandleDestroyed.

Note that I've used Capture = true; in WM_MOUSEMOVE, so pressing the left mouse button and dragging, e.g., a Button Control, won't cause - in this case - a Click event.
Modify it if you don't like it.

Note: As Reza Aghaei suggested, if you set your ListView to MultiSelect = false, you can then click anywhere on it to drag the Form.

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);
    }
}
  • Related