【问题标题】:How do you change the color of the border on a group box?如何更改组框边框的颜色?
【发布时间】:2010-09-09 17:45:28
【问题描述】:

在 C#.NET 中,我尝试以编程方式更改组框中边框的颜色。

更新:在我们切换到 .NET 之前,当我在一个 winforms 系统上工作时被问到这个问题。

【问题讨论】:

  • @Amy Check user1944617 回答,恕我直言,接受一个真的很好,也很优越。刚刚尝试过并与默认组框设计完美契合。

标签: c# winforms user-interface controls groupbox


【解决方案1】:

我不确定这是否适用于所有情况,但多亏了这个线程,我们使用以下方式快速以编程方式挂钩到 Paint 事件:

GroupBox box = new GroupBox();
[...]
box.Paint += delegate(object o, PaintEventArgs p)
{
    p.Graphics.Clear(someColorHere);
};

干杯!

【讨论】:

    【解决方案2】:

    在上一个答案的基础上,一个更好的解决方案,包括组框的标签:

    groupBox1.Paint += PaintBorderlessGroupBox;
    
    private void PaintBorderlessGroupBox(object sender, PaintEventArgs p)
    {
      GroupBox box = (GroupBox)sender;
      p.Graphics.Clear(SystemColors.Control);
      p.Graphics.DrawString(box.Text, box.Font, Brushes.Black, 0, 0);
    }
    

    您可能想调整文本的 x/y,但对我来说这正好。

    【讨论】:

    • 谢谢@Mick Bruno,你为我节省了很多时间:)
    • 谢谢!要删除边框,请像我一样使用box.Parent.BackColor
    【解决方案3】:

    只需将任何对象(不仅仅是按钮)上的绘制动作设置为此方法即可绘制边框。

        private void UserControl1_Paint(object sender, PaintEventArgs e)
        {
            ControlPaint.DrawBorder(e.Graphics, this.ClientRectangle, Color.Red, ButtonBorderStyle.Solid);
    
        }
    

    它仍然不会像原来的那样漂亮和圆润,但它要简单得多。

    【讨论】:

      【解决方案4】:

      只需添加绘画事件。

          private void groupBox1_Paint(object sender, PaintEventArgs e)
          {
              GroupBox box = sender as GroupBox;
              DrawGroupBox(box, e.Graphics, Color.Red, Color.Blue);
          }
      
      
          private void DrawGroupBox(GroupBox box, Graphics g, Color textColor, Color borderColor)
          {
              if (box != null)
              {
                  Brush textBrush = new SolidBrush(textColor);
                  Brush borderBrush = new SolidBrush(borderColor);
                  Pen borderPen = new Pen(borderBrush);
                  SizeF strSize = g.MeasureString(box.Text, box.Font);
                  Rectangle rect = new Rectangle(box.ClientRectangle.X,
                                                 box.ClientRectangle.Y + (int)(strSize.Height / 2),
                                                 box.ClientRectangle.Width - 1,
                                                 box.ClientRectangle.Height - (int)(strSize.Height / 2) - 1);
      
                  // Clear text and border
                  g.Clear(this.BackColor);
      
                  // Draw text
                  g.DrawString(box.Text, box.Font, textBrush, box.Padding.Left, 0);
      
                  // Drawing Border
                  //Left
                  g.DrawLine(borderPen, rect.Location, new Point(rect.X, rect.Y + rect.Height));
                  //Right
                  g.DrawLine(borderPen, new Point(rect.X + rect.Width, rect.Y), new Point(rect.X + rect.Width, rect.Y + rect.Height));
                  //Bottom
                  g.DrawLine(borderPen, new Point(rect.X, rect.Y + rect.Height), new Point(rect.X + rect.Width, rect.Y + rect.Height));
                  //Top1
                  g.DrawLine(borderPen, new Point(rect.X, rect.Y), new Point(rect.X + box.Padding.Left, rect.Y));
                  //Top2
                  g.DrawLine(borderPen, new Point(rect.X + box.Padding.Left + (int)(strSize.Width), rect.Y), new Point(rect.X + rect.Width, rect.Y));
              }
          }
      

      【讨论】:

      • 有没有办法加粗边框和圆矩形?
      • @A.Pissicat Pen 的第二个参数是宽度。添加它以更改厚度。
      【解决方案5】:

      我已经用一些对新手来说可能更容易理解的东西实现了相同的边界:

          private void groupSchitaCentru_Paint(object sender, PaintEventArgs e)
          {
              Pen blackPen = new Pen(Color.Black, 2);
              Point pointTopLeft = new Point(0, 7);
              Point pointBottomLeft = new Point(0, groupSchitaCentru.ClientRectangle.Height);
              Point pointTopRight = new Point(groupSchitaCentru.ClientRectangle.Width, 7);
              Point pointBottomRight = new Point(groupSchitaCentru.ClientRectangle.Width, groupSchitaCentru.ClientRectangle.Height);
      
              e.Graphics.DrawLine(blackPen, pointTopLeft, pointBottomLeft);
              e.Graphics.DrawLine(blackPen, pointTopLeft, pointTopRight);
              e.Graphics.DrawLine(blackPen, pointBottomRight, pointTopRight);
              e.Graphics.DrawLine(blackPen, pointBottomLeft, pointBottomRight);
          }
      
      1. 在 GroupBox 控件上设置 Paint 事件。在此示例中,我的控件的名称是“groupSchitaCentru”。需要这个事件是因为它的参数 e。
      2. 使用 System.Drawing.Pen 类设置笔对象:https://msdn.microsoft.com/en-us/library/f956fzw1(v=vs.110).aspx
      3. 设置代表控件所代表矩形角的点。使用控件的属性 ClientRectangle 来获取其尺寸。 我使用 TopLeft (0,7) 因为我想尊重控件的边框,并围绕其文本画线。 要获取有关坐标系的更多信息,请访问此处:https://docs.microsoft.com/en-us/dotnet/framework/winforms/windows-forms-coordinates

      我不知道,可能对希望实现此边框调整的人有所帮助。

      【讨论】:

      • 添加了GroupBox groupBox = (GroupBox)sender;,以便可以使用相同的绘制事件在所有组框上重新绘制相同的边框。
      【解决方案6】:

      FWIW,这是我使用的实现。它是 GroupBox 的子对象,但不仅可以设置 BorderColor,还可以设置边框的粗细和圆角的半径。此外,您可以为 GroupBox 标签设置所需的缩进量,并使用右侧的负缩进缩进。

      using System;
      using System.Drawing;
      using System.Windows.Forms;
      
      namespace BorderedGroupBox
      {
          public class BorderedGroupBox : GroupBox
          {
              private Color _borderColor = Color.Black;
              private int _borderWidth = 2;
              private int _borderRadius = 5;
              private int _textIndent = 10;
      
              public BorderedGroupBox() : base()
              {
                  InitializeComponent();
                  this.Paint += this.BorderedGroupBox_Paint;
              }
      
              public BorderedGroupBox(int width, float radius, Color color) : base()
              {
                  this._borderWidth = Math.Max(1,width);
                  this._borderColor = color;
                  this._borderRadius = Math.Max(0,radius);
                  InitializeComponent();
                  this.Paint += this.BorderedGroupBox_Paint;
              }
      
              public Color BorderColor
              {
                  get => this._borderColor;
                  set
                  {
                      this._borderColor = value;
                      DrawGroupBox();
                  }
              }
      
              public int BorderWidth
              {
                  get => this._borderWidth;
                  set
                  {
                      if (value > 0)
                      {
                          this._borderWidth = Math.Min(value, 10);
                          DrawGroupBox();
                      }
                  }
              }
      
              public int BorderRadius
              {
                  get => this._borderRadius;
                  set
                  {   // Setting a radius of 0 produces square corners...
                      if (value >= 0)
                      {
                          this._borderRadius = value;
                          this.DrawGroupBox();
                      }
                  }
              }
      
              public int LabelIndent
              {
                  get => this._textIndent;
                  set
                  {
                      this._textIndent = value;
                      this.DrawGroupBox();
                  }
              }
      
              private void BorderedGroupBox_Paint(object sender, PaintEventArgs e) =>
                  DrawGroupBox(e.Graphics);
      
              private void DrawGroupBox() =>
                  this.DrawGroupBox(this.CreateGraphics());
      
              private void DrawGroupBox(Graphics g)
              {
                  Brush textBrush = new SolidBrush(this.ForeColor);
                  SizeF strSize = g.MeasureString(this.Text, this.Font);
      
                  Brush borderBrush = new SolidBrush(this.BorderColor);
                  Pen borderPen = new Pen(borderBrush,(float)this._borderWidth);
                  Rectangle rect = new Rectangle(this.ClientRectangle.X,
                                                  this.ClientRectangle.Y + (int)(strSize.Height / 2),
                                                  this.ClientRectangle.Width - 1,
                                                  this.ClientRectangle.Height - (int)(strSize.Height / 2) - 1);
      
                  Brush labelBrush = new SolidBrush(this.BackColor);
      
                  // Clear text and border
                  g.Clear(this.BackColor);
      
                  // Drawing Border (added "Fix" from Jim Fell, Oct 6, '18)
                  int rectX = (0 == this._borderWidth % 2) ? rect.X + this._borderWidth / 2 : rect.X + 1 + this._borderWidth / 2;
                  int rectHeight = (0 == this._borderWidth % 2) ? rect.Height - this._borderWidth / 2 : rect.Height - 1 - this._borderWidth / 2;
                  // NOTE DIFFERENCE: rectX vs rect.X and rectHeight vs rect.Height
                  g.DrawRoundedRectangle(borderPen, rectX, rect.Y, rect.Width, rectHeight, (float)this._borderRadius);
      
                  // Draw text
                  if (this.Text.Length > 0)
                  {
                      // Do some work to ensure we don't put the label outside
                      // of the box, regardless of what value is assigned to the Indent:
                      int width = (int)rect.Width, posX;
                      posX = (this._textIndent < 0) ? Math.Max(0-width,this._textIndent) : Math.Min(width, this._textIndent);
                      posX = (posX < 0) ? rect.Width + posX - (int)strSize.Width : posX;
                      g.FillRectangle(labelBrush, posX, 0, strSize.Width, strSize.Height);
                      g.DrawString(this.Text, this.Font, textBrush, posX, 0);
                  }
              }
      
              #region Component Designer generated code
              /// <summary>Required designer variable.</summary>
              private System.ComponentModel.IContainer components = null;
      
              /// <summary>Clean up any resources being used.</summary>
              /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
              protected override void Dispose(bool disposing)
              {
                  if (disposing && (components != null))
                      components.Dispose();
      
                  base.Dispose(disposing);
              }
      
              /// <summary>Required method for Designer support - Don't modify!</summary>
              private void InitializeComponent() => components = new System.ComponentModel.Container();
              #endregion
          }
      }
      

      要使其工作,您还必须扩展基本 Graphics 类(注意:这是派生自我在尝试创建圆角面板控件时在此处找到的一些代码,但我找不到原文链接在这里):

      static class GraphicsExtension
      {
          private static GraphicsPath GenerateRoundedRectangle(
              this Graphics graphics,
              RectangleF rectangle,
              float radius)
          {
              float diameter;
              GraphicsPath path = new GraphicsPath();
              if (radius <= 0.0F)
              {
                  path.AddRectangle(rectangle);
                  path.CloseFigure();
                  return path;
              }
              else
              {
                  if (radius >= (Math.Min(rectangle.Width, rectangle.Height)) / 2.0)
                      return graphics.GenerateCapsule(rectangle);
                  diameter = radius * 2.0F;
                  SizeF sizeF = new SizeF(diameter, diameter);
                  RectangleF arc = new RectangleF(rectangle.Location, sizeF);
                  path.AddArc(arc, 180, 90);
                  arc.X = rectangle.Right - diameter;
                  path.AddArc(arc, 270, 90);
                  arc.Y = rectangle.Bottom - diameter;
                  path.AddArc(arc, 0, 90);
                  arc.X = rectangle.Left;
                  path.AddArc(arc, 90, 90);
                  path.CloseFigure();
              }
              return path;
          }
      
          private static GraphicsPath GenerateCapsule(
              this Graphics graphics,
              RectangleF baseRect)
          {
              float diameter;
              RectangleF arc;
              GraphicsPath path = new GraphicsPath();
              try
              {
                  if (baseRect.Width > baseRect.Height)
                  {
                      diameter = baseRect.Height;
                      SizeF sizeF = new SizeF(diameter, diameter);
                      arc = new RectangleF(baseRect.Location, sizeF);
                      path.AddArc(arc, 90, 180);
                      arc.X = baseRect.Right - diameter;
                      path.AddArc(arc, 270, 180);
                  }
                  else if (baseRect.Width < baseRect.Height)
                  {
                      diameter = baseRect.Width;
                      SizeF sizeF = new SizeF(diameter, diameter);
                      arc = new RectangleF(baseRect.Location, sizeF);
                      path.AddArc(arc, 180, 180);
                      arc.Y = baseRect.Bottom - diameter;
                      path.AddArc(arc, 0, 180);
                  }
                  else path.AddEllipse(baseRect);
              }
              catch { path.AddEllipse(baseRect); }
              finally { path.CloseFigure(); }
              return path;
          }
      
          /// <summary>
          /// Draws a rounded rectangle specified by a pair of coordinates, a width, a height and the radius
          /// for the arcs that make the rounded edges.
          /// </summary>
          /// <param name="brush">System.Drawing.Pen that determines the color, width and style of the rectangle.</param>
          /// <param name="x">The x-coordinate of the upper-left corner of the rectangle to draw.</param>
          /// <param name="y">The y-coordinate of the upper-left corner of the rectangle to draw.</param>
          /// <param name="width">Width of the rectangle to draw.</param>
          /// <param name="height">Height of the rectangle to draw.</param>
          /// <param name="radius">The radius of the arc used for the rounded edges.</param>
          public static void DrawRoundedRectangle(
              this Graphics graphics,
              Pen pen,
              float x,
              float y,
              float width,
              float height,
              float radius)
          {
              RectangleF rectangle = new RectangleF(x, y, width, height);
              GraphicsPath path = graphics.GenerateRoundedRectangle(rectangle, radius);
              SmoothingMode old = graphics.SmoothingMode;
              graphics.SmoothingMode = SmoothingMode.AntiAlias;
              graphics.DrawPath(pen, path);
              graphics.SmoothingMode = old;
          }
      
          /// <summary>
          /// Draws a rounded rectangle specified by a pair of coordinates, a width, a height and the radius
          /// for the arcs that make the rounded edges.
          /// </summary>
          /// <param name="brush">System.Drawing.Pen that determines the color, width and style of the rectangle.</param>
          /// <param name="x">The x-coordinate of the upper-left corner of the rectangle to draw.</param>
          /// <param name="y">The y-coordinate of the upper-left corner of the rectangle to draw.</param>
          /// <param name="width">Width of the rectangle to draw.</param>
          /// <param name="height">Height of the rectangle to draw.</param>
          /// <param name="radius">The radius of the arc used for the rounded edges.</param>
      
          public static void DrawRoundedRectangle(
              this Graphics graphics,
              Pen pen,
              int x,
              int y,
              int width,
              int height,
              int radius)
          {
              graphics.DrawRoundedRectangle(
                  pen,
                  Convert.ToSingle(x),
                  Convert.ToSingle(y),
                  Convert.ToSingle(width),
                  Convert.ToSingle(height),
                  Convert.ToSingle(radius));
          }
      }
      

      【讨论】:

      • 两个问题:1)我认为我只能将 BorderedGroupBox 用于以编程方式构建的表单;即不是用 IDE 构建的东西; 2) 什么是 graphics.GenerateCapsule()?
      • 1) 我在 Visual Studio 的设计器中使用这些控件没有任何问题... 2) 哈哈——我不认为我曾经使用过那么多半径,没有看到参考所以没有复制它的代码(哎呀!):
      • 谢谢布雷特。对于其他新手,我找到了解释如何创建自定义控件的链接:blackwasp.co.uk/vscontrolintoolbox.aspx。快速简便的过程。我会喜欢使用这个控件。
      • 修复了绘制宽边框...g.DrawRoundedRectangle(borderPen, (0 == this._borderWidth % 2) ? rect.X + this._borderWidth / 2 : rect.X + 1 + this._borderWidth / 2, rect.Y, rect.Width - this._borderWidth, (0 == this._borderWidth % 2) ? rect.Height - this._borderWidth / 2 : rect.Height - 1 - this._borderWidth / 2, (float)this._borderRadius);
      • @JimFell -- 谢谢!我已将您的建议应用于上面的代码(带有归属地!)。 :)
      【解决方案7】:

      对 Jim Fell 的代码进行的这项调整使边框对我来说更好一些,但添加为注释太长了

      ...

         Rectangle rect = new Rectangle(this.ClientRectangle.X,
                                              this.ClientRectangle.Y + (int)(strSize.Height / 2),
                                              this.ClientRectangle.Width,
                                              this.ClientRectangle.Height - (int)(strSize.Height / 2));
      
          Brush labelBrush = new SolidBrush(this.BackColor);
      
          // Clear text and border
          g.Clear(this.BackColor);
      
      
          int drawX = rect.X;
          int drawY = rect.Y;
          int drawWidth = rect.Width;
          int drawHeight = rect.Height;
      
          if (this._borderWidth > 0)
          {
              drawX += this._borderWidth / 2;
              drawY += this._borderWidth / 2;
      
              drawWidth -= this._borderWidth;
              drawHeight -= this._borderWidth;
              
              if (this._borderWidth % 2 == 0)
              {
                  drawX -= 1;
                  drawWidth += 1;
      
                  drawY -= 1;
                  drawHeight += 1;
              }
          }
      
          g.DrawRoundedRectangle(borderPen, drawX, drawY, drawWidth, drawHeight, (float)this._borderRadius);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-12
        • 2013-02-18
        • 1970-01-01
        • 2017-12-02
        • 2020-05-14
        • 1970-01-01
        • 2011-03-27
        • 1970-01-01
        相关资源
        最近更新 更多