Perfect solution for WinForm form form fillet and stroke



In the project, the four corners of the form need to be changed to rounded corners. The rounded corners of WinForm form form are not well set or drawn. I found many solutions on the Internet and finally found a perfect solution.

Commonly used in online materials is to redraw the four corners of the form. However, different methods are adopted, and the final effect is also different. At the same time, the physical labor brought by the amount of code is also different.

The first scheme: Rewrite onpaint or redraw in the paint event of the form.

An obvious disadvantage of this scheme is that the window flickers when the software runs. The rounded corners drawn by this scheme have certain thorns and are not smooth.

The second scheme: redrawing using Win32 API

This scheme is a perfect scheme without the shortcomings of scheme 1. The code is as follows.

public partial class FrmLogin : Form, ILoginView
        private ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        public FrmLogin()
            Load += FrmLogin_Load;
            SetFormRoundRectRgn(this, 5);    // Set fillet
        private void FrmLogin_Load(object sender, EventArgs e)
            this.BackColor = ColorTranslator.FromHtml("#FF5DB3AB"); //171, 179, 93
            BackgroundImage = ImageHelper.GetImage("Login\\login_bg.png");
/// <summary>
        ///Sets the rounded rectangle of the form
        /// </summary>
        ///< param name = "form" > form to be set < / param >
        ///< param name = "rgnradius" > radius of rounded rectangle < / param >
        public static void SetFormRoundRectRgn(Form form, int rgnRadius)
            int hRgn = 0;
            hRgn = Win32.CreateRoundRectRgn(0, 0, form.Width + 1, form.Height + 1, rgnRadius, rgnRadius);
            Win32.SetWindowRgn(form.Handle, hRgn, true);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace UClass.View.Login
    public class Win32
        #region Window Const
        public const int WM_ERASEBKGND = 0x0014;
        public const int WM_LBUTTONDOWN = 0x0201;
        public const int WM_LBUTTONUP = 0x0202;
        public const int WM_LBUTTONDBLCLK = 0x0203;
        public const int WM_WINDOWPOSCHANGING = 0x46;
        public const int WM_PAINT = 0xF;
        public const int WM_CREATE = 0x0001;
        public const int WM_ACTIVATE = 0x0006;
        public const int WM_NCCREATE = 0x0081;
        public const int WM_NCCALCSIZE = 0x0083;
        public const int WM_NCPAINT = 0x0085;
        public const int WM_NCACTIVATE = 0x0086;
        public const int WM_NCLBUTTONDOWN = 0x00A1;
        public const int WM_NCLBUTTONUP = 0x00A2;
        public const int WM_NCLBUTTONDBLCLK = 0x00A3;
        public const int WM_NCMOUSEMOVE = 0x00A0;
        public const int WM_NCHITTEST = 0x0084;
        public const int HTLEFT = 10;
        public const int HTRIGHT = 11;
        public const int HTTOP = 12;
        public const int HTTOPLEFT = 13;
        public const int HTTOPRIGHT = 14;
        public const int HTBOTTOM = 15;
        public const int HTBOTTOMLEFT = 0x10;
        public const int HTBOTTOMRIGHT = 17;
        public const int HTCAPTION = 2;
        public const int HTCLIENT = 1;
        public const int WM_FALSE = 0;
        public const int WM_TRUE = 1;
        #region Public extern methods
        public static extern int CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3);
        public static extern int SetWindowRgn(IntPtr hwnd, int hRgn, Boolean bRedraw);
        [DllImport("gdi32.dll", EntryPoint = "DeleteObject", CharSet = CharSet.Ansi)]
        public static extern int DeleteObject(int hObject);
        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
        public static extern bool ReleaseCapture();

Forms and controls stroke

Implementation idea: draw a rectangle 1 larger than the original form and control based on the existing form and control. The width and color of stroke can be set through pen. The specific codes are as follows

private void FrmFirstView_Paint(object sender, PaintEventArgs e)
private void ControlBorder_Paint(object sender, Graphics g, Color color)
            Pen pen = new Pen(Color.FromArgb(255, color), 1f);
            foreach (System.Windows.Forms.Control ctr in this.pnlContent.Controls)
                if (ctr is Control.Controls.TextBoxs.TextBoxEx || ctr is ComboBox)
                    g.DrawRectangle(pen, new Rectangle(new Point(ctr.Location.X - 1, ctr.Location.Y - 1), new Size(ctr.Size.Width + 1, ctr.Size.Height + 1)));

Reproduced at:…