web-dev-qa-db-fra.com

Rendre une forme sans bordure mobile?

Existe-t-il un moyen de rendre un formulaire sans bordure (FormBorderStyle est défini sur "aucun"), déplaçable lorsque la souris est cliquée sur le formulaire comme s'il y avait une bordure?

92
user

This article sur CodeProject détaille une technique. Se résume essentiellement à:

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

Cela correspond essentiellement exactement à la saisie de la barre de titre d'une fenêtre, du point de vue du gestionnaire de fenêtres.

205
Joey

Ne rendons pas les choses plus difficiles qu’elles doivent être. 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 amènent Windows à penser qu'un contrôle sur un formulaire est le formulaire réel.

Cela étant dit, voici mon extrait. Je l'utilise tout le temps. Je voudrais également noter que vous ne devriez pas utiliser this.Invalidate (); comme d'autres aiment le faire, car dans certains cas, le formulaire scintille. Et dans certains cas, cela aussi. Actualiser. 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) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);

            this.Update();
        }
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        mouseDown = false;
    }
37
jay_t55

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

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 avez cliqué sur le panneau, votre formulaire se déplacera 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(e.X, e.Y);
}

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(p.X - this._start_point.X,p.Y - this._start_point.Y);     
  }
}
18
junmats

WPF seulement


je n'ai pas le code exact à portée de main, mais dans un projet récent, je pense avoir utilisé l'événement MouseDown.

frmBorderless.DragMove();

Méthode Window.DragMove (MSDN)

11
Chris

Ref. 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);
}
8
Gnana Akilan

Il n'y a pas de propriété que vous pouvez retourner pour que cela se produise comme par magie. Examinez les événements du formulaire et il devient assez simple de l'implémenter en définissant this.Top et this.Left. Plus précisément, vous voudrez regarder MouseDown, MouseUp et MouseMove.

4
Matthew Scharley
public Point mouseLocation;
private void frmInstallDevice_MouseDown(object sender, MouseEventArgs e)
{
  mouseLocation = new Point(-e.X, -e.Y);
}

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 ...

4
Syed Ali

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

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

AddDrag(NameOfControl);
3
Ricky Divjakovski

https://social.msdn.Microsoft.com/Forums/vstudio/en-US/d803d869-68e6-46ff-9ff1-fabf78d6393c/how-to-make-a-borderless-form-in-c-for-=?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);
      }
}
2
Abhirath Mahipal

Le moyen le plus simple est:

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

if (e.Button == MouseButtons.Left){
    Left += e.X;
    Top += e.Y;`
}
1
user7500524

Certaines réponses ne permettant pas aux contrôles enfants d'être déplaçables, j'ai créé une petite classe d'assistance . Elle doit être passée au formulaire de niveau supérieur. 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);
        }
    }
}
1
Sebastian

De même, si vous devez utiliser DoubleClick et rendre votre formulaire plus grand/plus petit, vous pouvez utiliser la Première réponse, créer une variable int globale, ajouter 1 chaque fois que l'utilisateur clique sur le composant que vous utilisez pour le faire glisser. Si variable == 2, agrandissez/réduisez votre formulaire. Utilisez également une minuterie toutes les demi-secondes ou toutes les secondes pour créer votre variable = 0;

1
Billy Xd

J'essayais de rendre mobile une forme de fenêtre contenant un contrôle WPF Element Host et un contrôle WPF User. 

Je me suis retrouvé avec un panneau de pile appelé StackPanel dans mon contrôle utilisateur WPF, ce qui semblait logique d'essayer de cliquer sur pour déplacer. Essayer de manipuler le code de junmats a fonctionné lorsque j'ai déplacé la souris lentement, mais si je l'avais déplacée plus rapidement, la souris s'éloignerait du formulaire et le formulaire resterait coincé quelque part au milieu du mouvement. 

Cela améliorait sa réponse à ma situation en utilisant CaptureMouse et ReleaseCaptureMouse et maintenant la souris ne s'éloignait pas du formulaire tout en le déplaçant même si je le déplaçais 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)(p.X - this._start_point.X), (int)(p.Y - this._start_point.Y));
    }
}

    //Global variables;
    private Point _start_point = new Point(0, 0);
1
Mike Sage

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();
}
1
Neeraj Kumar Das

L'ajout d'un gestionnaire d'événements MouseLeftButtonDown à MainWindow a fonctionné pour moi.

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

base.OnMouseLeftButtonDown(e);
this.DragMove();
0
Aparna Ratheesh

J'ai essayé ce qui suit et le changement a commencé, ma fenêtre transparente n'était plus figée mais pouvait être déplacée !! (Jeter toutes les autres solutions complexes ci-dessus ...)

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

Cela a fonctionné pour moi.

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        _mouseLoc = e.Location;
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            int dx = e.Location.X - _mouseLoc.X;
            int dy = e.Location.Y - _mouseLoc.Y;
            this.Location = new Point(this.Location.X + dx, this.Location.Y + dy);
        }
    }
0
Sudhananda Biswas

J'étends la solution de jay_t55 avec une méthode supplémentaire, ToolStrip1_MouseLeave, qui gère le cas où la souris se déplace rapidement et quitte la région.

private bool mouseDown;
private Point lastLocation;

private void ToolStrip1_MouseDown(object sender, MouseEventArgs e) {
    mouseDown = true;
    lastLocation = e.Location;
}

private void ToolStrip1_MouseMove(object sender, MouseEventArgs e) {
    if (mouseDown) {
        this.Location = new Point(
            (this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);

        this.Update();
    }
}

private void ToolStrip1_MouseUp(object sender, MouseEventArgs e) {
    mouseDown = false;
}

private void ToolStrip1_MouseLeave(object sender, EventArgs e) {
    mouseDown = false;
}
0
Michael