How to move and resize a form without a border?
Asked Answered
T

7

41

Does anyone know how I can resize a winform when it has no border. I don't want the default border that Windows has, so I changed the property "FormBorderStyle" to "None". This removed the border, although now it can't be resized. I've figured out how to move the form around, I just need to know how to resize it.

Tarttan answered 4/4, 2010 at 17:21 Comment(0)
L
76

Some sample code that allow moving and resizing the form:

  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
      this.FormBorderStyle = FormBorderStyle.None;
      this.DoubleBuffered = true;
      this.SetStyle(ControlStyles.ResizeRedraw, true);
    }
    private const int cGrip = 16;      // Grip size
    private const int cCaption = 32;   // Caption bar height;

    protected override void OnPaint(PaintEventArgs e) {
      Rectangle rc = new Rectangle(this.ClientSize.Width - cGrip, this.ClientSize.Height - cGrip, cGrip, cGrip);
      ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc);
      rc = new Rectangle(0, 0, this.ClientSize.Width, cCaption);
      e.Graphics.FillRectangle(Brushes.DarkBlue, rc);
    }

    protected override void WndProc(ref Message m) {
      if (m.Msg == 0x84) {  // Trap WM_NCHITTEST
        Point pos = new Point(m.LParam.ToInt32());
        pos = this.PointToClient(pos);
        if (pos.Y < cCaption) {
          m.Result = (IntPtr)2;  // HTCAPTION
          return;
        }
        if (pos.X >= this.ClientSize.Width - cGrip && pos.Y >= this.ClientSize.Height - cGrip) {
          m.Result = (IntPtr)17; // HTBOTTOMRIGHT
          return;
        }
      }
      base.WndProc(ref m);
    }
  }
Lalalalage answered 4/4, 2010 at 18:28 Comment(6)
Like this I get a blue ugly bar at the top.Tananarive
If you don't want the bar on top just don't override OnPaint(). The rest of the code is solid. Thanks a bunch mate :)Plutus
To remove the top border and ONLY have the sizer grip, simply remove the last two lines of the OnPaint method: rc = new Rectangle(0, 0, this.ClientSize.Width, cCaption); e.Graphics.FillRectangle(Brushes.DarkBlue, rc);Glazer
do I need to include something special? because I cant make it work. looks like WndProc gets called but m.Msg is never equal to 0x84. .NET Framework 4.8Magavern
Nevermind. I had panel in my form with dock: fill so it was completely covering client area and mouse was always hovering over control and was never at client area thus WM_NCHITTEST was never firing... simply undocking worked.Magavern
This works but there is a lot of "shaking" of the controls inside the form when pulling left or top. The same happens to the opposite edge of the form itself. It seems the call to WM_NCHITTEST comes after the form has moved (or something) and the code kind of sets it back in place. Not a big deal but nasty looking thing. The DoubleBuffered and ResizeRedraw flags do not fix it.Okra
C
33

Here's a complete example of a customized form with all 8 points of resizing:

public partial class Form1 : Form {
public Form1() {
  InitializeComponent();
  this.FormBorderStyle = FormBorderStyle.None; // no borders
  this.DoubleBuffered = true;
  this.SetStyle(ControlStyles.ResizeRedraw, true); // this is to avoid visual artifacts
}

protected override void OnPaint(PaintEventArgs e) // you can safely omit this method if you want
{
    e.Graphics.FillRectangle(Brushes.Green, Top);
    e.Graphics.FillRectangle(Brushes.Green, Left);
    e.Graphics.FillRectangle(Brushes.Green, Right);
    e.Graphics.FillRectangle(Brushes.Green, Bottom);
}

private const int
    HTLEFT = 10,
    HTRIGHT = 11,
    HTTOP = 12,
    HTTOPLEFT = 13,
    HTTOPRIGHT = 14,
    HTBOTTOM = 15,
    HTBOTTOMLEFT = 16,
    HTBOTTOMRIGHT = 17;

const int _ = 10; // you can rename this variable if you like

Rectangle Top { get { return new Rectangle(0, 0, this.ClientSize.Width, _); } }
Rectangle Left { get { return new Rectangle(0, 0, _, this.ClientSize.Height); } }
Rectangle Bottom { get { return new Rectangle(0, this.ClientSize.Height - _, this.ClientSize.Width, _); } }
Rectangle Right { get { return new Rectangle(this.ClientSize.Width - _, 0, _, this.ClientSize.Height); } }

Rectangle TopLeft { get { return new Rectangle(0, 0, _, _); } }
Rectangle TopRight { get { return new Rectangle(this.ClientSize.Width - _, 0, _, _); } }
Rectangle BottomLeft { get { return new Rectangle(0, this.ClientSize.Height - _, _, _); } }
Rectangle BottomRight { get { return new Rectangle(this.ClientSize.Width - _, this.ClientSize.Height - _, _, _); } }


protected override void WndProc(ref Message message)
{
    base.WndProc(ref message);

    if (message.Msg == 0x84) // WM_NCHITTEST
    {
        var cursor = this.PointToClient(Cursor.Position);

        if (TopLeft.Contains(cursor)) message.Result = (IntPtr)HTTOPLEFT;
   else if (TopRight.Contains(cursor)) message.Result = (IntPtr)HTTOPRIGHT;
   else if (BottomLeft.Contains(cursor)) message.Result = (IntPtr)HTBOTTOMLEFT;
   else if (BottomRight.Contains(cursor)) message.Result = (IntPtr)HTBOTTOMRIGHT;

   else if (Top.Contains(cursor)) message.Result = (IntPtr)HTTOP;
   else if (Left.Contains(cursor)) message.Result = (IntPtr)HTLEFT;
   else if (Right.Contains(cursor)) message.Result = (IntPtr)HTRIGHT;
   else if (Bottom.Contains(cursor)) message.Result = (IntPtr)HTBOTTOM;
    }
}}
Contraindicate answered 28/8, 2015 at 0:32 Comment(2)
a little error. edges and corners are overlapping so for example top one that is returning new Rectangle(0, 0, this.ClientSize.Width, _); must return new Rectangle(_, 0, this.ClientSize.Width - _, _); in order to leave small square for corner square... other edges will also have offsets accordinglyMagavern
The "error" doesn't make a difference since the corners are checked before the edgesScout
M
12

