重写Checkbox 改写选择框的大小
/* 作者:Starts_2000 * 日期:2009-07-30 * 网站:http://www.csharpwin.com CS 程序员之窗。 * 你可以免费使用或修改以下代码,但请保留版权信息。 * 具体请查看 CS程序员之窗开源协议(http://www.csharpwin.com/csol.html)。 */ [ToolboxBitmap(typeof(CheckBox))] public class CheckBoxEx : CheckBox { private Color _baseColor = Color.FromArgb(51, 161, 224); private ControlState _controlState; private static readonly ContentAlignment RightAlignment = ContentAlignment.TopRight | ContentAlignment.BottomRight | ContentAlignment.MiddleRight; private static readonly ContentAlignment LeftAligbment = ContentAlignment.TopLeft | ContentAlignment.BottomLeft | ContentAlignment.MiddleLeft; public CheckBoxEx() : base() { SetStyle( ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, true); } public Color BaseColor { get { return _baseColor; } set { _baseColor = value; base.Invalidate(); } } protected virtual int DefaultCheckButtonWidth { get { return 30; } } internal ControlState ControlState { get { return _controlState; } set { if (_controlState != value) { _controlState = value; base.Invalidate(); } } } protected override void OnMouseEnter(EventArgs e) { base.OnMouseEnter(e); ControlState = ControlState.Hover; } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); ControlState = ControlState.Normal; } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (e.Button == MouseButtons.Left && e.Clicks == 1) { ControlState = ControlState.Pressed; } } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (e.Button == MouseButtons.Left && e.Clicks == 1) { if (ClientRectangle.Contains(e.Location)) { ControlState = ControlState.Hover; } else { ControlState = ControlState.Normal; } } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); base.OnPaintBackground(e); Graphics g = e.Graphics; Rectangle checkButtonRect; Rectangle textRect; CalculateRect(out checkButtonRect, out textRect); g.SmoothingMode = SmoothingMode.AntiAlias; Color backColor = ControlPaint.Light(_baseColor); Color borderColor; Color innerBorderColor; Color checkColor; bool hover = false; if (Enabled) { switch (ControlState) { case ControlState.Hover: borderColor = _baseColor; innerBorderColor = _baseColor; checkColor = GetColor(_baseColor, 0, 35, 24, 9); hover = true; break; case ControlState.Pressed: borderColor = _baseColor; innerBorderColor = GetColor(_baseColor, 0, -13, -8, -3); checkColor = GetColor(_baseColor, 0, -35, -24, -9); hover = true; break; default: borderColor = _baseColor; innerBorderColor = Color.Empty; checkColor = _baseColor; break; } } else { borderColor = SystemColors.ControlDark; innerBorderColor = SystemColors.ControlDark; checkColor = SystemColors.ControlDark; } using (SolidBrush brush = new SolidBrush(Color.White)) { g.FillRectangle(brush, checkButtonRect); } if (hover) { using (Pen pen = new Pen(innerBorderColor, 2F)) { g.DrawRectangle(pen, checkButtonRect); } } switch (CheckState) { case CheckState.Checked: DrawCheckedFlag( g, checkButtonRect, checkColor); break; case CheckState.Indeterminate: checkButtonRect.Inflate(-1, -1); using (GraphicsPath path = new GraphicsPath()) { path.AddEllipse(checkButtonRect); using (PathGradientBrush brush = new PathGradientBrush(path)) { brush.CenterColor = checkColor; brush.SurroundColors = new Color[] { Color.White }; Blend blend = new Blend(); blend.Positions = new float[] { 0f, 0.4f, 1f }; blend.Factors = new float[] { 0f, 0.3f, 1f }; brush.Blend = blend; g.FillEllipse(brush, checkButtonRect); } } checkButtonRect.Inflate(1, 1); break; } using (Pen pen = new Pen(borderColor)) { g.DrawRectangle(pen, checkButtonRect); } Color textColor = Enabled ? ForeColor : SystemColors.GrayText; TextRenderer.DrawText( g, Text, Font, textRect, textColor, GetTextFormatFlags(TextAlign, RightToLeft == RightToLeft.Yes)); } private void CalculateRect( out Rectangle checkButtonRect, out Rectangle textRect) { checkButtonRect = new Rectangle( 0, 0, DefaultCheckButtonWidth, DefaultCheckButtonWidth); textRect = Rectangle.Empty; bool bCheckAlignLeft = (int)(LeftAligbment & CheckAlign) != 0; bool bCheckAlignRight = (int)(RightAlignment & CheckAlign) != 0; bool bRightToLeft = RightToLeft == RightToLeft.Yes; if ((bCheckAlignLeft && !bRightToLeft) || (bCheckAlignRight && bRightToLeft)) { switch (CheckAlign) { case ContentAlignment.TopRight: case ContentAlignment.TopLeft: checkButtonRect.Y = 2; break; case ContentAlignment.MiddleRight: case ContentAlignment.MiddleLeft: checkButtonRect.Y = (Height - DefaultCheckButtonWidth) / 2; break; case ContentAlignment.BottomRight: case ContentAlignment.BottomLeft: checkButtonRect.Y = Height - DefaultCheckButtonWidth - 2; break; } checkButtonRect.X = 1; textRect = new Rectangle( checkButtonRect.Right + 2, 0, Width - checkButtonRect.Right - 4, Height); } else if ((bCheckAlignRight && !bRightToLeft) || (bCheckAlignLeft && bRightToLeft)) { switch (CheckAlign) { case ContentAlignment.TopLeft: case ContentAlignment.TopRight: checkButtonRect.Y = 2; break; case ContentAlignment.MiddleLeft: case ContentAlignment.MiddleRight: checkButtonRect.Y = (Height - DefaultCheckButtonWidth) / 2; break; case ContentAlignment.BottomLeft: case ContentAlignment.BottomRight: checkButtonRect.Y = Height - DefaultCheckButtonWidth - 2; break; } checkButtonRect.X = Width - DefaultCheckButtonWidth - 1; textRect = new Rectangle( 2, 0, Width - DefaultCheckButtonWidth - 6, Height); } else { switch (CheckAlign) { case ContentAlignment.TopCenter: checkButtonRect.Y = 2; textRect.Y = checkButtonRect.Bottom + 2; textRect.Height = Height - DefaultCheckButtonWidth - 6; break; case ContentAlignment.MiddleCenter: checkButtonRect.Y = (Height - DefaultCheckButtonWidth) / 2; textRect.Y = 0; textRect.Height = Height; break; case ContentAlignment.BottomCenter: checkButtonRect.Y = Height - DefaultCheckButtonWidth - 2; textRect.Y = 0; textRect.Height = Height - DefaultCheckButtonWidth - 6; break; } checkButtonRect.X = (Width - DefaultCheckButtonWidth) / 2; textRect.X = 2; textRect.Width = Width - 4; } } private void DrawCheckedFlag(Graphics graphics, Rectangle rect, Color color) { PointF[] points = new PointF[3]; points[0] = new PointF( rect.X + rect.Width / 4.5f, rect.Y + rect.Height / 2.5f); points[1] = new PointF( rect.X + rect.Width / 2.5f, rect.Bottom - rect.Height / 3f); points[2] = new PointF( rect.Right - rect.Width / 4.0f, rect.Y + rect.Height / 4.5f); using (Pen pen = new Pen(color, 2F)) { graphics.DrawLines(pen, points); } } private Color GetColor(Color colorBase, int a, int r, int g, int b) { int a0 = colorBase.A; int r0 = colorBase.R; int g0 = colorBase.G; int b0 = colorBase.B; if (a + a0 > 255) { a = 255; } else { a = Math.Max(a + a0, 0); } if (r + r0 > 255) { r = 255; } else { r = Math.Max(r + r0, 0); } if (g + g0 > 255) { g = 255; } else { g = Math.Max(g + g0, 0); } if (b + b0 > 255) { b = 255; } else { b = Math.Max(b + b0, 0); } return Color.FromArgb(a, r, g, b); } internal static TextFormatFlags GetTextFormatFlags( ContentAlignment alignment, bool rightToleft) { TextFormatFlags flags = TextFormatFlags.WordBreak | TextFormatFlags.SingleLine; if (rightToleft) { flags |= TextFormatFlags.RightToLeft | TextFormatFlags.Right; } switch (alignment) { case ContentAlignment.BottomCenter: flags |= TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter; break; case ContentAlignment.BottomLeft: flags |= TextFormatFlags.Bottom | TextFormatFlags.Left; break; case ContentAlignment.BottomRight: flags |= TextFormatFlags.Bottom | TextFormatFlags.Right; break; case ContentAlignment.MiddleCenter: flags |= TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter; break; case ContentAlignment.MiddleLeft: flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.Left; break; case ContentAlignment.MiddleRight: flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.Right; break; case ContentAlignment.TopCenter: flags |= TextFormatFlags.Top | TextFormatFlags.HorizontalCenter; break; case ContentAlignment.TopLeft: flags |= TextFormatFlags.Top | TextFormatFlags.Left; break; case ContentAlignment.TopRight: flags |= TextFormatFlags.Top | TextFormatFlags.Right; break; } return flags; } } /// <summary> /// 控件的状态。 /// </summary> internal enum ControlState { /// <summary> /// 正常。 /// </summary> Normal, /// <summary> /// 鼠标进入。 /// </summary> Hover, /// <summary> /// 鼠标按下。 /// </summary> Pressed, /// <summary> /// 获得焦点。 /// </summary> Focused, }