Не работает Shown в C#

192
27 февраля 2019, 21:40

Работаю сейчас в формах C#. У меня есть две формы. Хочу, чтобы как только нажимается кнопка в первой форме, открывалась вторая форма и выполнялся код после вывода этой формы. Я использовал метод Shown, но по какой-то причине он не работает. Включается только, если поставить в самом начале метода MessageBox.

private void Form2_Shown(object sender, EventArgs e)
    {
        float h;
        int division = 10;
        Graphics gr = pictureBox1.CreateGraphics();
        Pen p = new System.Drawing.Pen(System.Drawing.Color.Gray);
        //Разметка
        h = 0;
        while (h <= pictureBox1.Width)
        {
            gr.DrawLine(p, h, 0, h, pictureBox1.Height);
            h += division;
        }
        h = 0;
        while (h <= pictureBox1.Height)
        {
            gr.DrawLine(p, 0, h, pictureBox1.Width, h);
            h += division;
        }
        //Координатная ось
        p.Color = Color.Red;
        gr.DrawLine(p, pictureBox1.Width / 2, 0, pictureBox1.Width / 2, pictureBox1.Height);
        gr.DrawLine(p, 0, pictureBox1.Height / 2, pictureBox1.Width, pictureBox1.Height / 2);

    }

Answer 1

"Неправильно вы бутерброд едите".

Несколько важных моментов:

  • изображение, нарисованное на форме, нигде не сохраняется, следовательно, при следующей перерисовке формы будет потеряно.
  • форма будет принудительно перерисована при открытии, изменении размера, перекрытии вашей формы другой формой, вызове метода Invalidate() в коде.
  • за отрисовку формы отвечает виртуальный метод Control.OnPaint(PaintEventArgs) и событие Control.Paint.

Проблемы вашего кода

Вы рисуете в событии, которое вызывается один единственный раз, и нигде не запоминаете, что нарисовали. Следовательно, при любом обновлении формы вы получите исходное изображение.

Пути решения

Вариантов несколько:

  1. Переопределить OnPaint или использовать обработчик события Paint. Собственно событие Paint вызывает метод OnPaint и все дополнительные методы, которые на него подписаны. Событие срабатывает при любой перерисовке формы. Переносим ваш код рисования в соответствующий метод и радуемся... но не все так просто. Это, наверное, самый очевидный вариант, но и самый сложный в плане правильной реализации, так как от этого будет напрямую зависеть и внешний вид вашей формы, и ее производительность. Код отрисовки должен быть максимально быстрым, без тяжелых вычислений, добывания данных и прочей ерунды. Плюс, вам придется вручную учитывать положение дочерних элементов на форме, что тоже не самое интересное занятие.

  2. Рисуем картинку и вставляем в форму. Тут все совсем тривиально. Берем Bitmap нужного размера, получаем из него объект Graphics и рисуем все, что нам надо. После этого вставляем в форму в виде отдельного контрола или сохраняем в каком-нибудь поле формы и переносим изображение на нужный участок с помощью DrawImage в OnPaint. DrawImage реализован нативными средствами и работает очень быстро, но ему нужно готовое изображение. К слову, DrawImage тоже можно заставить долго "думать", например, скормив ему очень большую, по размерам в пикселях, картинку с указанием сильно ее уменьшить. Данный способ всем хорош, кроме одного - не подходит для динамических изображений в реальном времени (относительно реальном разумеется). Зато с сохранением изображения в файл вообще никакой мороки - Bitmap.Save =).

  3. Кастомный контрол. Этот вариант мне наиболее симпатичен, так как позволяет сделать работу один раз и пользоваться результатами, когда понадобится.

    Идея в следующем:

    • создаем наследника UserControl (в дальнейшем MyControl).
    • в MyControl добавляем приватные поля для хранения объектов, которые необходимо рисовать. Часть данных может быть постоянной, часть пользовательской, по желанию.
    • в MyControl переопределяем OnPaint таким образом, чтобы он рисовал хранящиеся внутри объекты в нужном порядке.
    • добавляем публичные свойства, для приема необходимых для отрисовки параметров и объектов.

    Все. Теперь осталось только положить наш кастомный контрол на форму и передать ему необходимые параметры, все остальное он сделает уже сам. Как, собственно, и поступают все стандартные и не очень контролы.

    Данный вариант - нечто среднее между первым и вторым вариантами по сложности, но в отличие от них может быть легко переиспользован при качественной реализации.

Вроде ничего существенного не забыл, но если что-то описано не совсем понятно, дайте знать - уточню =)

READ ALSO
Качество выводимого в picturebox изображения

Качество выводимого в picturebox изображения

Есть битмап размером 100x100 пикселей, он растягивается и отображается в pictureBox формы,и выглядит это следующим образом (пискели мыльные, нету...

200
Cоздание backend для сайта. Отличие от .NET, .NET Core, .NET Framework, .NET MVC

Cоздание backend для сайта. Отличие от .NET, .NET Core, .NET Framework, .NET MVC

Пишу backend на PHPСобираюсь перейти на C#

233
Нет проекта ADO.NET Entity Data Model

Нет проекта ADO.NET Entity Data Model

При изучении Entity столкнулся с проблемойНет самого проекта ADO

207
Wpf MVVM выделить ListView?

Wpf MVVM выделить ListView?

Пишу Wpf MVVM приложение, в рантайме заполняю элемент ListView строками, после заполнения я могу только кликать по элементам, но не могу выделять...

265