Принятый ответ - это крутой трюк, но он не всегда работает, если форма покрыта закрепленным в Fill дочерним элементом управления, например, Panel (или его производными), потому что этот элемент управления использует все большинство сообщений Windows.
Вот простой подход, который работает и в этом случае: получить рассматриваемый элемент управления (используйте этот класс вместо стандартного) и обрабатывать сообщения мыши, например, так:
private class MyTableLayoutPanel : Panel // or TableLayoutPanel, etc.
{
private Point _mouseDown;
private Point _formLocation;
private bool _capture;
// NOTE: we cannot use the WM_NCHITTEST / HTCAPTION trick because the table is in control, not the owning form...
protected override void OnMouseDown(MouseEventArgs e)
{
_capture = true;
_mouseDown = e.Location;
_formLocation = ((Form)TopLevelControl).Location;
}
protected override void OnMouseUp(MouseEventArgs e)
{
_capture = false;
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (_capture)
{
int dx = e.Location.X - _mouseDown.X;
int dy = e.Location.Y - _mouseDown.Y;
Point newLocation = new Point(_formLocation.X + dx, _formLocation.Y + dy);
((Form)TopLevelControl).Location = newLocation;
_formLocation = newLocation;
}
}
}