Rendre mobile un formulaire sans frontières?

Est-il possible de créer un formulaire sans bordure (FormBorderStyle est défini sur “none”) lorsque la souris est cliquée sur le formulaire comme s’il y avait une bordure?

Cet article sur CodeProject détaille une technique. Est fondamentalement se résume à:

public const int WM_NCLBUTTONDOWN = 0xA1; public const int HT_CAPTION = 0x2; [System.Runtime.InteropServices.DllImportAtsortingbute("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); [System.Runtime.InteropServices.DllImportAtsortingbute("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); } } 

Cela revient essentiellement à saisir la barre de titre d’une fenêtre, du sharepoint vue du gestionnaire de fenêtres.

Ne rendons pas les choses plus difficiles que nécessaire. J’ai rencontré tellement d’extraits de code qui vous permettent de faire glisser un formulaire (ou un autre contrôle). Et beaucoup d’entre eux ont leurs propres inconvénients / effets secondaires. Surtout ceux où ils poussent Windows à penser qu’un contrôle sur un formulaire est la forme réelle.

Cela étant dit, voici mon extrait. Je l’utilise tout le temps. J’aimerais également noter que vous ne devriez pas utiliser ceci.Invalider (); comme d’autres aiment le faire, car il fait clignoter le formulaire dans certains cas. Et dans certains cas, il en est ainsi. Actualisez. En utilisant this.Update, je n’ai pas eu de problèmes de scintillement:

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

Une autre façon plus simple de faire la même chose.

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

utilisez MouseDown, MouseMove et MouseUp. Vous pouvez définir un indicateur de variable pour cela. J’ai un échantillon, mais je pense que vous devez réviser.

Je code l’action de la souris sur un panneau. Une fois que vous cliquez sur le panneau, votre formulaire se déplace avec lui.

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

WPF uniquement


Je n’ai pas le code exact à scope de main, mais dans un projet récent, je pense avoir utilisé l’événement MouseDown et simplement mis ceci:

 frmBorderless.DragMove(); 

Méthode Window.DragMove (MSDN)

Réf. lien vidéo

Ceci est testé et facile à comprendre.

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

Il n’y a pas de propriété que vous pouvez retourner pour que cela se produise comme par magie. Regardez les événements pour le formulaire et il devient assez sortingvial de l’implémenter en définissant this.Top et this.Left . Plus précisément, vous voudrez regarder MouseDown , MouseUp et 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; } } 

Cela peut résoudre votre problème ….

Pour .NET Framework 4,

Vous pouvez utiliser this.DragMove() pour l’événement MouseDown du composant (mainLayout dans cet exemple) que vous utilisez pour faire glisser.

 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

Ce morceau de code du lien ci-dessus a fait l’affaire dans mon cas 🙂

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

De plus, si vous avez besoin de DoubleClick et de rendre votre formulaire plus grand / plus petit, vous pouvez utiliser la réponse First, créer une variable int globale, append 1 chaque fois que l’utilisateur clique sur le composant que vous utilisez pour le glisser. Si variable == 2 alors rendez votre formulaire plus grand / plus petit. Utilisez également une timer toutes les demi-secondes ou secondes pour que votre variable = 0 ;

Le plus simple est:

Commencez par créer une étiquette nommée label1. Accédez aux événements de label1> événements de la souris> Label1_Mouse Move et écrivez-les:

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

Le meilleur moyen que j’ai trouvé (modifié bien sûr)

 // 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.DllImportAtsortingbute("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); [System.Runtime.InteropServices.DllImportAtsortingbute("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; } } } 

Pour appliquer un glissement à un contrôle, insérez-le simplement après InitializeComponent ()

 AddDrag(NameOfControl); 

J’essayais de créer un formulaire Windows sans marge contenant un contrôle WPF Element Host et un contrôle utilisateur WPF.

Je me suis retrouvé avec un panneau de stack appelé StackPanel dans mon contrôle utilisateur WPF, ce qui semblait logique de cliquer sur pour le déplacer. Essayer le code de junmats a fonctionné lorsque j’ai déplacé la souris lentement, mais si je déplaçais la souris plus vite, la souris se détacherait du formulaire et le formulaire serait bloqué quelque part au milieu du mouvement.

Cela a amélioré sa réponse à ma situation en utilisant CaptureMouse et ReleaseCaptureMouse et maintenant la souris ne quitte pas le formulaire en le déplaçant même si je le déplace rapidement.

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

L’ajout d’un MouseLeftButtonDown événement MouseLeftButtonDown à MainWindow a fonctionné pour moi.

Dans la fonction d’événement qui est générée automatiquement, ajoutez le code ci-dessous:

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

Étant donné que certaines réponses ne permettent pas aux contrôles enfants d’être déplaçables, j’ai créé une petite classe d’assistance. Il faut passer la forme de haut niveau. Peut être rendu plus générique si désiré.

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

J’ai essayé le suivant et presto changeo, ma fenêtre transparente n’était plus figée mais pouvait être déplacée !! (jetez toutes les autres solutions complexes ci-dessus …)

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