Winforms - Click/drag anywhere in the form to move it as if clicked in the form caption
Microsoft KB Article 320687 has a detailed answer to this question.
Basically, you override the WndProc method to return HTCAPTION to the WM_NCHITTEST message when the point being tested is in the client area of the form -- which is, in effect, telling Windows to treat the click exactly the same as if it had occured on the caption of the form.
private const int WM_NCHITTEST = 0x84;
private const int HTCLIENT = 0x1;
private const int HTCAPTION = 0x2;
protected override void WndProc(ref Message m)
{
switch(m.Msg)
{
case WM_NCHITTEST:
base.WndProc(ref m);
if ((int)m.Result == HTCLIENT)
m.Result = (IntPtr)HTCAPTION;
return;
}
base.WndProc(ref m);
}
Here is a way to do it using a P/Invoke.
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HTCAPTION = 0x2;
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
void Form_Load(object sender, EventArgs e)
{
this.MouseDown += new MouseEventHandler(Form_MouseDown);
}
void Form_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
}
The following code assumes that the ProgressBarForm form has a ProgressBar control with Dock property set to Fill
public partial class ProgressBarForm : Form
{
private bool mouseDown;
private Point lastPos;
public ProgressBarForm()
{
InitializeComponent();
}
private void progressBar1_MouseMove(object sender, MouseEventArgs e)
{
if (mouseDown)
{
int xoffset = MousePosition.X - lastPos.X;
int yoffset = MousePosition.Y - lastPos.Y;
Left += xoffset;
Top += yoffset;
lastPos = MousePosition;
}
}
private void progressBar1_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
lastPos = MousePosition;
}
private void progressBar1_MouseUp(object sender, MouseEventArgs e)
{
mouseDown = false;
}
}