Make a borderless form movable?

196,832

Solution 1

This article on CodeProject details a technique. Is basically boils down to:

public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;

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

This essentially does exactly the same as grabbing the title bar of a window, from the window manager's point of view.

Solution 2

Let's not make things any more difficult than they need to be. I've come across so many snippets of code that allow you to drag a form around (or another Control). And many of them have their own drawbacks/side effects. Especially those ones where they trick Windows into thinking that a Control on a form is the actual form.

That being said, here is my snippet. I use it all the time. I'd also like to note that you should not use this.Invalidate(); as others like to do because it causes the form to flicker in some cases. And in some cases so does this.Refresh. Using this.Update, I have not had any flickering issues:

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

Solution 3

Another simpler way to do the same thing.

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

Solution 4

use MouseDown, MouseMove and MouseUp. You can set a variable flag for that. I have a sample, but I think you need to revise.

I am coding the mouse action to a panel. Once you click the panel, your form will move with it.

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

Solution 5

WPF only


don't have the exact code to hand, but in a recent project I think I used MouseDown event and simply put this:

frmBorderless.DragMove();

Window.DragMove Method (MSDN)

Share:
196,832
user
Author by

user

Updated on January 04, 2021

Comments

  • user
    user over 3 years

    Is there a way to make a form that has no border (FormBorderStyle is set to "none") movable when the mouse is clicked down on the form just as if there was a border?

  • user
    user over 14 years
    I figured I would have to use those events but I am not sure what to do with them. When the MouseDown event is called, how do I allow the form to be moved?
  • Rich
    Rich over 14 years
    That's WPF, though. Ok, the OP didn't exactly specify this.
  • Chris
    Chris over 14 years
    Yeah, which is something I forgot about the project I was doing. I just looked at Forms and it's not available. Sorry!
  • Bijendra Singh
    Bijendra Singh over 14 years
    On mouse down you set a flag and store the base coordinates. On mouse move - if the flag is set - you adjust the top and left by the offset of the new mouse coordinates. On mouse up you clear the flag.
  • Rich
    Rich over 14 years
    Still, you can do this with the Windows API fairly easy which doesn't depend on still getting mouse events. This method does fail if you grab at a pixel at the very top edge of the form and drag upwards, for example.
  • Rich
    Rich over 14 years
    It is. As said elsewhere already, this relies on the form still generating MouseMove events. As a simple case, suppose you grad the Form at the top-most pixel row and drag upwards. Nothing will happen, although the form will jump around as soon as you move the mouse back onto it.
  • Technivorous
    Technivorous about 9 years
    dang winforms... looked for this answer for nearly two hours.... im new to c# though, you did me wonders!
  • Rembunator
    Rembunator almost 9 years
    @Chris This worked for me in a WPF project. Thanks for not deleting the answer.
  • Thomas Wagenaar
    Thomas Wagenaar over 8 years
    Anyone of making it possible that you can move the form by holding a specific tool (eg a label).
  • EasyBB
    EasyBB over 8 years
    This is exactly the way I thought of, my only issue was it was buggy as all hell until I read how you did it. Thanks mate
  • dbrree
    dbrree about 8 years
    This doesn't work for me at all. Code runs just fine, everything is correct, and my window is still just sitting there. Any ideas?
  • Mmm
    Mmm almost 8 years
    This one worked better for me than the amazing tiny snippet above the overrides WndProc. Mind you, the WndProc did work ... it just stopped other things from working. Thanks!
  • Reza Taibur
    Reza Taibur almost 8 years
    You can also use "e.Location" instead of Control.MousePosition
  • Sebastiano
    Sebastiano almost 8 years
    If double-clicked, the form gets maximized. Also read here and there that this breaks right-clicking.
  • Remon Ramy
    Remon Ramy over 7 years
    @dbrree You probably copied the code, that won't work as Form1_MouseDown is not assigned to the actual MouseDown event of Form1.
  • Paul Nelson
    Paul Nelson over 7 years
    If you have a label or an icon (or any other foreground objects!) where you are grabbing the form to drag, add a mousedown event to these items too. Form events can't see through form objects.
  • Jamshaid K.
    Jamshaid K. about 7 years
    This code works, but how is it easy to understand? I don't know about anything in this code segment besides the switch statement!
  • Sylverdrag
    Sylverdrag almost 7 years
    Probably the best option here as it works nicely and doesn't rely on WndProc (can easily be ported to other platforms with Mono). Can be improved by changing the state to maximized/normal if Y<10
  • Richard Peck
    Richard Peck almost 7 years
    You need to add this.MouseDown += ... to the Main() function for the form
  • Roger Deep
    Roger Deep over 6 years
    It does not work on mono, changed .net 4.5.2 to mono/net 4.5 and still does not work. Trying to find a solution now.
  • Justin
    Justin over 6 years
    Worked like a charm for me!!!! I had to move the event handling to the panel I was putting in place of the form but it worked
  • Dave Cousineau
    Dave Cousineau over 5 years
    this is good. a couple issues. 1) gets messed up by double clicks. only set mouseDown = true if e.Clicks == 1. 2) this doesn't work if you have controls (panels) on your form. what I do is hook the events of most controls on the form, except for some kinds that don't make sense like buttons.
  • Dimuth Ruwantha
    Dimuth Ruwantha almost 5 years
    I was looking for this for weeks. I was almost drawing this manually calculating the positions previously.
  • Syroot
    Syroot about 4 years
    This answer is for WPF, the question is about WinForms.
  • Sorry IwontTell
    Sorry IwontTell almost 4 years
    This answer has most points. I use his answer and got it why He has most stars.
  • Sorry IwontTell
    Sorry IwontTell almost 4 years
    This works great except that some mouse event handlers can't accept left button click.
  • Andreas Rejbrand
    Andreas Rejbrand almost 4 years
    This is WM_NCHITTEST in disguise.
  • Nick Juelich
    Nick Juelich over 3 years
    Absolutely the right solution here, even in 2021
  • Sudhananda Biswas
    Sudhananda Biswas almost 3 years
    Yeah, if simple works fine why need to go complex. 🤓