winformscustomizationframeresizable

Resizable Form with BorderStyle None and Child with Dock Fill


My goal is to create window (using WindowsForms) that is resizable like normal Win10 windows but has no titlebar, so I can draw it myself (like UWP apps).


Solution

  • I finally found a really good working anwser by modifing this code: https://stackoverflow.com/a/29788300/15213858

    What I have now:

    public class MyForm : Form
    {
        //Window Messages
        public const uint WM_NCPAINT = 0x85;
        public const uint WM_NCCALCSIZE = 0x83;
        public const uint WM_NCHITTEST = 0x84;
    
        //RECT Structure
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left, top, right, bottom;
        }
    
        //WINDOWPOS Structure
        [StructLayout(LayoutKind.Sequential)]
        public struct WINDOWPOS
        {
            public IntPtr hwnd;
            public IntPtr hwndinsertafter;
            public int x, y, cx, cy;
            public int flags;
        }
    
        //NCCALCSIZE_PARAMS Structure
        [StructLayout(LayoutKind.Sequential)]
        public struct NCCALCSIZE_PARAMS
        {
            public RECT rgrc0, rgrc1, rgrc2;
            public WINDOWPOS lppos;
        }
    
        //Window Procedure Hook
        protected override void WndProc(ref Message m)
        {
            //Don't style window in designer...
            if (DesignMode)
                base.WndProc(ref m);
    
            //Handle Message
            switch ((uint)m.Msg)
            {
                case WM_NCCALCSIZE: WmNCCalcSize(ref m); break;
                default: base.WndProc(ref m); break;
            }
        }
    
        //WM_NCCALCSIZE
        private void WmNCCalcSize(ref Message m)
        {
    
            //Check WPARAM
            if (m.WParam != IntPtr.Zero)    //TRUE
            {
                //When TRUE, LPARAM Points to a NCCALCSIZE_PARAMS structure
                var nccsp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
    
                //We're adjusting the size of the client area here. Right now, the client area is the whole form.
                //Adding to the Top, Bottom, Left, and Right will size the client area.
                nccsp.rgrc0.top += 0;      //30-pixel top border
                nccsp.rgrc0.bottom -= 8;    //4-pixel bottom (resize) border
                nccsp.rgrc0.left += 8;      //4-pixel left (resize) border
                nccsp.rgrc0.right -= 8;     //4-pixel right (resize) border
    
                //Set the structure back into memory
                Marshal.StructureToPtr(nccsp, m.LParam, true);
            }
            else    //FALSE
            {
                //When FALSE, LPARAM Points to a RECT structure
                var clnRect = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
    
                //Like before, we're adjusting the rectangle...
                //Adding to the Top, Bottom, Left, and Right will size the client area.
                clnRect.top += 0;      //30-pixel top border
                clnRect.bottom -= 8;    //4-pixel bottom (resize) border
                clnRect.left += 8;      //4-pixel left (resize) border
                clnRect.right -= 8;     //4-pixel right (resize) border
    
                //Set the structure back into memory
                Marshal.StructureToPtr(clnRect, m.LParam, true);
            }
    
            //Return Zero
            m.Result = IntPtr.Zero;
        }
    }