Как изменить цвет рамки на групповом поле?

В C# .NET я пытаюсь программно изменить цвет границы в групповом поле.

Обновление: этот вопрос был задан, когда я работал над системой winforms до того, как мы перешли на .NET.

@Amy Проверьте ответ user1944617, это действительно красиво и лучше, чем принято. просто попробовал и идеально вписался в дизайн групповой коробки по умолчанию.

Drake 05.03.2014 15:17
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
31
1
91 225
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Я не уверен, что это применимо к каждому случаю, но благодаря этому потоку мы быстро подключились к событию Paint программно, используя:

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

Ваше здоровье!

Ответ принят как подходящий

Основываясь на предыдущем ответе, лучшее решение, которое включает метку для группового поля:

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, ты сэкономил мне много времени :)

Michael La Voie 11.01.2012 06:23

Спасибо! Чтобы удалить границу, используйте box.Parent.BackColor, как это сделал я.

dwo 11.10.2013 15:12

Просто установите для этого метода действие рисования на любом объекте (не только на кнопках), чтобы нарисовать границу.

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

    }

Он все равно не будет красивым и округлым, как оригинал, но все намного проще.

Просто добавьте событие рисования.

    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 06.03.2017 18:37

@ A.Pissicat Второй параметр для Ручка - ширина. Добавьте это, чтобы изменить толщину.

DCOPTimDowd 04.12.2019 21:04

Я достиг такой же границы с чем-то, что может быть проще понять новичкам:

    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. Задайте событие Paint для элемента управления GroupBox. В этом примере имя моего элемента управления - «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;, чтобы одно и то же событие рисования можно было использовать для перерисовки границ на всех групповых блоках одинаково.

Jim Fell 02.10.2018 18:05

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 (Примечание: это получено из некоторого кода, который я нашел здесь однажды, когда пытался создать элемент управления Panel с закругленными углами, но я не могу найти исходное сообщение ссылку здесь):

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 ()?

4mla1fn 08.08.2018 15:59

1) Я использую эти элементы управления в конструкторе Visual Studio без каких-либо проблем ... 2) лол - я не думаю, что когда-либо использовал такой большой радиус, не видел ссылку, поэтому не копировал код для нее (ух!):

NetXpert 09.08.2018 07:38

спасибо бретт. для других новичков я нашел эту ссылку, в которой объясняется, как создать собственный элемент управления: blackwasp.co.uk/vscontrolintoolbox.aspx. быстрый и легкий процесс. мне понравится использовать этот элемент управления.

4mla1fn 10.08.2018 03:51

Исправлено рисование широких границ ... 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);

Jim Fell 02.10.2018 18:10

@JimFell - спасибо! Я применил ваше предложение к приведенному выше коду (с указанием авторства!). :)

NetXpert 06.10.2018 18:57

Другие вопросы по теме