"Sizer" is the light blue panel in the right bottom corner

screenshot of Sizer

    int Mx;
    int My;
    int Sw;
    int Sh;

    bool mov;

    void SizerMouseDown(object sender, MouseEventArgs e)
    {
        mov = true;
        My = MousePosition.Y;
        Mx = MousePosition.X;
        Sw = Width;
        Sh = Height;
    }

    void SizerMouseMove(object sender, MouseEventArgs e)
    {
        if (mov == true) {
            Width = MousePosition.X - Mx + Sw;
            Height = MousePosition.Y - My + Sh;
        }
    }

    void SizerMouseUp(object sender, MouseEventArgs e)
    {
        mov = false;
    }
Mclaughlin answered 16/2, 2017 at 23:30 Comment(1)
A nice solution! However instead of a blue panel I used a small picture box showing an image of the resize dot pattern, with the Cursor property set to "SizeAll" so that the cursor changes to resize arrows when you are over the box.Suisse
V
2

(elaborate : in comment 2)

Resize "Form" From All place And Move it >>> Full Code <<<<<

//First u most to add this Class

 class ReSize
     {

        private bool Above, Right, Under, Left, Right_above, Right_under, Left_under, Left_above;


        int Thickness=6;  //Thickness of border  u can cheang it
        int Area = 8;     //Thickness of Angle border 


        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="thickness">set thickness of form border</param>
        public ReSize(int thickness)
        {
            Thickness = thickness;
        }

        /// <summary>
        /// Constructor set thickness of form border=1
        /// </summary>
        public ReSize()
        {
            Thickness = 10;
        }

        //Get Mouse Position
        public  string getMosuePosition(Point mouse, Form form)
        {
            bool above_underArea = mouse.X > Area && mouse.X < form.ClientRectangle.Width - Area; /* |\AngleArea(Left_Above)\(=======above_underArea========)/AngleArea(Right_Above)/| */ //Area===>(==)
            bool right_left_Area = mouse.Y > Area && mouse.Y < form.ClientRectangle.Height - Area; 

            bool _Above=mouse.Y <= Thickness;  //Mouse in Above All Area
            bool _Right= mouse.X >= form.ClientRectangle.Width - Thickness;
            bool _Under=mouse.Y >= form.ClientRectangle.Height - Thickness;
            bool _Left=mouse.X <= Thickness;

            Above = _Above && (above_underArea); if (Above) return "a";   /*Mouse in Above All Area WithOut Angle Area */
            Right = _Right && (right_left_Area); if (Right) return "r";
            Under = _Under && (above_underArea); if (Under) return "u";
            Left = _Left && (right_left_Area);   if (Left) return "l";


            Right_above =/*Right*/ (_Right && (!right_left_Area)) && /*Above*/ (_Above && (!above_underArea));   if (Right_above) return "ra";     /*if Mouse  Right_above */
            Right_under =/* Right*/((_Right) && (!right_left_Area)) && /*Under*/(_Under && (!above_underArea));  if (Right_under) return "ru";     //if Mouse  Right_under 
            Left_under = /*Left*/((_Left) && (!right_left_Area)) && /*Under*/ (_Under && (!above_underArea));    if (Left_under) return "lu";      //if Mouse  Left_under
            Left_above = /*Left*/((_Left) && (!right_left_Area)) && /*Above*/(_Above && (!above_underArea));     if (Left_above) return "la";      //if Mouse  Left_above

            return "";

        }


    }

