c# Нарисовать границы формы

Всем привет. Хочу нарисовать "кастомные" границы для формы (borderstyle стоит none). Форм у меня достаточно много, поэтому я подумал, что будет проще, если я создам метод, в который буду передавать форму. Написал я значит его (ниже код):

class BorderClass
    {
        public static void Paint(Form form)
        {
            using (Graphics gr = form.CreateGraphics())
            {
                Point p1 = new Point(0, 0); //левый верхний угол
                Point p2 = new Point(form.Size.Width, form.Size.Height); //правый верхний угол
                Point p3 = new Point(0, form.Size.Height); //левый нижний угол
                Point p4 = new Point(form.Size.Width, 0); //правый нижний угол
                Pen PenSettings = new Pen(Color.Red, 10);// цвет линии и ширина
                PenSettings.Alignment = System.Drawing.Drawing2D.PenAlignment.Inset;
                gr.DrawLine(PenSettings, p1, p4);// рисуем линию
            }
        }
    }

В Form_Load пытаюсь вызвать его: " BorderClass.Paint(this); " , но как-то не очень получается.

p.s. для примера взял точки 1 и 4, чтобы наглядно было видно, что это работает, но оно не работает. В чём может быть проблема?


Ответы (1 шт):

Автор решения: Alexander Petrov

Класс-хелпер для рисования бордюра:

class FormBorderRenderer
{
    static Pen pen = new Pen(Color.Red, 10) { Alignment = PenAlignment.Inset };

    public static void Draw(Form form, Graphics graphics)
    {
        graphics.DrawRectangle(pen, form.ClientRectangle);
    }
}

Я переименовал и класс, и метод, чтобы он больше соответствовал уже имеющимся в WinForms классам наподобие TextBoxRenderer, ButtonRenderer и т. п.

Перо сделано полем, чтобы не создавать его каждый раз заново.
Если его создавать при каждом вызове метода, то нужно вызывать Dispose для освобождения ресурсов, а лучше - обернуть в using.

Вместо параметра Form метод может принимать Rectangle, если для отрисовки не нужны другие свойства формы.


Я использовал ClientRectangle, но это по желанию.
Полезная ссылка: https://stackoverflow.com/a/34453825/5045688 - различие между ClientRectangle и DisplayRectangle.


Форму подписываем на событие Paint, в обработчике которого пишем:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    FormBorderRenderer.Draw(this, e.Graphics);
}


А можно как-нибудь переопределить метод OnPaint во всех формах?

Базовый класс формы с произвольной отрисовкой бордюра:

public class CustomBorderForm : Form
{
    public CustomBorderForm()
    {
        FormBorderStyle = FormBorderStyle.None;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        FormBorderRenderer.Draw(this, e.Graphics);
    }
}

Далее наследуем другие формы от него:

public partial class Form1 : CustomBorderForm

Предложу ещё один вариант.

public partial class Form1 : Form
{
    public Form1()
    {
        //InitializeComponent();

        FormBorderStyle = FormBorderStyle.None;
        BackColor = Color.Red;

        var panel = new Panel
        {
            Parent = this,
            BackColor = SystemColors.Control,
            Left = 10,
            Top = 10,
            Width = this.Width - 20,
            Height = this.Height - 20
        };

        var button = new Button { Parent = panel, Text = "Click" };
    }
}

Задаём форме фоновый цвет - это будет цвет бордюра.
Помещаем на форму панель, с размерами меньше на требуемую толщину бордюра.

Теперь все контролы помещаем на эту панель. Не на форму!

→ Ссылка