项目中需要把窗体的四角改为圆角,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");
}}
///
/// 设置窗体的圆角矩形
///
/// 需要设置的窗体
/// 圆角矩形的半径
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();
}