Hacer una forma sin bordes movible?

¿Hay alguna manera de hacer que un formulario que no tiene borde (FormBorderStyle está establecido en “ninguno”) se pueda mover cuando se hace clic con el mouse sobre el formulario como si hubiera un borde?

Este artículo en CodeProject detalla una técnica. Básicamente se reduce a:

public const int WM_NCLBUTTONDOWN = 0xA1; public const int HT_CAPTION = 0x2; [System.Runtime.InteropServices.DllImportAttribute("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); [System.Runtime.InteropServices.DllImportAttribute("user32.dll")] public static extern bool ReleaseCapture(); private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { if (e.Button == MouseButtons.Left) { ReleaseCapture(); SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0); } } 

Esto básicamente hace exactamente lo mismo que agarrar la barra de título de una ventana, desde el punto de vista del administrador de la ventana.

No hagamos las cosas más difíciles de lo que deben ser. He encontrado tantos fragmentos de código que te permiten arrastrar un formulario (u otro Control). Y muchos de ellos tienen sus propios inconvenientes / efectos secundarios. Especialmente aquellos en los que engañan a Windows para que piense que un Control en un formulario es la forma real.

Dicho esto, aquí está mi fragmento. Lo uso todo el tiempo. También me gustaría señalar que no deberías usar esto. Invalidar (); como a otros les gusta porque hace que la forma parpadee en algunos casos. Y en algunos casos también lo hace esto. Refrescar. Usando this.Update, no he tenido ningún problema de parpadeo:

 private bool mouseDown; private Point lastLocation; private void Form1_MouseDown(object sender, MouseEventArgs e) { mouseDown = true; lastLocation = e.Location; } private void Form1_MouseMove(object sender, MouseEventArgs e) { if(mouseDown) { this.Location = new Point( (this.Location.X - lastLocation.X) + eX, (this.Location.Y - lastLocation.Y) + eY); this.Update(); } } private void Form1_MouseUp(object sender, MouseEventArgs e) { mouseDown = false; } 

Otra forma más simple de hacer lo mismo.

 public partial class Form1 : Form { public Form1() { InitializeComponent(); // set this.FormBorderStyle to None here if needed // if set to none, make sure you have a way to close the form! } protected override void WndProc(ref Message m) { base.WndProc(ref m); if (m.Msg == WM_NCHITTEST) m.Result = (IntPtr)(HT_CAPTION); } private const int WM_NCHITTEST = 0x84; private const int HT_CLIENT = 0x1; private const int HT_CAPTION = 0x2; } 

utilice MouseDown, MouseMove y MouseUp. Puede establecer un indicador de variable para eso. Tengo una muestra, pero creo que debes revisarla.

Estoy codificando la acción del mouse en un panel. Una vez que haga clic en el panel, su formulario se moverá con él.

 //Global variables; private bool _dragging = false; private Point _offset; private Point _start_point=new Point(0,0); private void panel1_MouseDown(object sender, MouseEventArgs e) { _dragging = true; // _dragging is your variable flag _start_point = new Point(eX, eY); } private void panel1_MouseUp(object sender, MouseEventArgs e) { _dragging = false; } private void panel1_MouseMove(object sender, MouseEventArgs e) { if(_dragging) { Point p = PointToScreen(e.Location); Location = new Point(pX - this._start_point.X,pY - this._start_point.Y); } } 

Solo WPF


no tengo el código exacto a mano, pero en un proyecto reciente creo que utilicé el evento MouseDown y simplemente coloque esto:

 frmBorderless.DragMove(); 

Método Window.DragMove (MSDN)

Árbitro. enlace de video

Esto se prueba y es fácil de entender.

 protected override void WndProc(ref Message m) { switch (m.Msg) { case 0x84: base.WndProc(ref m); if((int)m.Result == 0x1) m.Result = (IntPtr)0x2; return; } base.WndProc(ref m); } 

No hay propiedad que puedas voltear para que esto solo suceda mágicamente. Mire los eventos para el formulario y se vuelve bastante trivial implementar esto estableciendo esto. this.Top y this.Left . this.Left . Específicamente, querrás mirar MouseDown , MouseUp y MouseMove .

 public Point mouseLocation; private void frmInstallDevice_MouseDown(object sender, MouseEventArgs e) { mouseLocation = new Point(-eX, -eY); } private void frmInstallDevice_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { Point mousePos = Control.MousePosition; mousePos.Offset(mouseLocation.X, mouseLocation.Y); Location = mousePos; } } 

esto puede resolver tu problema …

Para .NET Framework 4,

Puede usar esto. this.DragMove() para el evento MouseDown del componente (mainLayout en este ejemplo) que está utilizando para arrastrar.

 private void mainLayout_MouseDown(object sender, MouseButtonEventArgs e) { this.DragMove(); } 

https://social.msdn.microsoft.com/Forums/vstudio/en-US/d803d869-68e6-46ff-9ff1-fabf78d6393c/how-to-make-a-borderless-form-in-c?forum=csharpgeneral

Este fragmento de código del enlace de arriba hizo el truco en mi caso 🙂

 protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (e.Button == MouseButtons.Left) { this.Capture = false; Message msg = Message.Create(this.Handle, 0XA1, new IntPtr(2), IntPtr.Zero); this.WndProc(ref msg); } } 

Además, si necesita hacer doble clic en DoubleClick y hacer que su forma sea más grande o más pequeña, puede usar la primera respuesta, crear una variable int global, agregar 1 cada vez que el usuario haga clic en el componente que usa para arrastrar. Si es variable == 2 , haz tu forma más grande / más pequeña. También use un temporizador cada medio segundo o un segundo para que su variable = 0 ;

La forma más fácil es:

Primero crea una etiqueta llamada label1. Vaya a los eventos de label1> eventos de mouse> Label1_Mouse Move y escríbalos:

 if (e.Button == MouseButtons.Left){ Left += eX; Top += eY;` } 

La mejor forma que he encontrado (modificado por supuesto)

 // This adds the event handler for the control private void AddDrag(Control Control) { Control.MouseDown += new System.Windows.Forms.MouseEventHandler(this.DragForm_MouseDown); } public const int WM_NCLBUTTONDOWN = 0xA1; public const int HT_CAPTION = 0x2; [System.Runtime.InteropServices.DllImportAttribute("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); [System.Runtime.InteropServices.DllImportAttribute("user32.dll")] public static extern bool ReleaseCapture(); private void DragForm_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { ReleaseCapture(); SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0); // Checks if Y = 0, if so maximize the form if (this.Location.Y == 0) { this.WindowState = FormWindowState.Maximized; } } } 

Para aplicar arrastre a un control, simplemente inserte esto después de InitializeComponent ()

 AddDrag(NameOfControl); 

Estaba tratando de hacer que una ventana móvil sin márgenes que contenía un control WPF Element Host y un control de usuario WPF.

Terminé con un panel de stack llamado StackPanel en mi control de usuario de WPF, que me pareció lógico probar haciendo clic para moverlo. Probar el código de junmats funcionó cuando moví el mouse lentamente, pero si movía el mouse más rápido, el mouse se movería fuera del formulario y el formulario quedaría atascado en algún punto del medio del movimiento.

Esto mejoró su respuesta para mi situación usando CaptureMouse y ReleaseCaptureMouse y ahora el mouse no se mueve fuera del formulario mientras lo mueve aunque lo mueva rápidamente.

 private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e) { _start_point = e.GetPosition(this); StackPanel.CaptureMouse(); } private void StackPanel_MouseUp(object sender, MouseButtonEventArgs e) { StackPanel.ReleaseMouseCapture(); } private void StackPanel_MouseMove(object sender, MouseEventArgs e) { if (StackPanel.IsMouseCaptured) { var p = _form.GetMousePositionWindowsForms(); _form.Location = new System.Drawing.Point((int)(pX - this._start_point.X), (int)(pY - this._start_point.Y)); } } //Global variables; private Point _start_point = new Point(0, 0); 

Agregar un controlador de eventos MouseLeftButtonDown a MainWindow funcionó para mí.

En la función de evento que se genera automáticamente, agregue el siguiente código:

 base.OnMouseLeftButtonDown(e); this.DragMove(); 

Como algunas respuestas no permiten que los controles secundarios sean arrastrables, he creado una pequeña clase de ayuda. Debería pasar el formulario de nivel superior. Se puede hacer más genérico si se desea.

 class MouseDragger { private readonly Form _form; private Point _mouseDown; protected void OnMouseDown(object sender, MouseEventArgs e) { _mouseDown = e.Location; } protected void OnMouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { int dx = e.Location.X - _mouseDown.X; int dy = e.Location.Y - _mouseDown.Y; _form.Location = new Point(_form.Location.X + dx, _form.Location.Y + dy); } } public MouseDragger(Form form) { _form = form; MakeDraggable(_form); } private void MakeDraggable(Control control) { var type = control.GetType(); if (typeof(Button).IsAssignableFrom(type)) { return; } control.MouseDown += OnMouseDown; control.MouseMove += OnMouseMove; foreach (Control child in control.Controls) { MakeDraggable(child); } } } 

¡Intenté lo siguiente y prest changeo, mi ventana transparente ya no estaba congelada en su lugar, pero podía moverse! (deseche todas esas otras soluciones complejas arriba …)

  private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { base.OnMouseLeftButtonDown(e); // Begin dragging the window this.DragMove(); }