WinForms FAQ - Mouse Handling

Find answers for the most frequently asked questions
Expand All Collapse All

You can drag such a window by using Win32 APIs to switch the mouse hit to WM_NCLBUTTONDOWN. The code below will allow you to drag by mousing down anywhere in the form’s clientarea as long as you don’t hit a child control on the form.

	using System.Runtime.InteropServices;
	............
	public const int WM_NCLBUTTONDOWN = 0xA1; 
 	public const int HTCAPTION = 0x2; 
 
 	[DllImportAttribute ('user32.dll')] 
 	public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); 
 
	[DllImportAttribute ('user32.dll')] 
	public static extern bool ReleaseCapture(); 

	private void Form2_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
	{
		ReleaseCapture();
		SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
	}

Here is a solution posed by Jacob Grass (Abiliti Solutions) that does not rely on InteropServices.

	Private blnMoving As Boolean = False
	Private MouseDownX As Integer
	Private MouseDownY As Integer
 
	Private Sub Form1_MouseDown(ByVal sender As Object, _
    			ByVal e As System.Windows.Forms.MouseEventArgs) Handles Form1.MouseDown
    		If e.Button = MouseButtons.Left Then
			blnMoving = True
			MouseDownX = e.X
			MouseDownY = e.Y
		End If
	End Sub
 
	Private Sub Form1_MouseUp(ByVal sender As Object, _
			ByVal e As System.Windows.Forms.MouseEventArgs) Handles Form1.MouseUp
		If e.Button = MouseButtons.Left Then
			blnMoving = False
		End If
	End Sub
 
	Private Sub Form1_MouseMove(ByVal sender As Object, _
			ByVal e As System.Windows.Forms.MouseEventArgs) Handles Form1.MouseMove
		If blnMoving Then
			Dim temp As Point = New Point()
 
			temp.X = Form1.Location.X + (e.X - MouseDownX)
			temp.Y = Form1.Location.Y + (e.Y - MouseDownY)
			Form1.Location = temp
		End If
	End Sub
Permalink

This usually happens when a Control doesn’t know that the mouse has left its bounds following a mouse enter. This results in the Control not throwing a MouseLeave event for subsequent mouse moves over it.

This is possible if you performed some operation when the mouse was within a Control that made it lose its mouse capture, for example, opening a top-level window over the Control such that the mouse is now over this new window.

To work around this problem send a WM_MOUSELEAVE manually to the original Control before the offending operation.


class NativeMethods
{
	[DllImport('user32.dll', CharSet=CharSet.Auto)]
	extern public static IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam)  ;
}

// Send a WM_MOUSELEAVE manually to a window.
NativeMethods.SendMessage(control.Handle, NativeMethods.WM_MOUSELEAVE, IntPtr.Zero, IntPtr.Zero);
Permalink

Catch the form’s MouseMove event which is called when the mouse moves over the form. To determine if a button is pressed during the move, check the event arg’s Button property. The code below draw’s a line on the form as the mouse moves over it. The line is red when the left button is pressed, white when the right button is pressed and blue when no button is pressed.

private Point _point = new Point(-1, -1);
....
private void InitializeComponent()
{
	// 
	// Form1
	// 
	this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
	this.ClientSize = new System.Drawing.Size(292, 273);
	this.Name = 'Form1';
	this.Text = 'Form1';
	this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);
}
....
private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
	if(_point.X	== -1)
		_point = new Point(e.X, e.Y);

	Color c;
	if(e.Button == MouseButtons.Left)
		c = Color.Red;
	else if(e.Button == MouseButtons.Right)
		c = Color.White;
	else if(e.Button == MouseButtons.None)
		c = Color.Blue;
	else
		c = this.BackColor;

	Point p = new Point(e.X,e.Y);
	Graphics g = Graphics.FromHwnd(this.Handle);
	Pen pen = new Pen(c,1);
	g.DrawLine(pen,_point,p);
	_point = p;
	pen.Dispose();
}
Permalink

The Cursor.Position property is a static property with both get and set methods available. Remember that the Point object used by the property is in screen coordinates. Here is code that move the mouse position down 20 points.

	Point pt = Cursor.Position;
	pt.Y += 20;
	Cursor.Position = pt;
Permalink

Use the Position property of the Cursor class found in the System.Windows.Forms namespace. Here is code that will flag whether the mouse is over button1.

	Point ptCursor = Cursor.Position;
	ptCursor = PointToClient(ptCursor);
	if( button1.Bounds.Contains(ptCursor) )
                 {
		//mouse over button1
		//....
	}
	else
	{
		//mouse not over button1
		//....
	}
Permalink

Share with

Couldn't find the FAQs you're looking for?

Please submit your question and answer.