Winform窗體圓角以及描邊完美解決方案

zmxyzmxy1234發表於2021-05-25

圓角

專案中需要把窗體的四角改為圓角,winform窗體的圓角不是很好設定或者說繪製。在網上查詢了很多方案,最終找到了一種完美解決方案。

在網上資料中常用的是都是重繪窗體四角。但是採用的方式不一樣最後的效果也不一樣同時程式碼量帶來的體力勞動也是不一樣的。

第一種方案:重寫OnPaint或者再窗體的Paint事件中實現重繪。

這種方案有一個明顯的缺點是軟體執行時會引起窗體的閃爍,這種方案繪製的圓角有一定的紋刺,圓角不光滑。

第二種方案:採用Win32 API重繪

這種方案是比較完美的方案,沒有方案一中的缺點。程式碼如下。

public partial class FrmLogin : Form, ILoginView
    {
        private ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        public FrmLogin()
        {
            InitializeComponent();
            Load += FrmLogin_Load;
            SetFormRoundRectRgn(this, 5);    //設定圓角
        }

        private void FrmLogin_Load(object sender, EventArgs e)
        {
            this.BackColor = ColorTranslator.FromHtml("#FF5DB3AB"); //171, 179, 93
            BackgroundImage = ImageHelper.GetImage("Login\\login_bg.png");
        }}
/// <summary>
        /// 設定窗體的圓角矩形
        /// </summary>
        /// <param name="form">需要設定的窗體</param>
        /// <param name="rgnRadius">圓角矩形的半徑</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);
            Win32.DeleteObject(hRgn);
        }
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;



        #endregion

        #region Public extern methods

        [DllImport("gdi32.dll")]
        public static extern int CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3);

        [DllImport("user32.dll")]
        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);

        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

        [DllImport("user32.dll")]
        public static extern bool ReleaseCapture();

        #endregion
    }
}

窗體和控制元件描邊

實現思路:在現有的窗體和控制元件的基礎之上畫一個比原來窗體和控制元件範圍大1的矩形,描邊的寬度和顏色可以透過pen設定。具體程式碼如下

private void FrmFirstView_Paint(object sender, PaintEventArgs e)
        {
            ControlBorder_Paint(sender,e.Graphics,ColorTranslator.FromHtml("#D1D1D1"));
        }
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)));
                }
            }
            pen.Dispose();
        }

轉載於:blog.csdn.net/wangzl1163/article/d...

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章