Then Form cs

 public partial class FormGDI : Form
    {

        ReSize resize = new ReSize();     // ReSize Class "/\" To Help Resize Form <None Style>


        public FormGDI()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.ResizeRedraw, true);

        }


        private const int cGrip = 16;      // Grip size
        private const int cCaption = 32;   // Caption bar height;

        protected override void OnPaint(PaintEventArgs e)
        {
            //this if you want to draw   (if)

            Color theColor = Color.FromArgb(10, 20, 20, 20);
            theColor = Color.DarkBlue;
            int BORDER_SIZE = 4;
            ControlPaint.DrawBorder(e.Graphics, ClientRectangle,
                                         theColor, BORDER_SIZE, ButtonBorderStyle.Dashed,
                                         theColor, BORDER_SIZE, ButtonBorderStyle.Dashed,
                                         theColor, BORDER_SIZE, ButtonBorderStyle.Dashed,
                                         theColor, BORDER_SIZE, ButtonBorderStyle.Dashed);


            Rectangle rc = new Rectangle(this.ClientSize.Width - cGrip, this.ClientSize.Height - cGrip, cGrip, cGrip);
            ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc);
            rc = new Rectangle(0, 0, this.ClientSize.Width, cCaption);
            e.Graphics.FillRectangle(Brushes.DarkBlue, rc);



            base.OnPaint(e);
        }


        //set MinimumSize to Form
        public override Size MinimumSize
        {
            get
            {
                return base.MinimumSize;
            }
            set
            {
                base.MinimumSize = new Size(179, 51); 
            }
        }

        //
        //override  WndProc  
        //
        protected override void WndProc(ref Message m)
        {
            //****************************************************************************

            int x = (int)(m.LParam.ToInt64() & 0xFFFF);               //get x mouse position
            int y = (int)((m.LParam.ToInt64() & 0xFFFF0000) >> 16);   //get y mouse position  you can gave (x,y) it from "MouseEventArgs" too
            Point pt = PointToClient(new Point(x, y));

            if (m.Msg == 0x84)
            {
                switch (resize.getMosuePosition(pt, this))
                {
                    case "l": m.Result = (IntPtr)10; return;  // the Mouse on Left Form
                    case "r": m.Result = (IntPtr)11; return;  // the Mouse on Right Form
                    case "a": m.Result = (IntPtr)12; return;
                    case "la": m.Result = (IntPtr)13; return;
                    case "ra": m.Result = (IntPtr)14; return;
                    case "u": m.Result = (IntPtr)15; return;
                    case "lu": m.Result = (IntPtr)16; return;
                    case "ru": m.Result = (IntPtr)17; return; // the Mouse on Right_Under Form
                    case "": m.Result = pt.Y < 32 /*mouse on title Bar*/ ? (IntPtr)2 : (IntPtr)1; return;  

                }
            }

              base.WndProc(ref m);

        }

    }
Vespine answered 21/9, 2014 at 22:53 Comment(3)
Can you elaborate on how this answers the question? Thanks!Automat
elaborate : first id make resize class it's have one method this method to determine position of mouse form calculate (point mouse) and (Form form)to get width and height of form then and the most importanst WndProc Override Method this method have ref Message m param when m.msg=0x84value u can set m.result=10 that mean you call form to resize from left and m.Result=11 call form from Right and ....to 17 but when m.Result=2 you call to move the form` and when m.Result=1that mean call don't do any thingVespine
it helps, but it doens't handle scrolling, it creates new border 'lines' through the form when scrollingExcessive
T
1

The simplest way is to assign mouse events to the form or the title bar, whatever you want to be hold for moving. You can move a BorderLess Form with assigning these methods to there events as names in method.

    int movX,movY;
    bool isMoving;

    private void onMouseDown(object sender, MouseEventArgs e)  
    {
         // Assign this method to mouse_Down event of Form or Panel,whatever you want
        isMoving = true;
        movX = e.X;
        movY = e.Y;
    }

    private void onMouseMove(object sender, MouseEventArgs e)
    {
         // Assign this method to Mouse_Move event of that Form or Panel
        if (isMoving)
        {
            this.SetDesktopLocation(MousePosition.X - movX, MousePosition.Y - movY);
        }
    }

    private void onMouseUp(object sender, MouseEventArgs e)
    {
       // Assign this method to Mouse_Up event of Form or Panel.
        isMoving = false;
    }
Tasty answered 4/3, 2019 at 15:1 Comment(1)
moxY that is located line 2 should be replaced with movYMeredeth
P
0

If you don't mind a short bar at the top, you can use a "regular" sizable form with the .ControlBox set to false and .Text (the caption bar at the top) set to an empty string.

You'll end up with a resizable form that looks like the Task Manager when you double-click on a chart. The advantage of this method is that when you resize it from the left, the right border does not jerk. The same is also when you resize it from the top.

this.FormBorderStyle = FormBorderStyle.Sizable;
this.ControlBox = false;
this.Text = "";
Pluri answered 18/7, 2020 at 2:7 Comment(0)
C
-3

(1) FormBorderStyle= Sizable or SizableToolWindows enter image description here

(2) clear text in form text

enter image description here

Cosh answered 14/12, 2022 at 19:33 Comment(2)
and make ControlBox=falseCosh
You know that you can edit your post to improve it, don't you?Babble

© 2022 - 2024 — McMap. All rights reserved.