Разработка приложений на языке C#. Полезные настройки. Особые спецификаторы формата, страница 10

В этом параметре скрывается информация, сопутствующая событию (вспомните wParam и lParam в каркасе API). Так, в аргументе PaintEventArgs спрятан контекст устройства для рисования (вспомните HDC). Он нас интересует, так как позволяет рисовать в контексте, не зависящем от физического устройства (монитора или принтера). Контекст устройства для рисования замаскирован в объекте класса Graphics. Мы должны его выудить из параметра (PaintEventArgs e) для того, чтобы получить возможность для рисования. Итак, для рисования мы должны:

·  Создать своего делегата и дать ему задание (указать адрес функции обработки события),

·  Добавить его в список делегатов события Paint,

·  Добавить в класс MyForm саму функцию обработки события.

Эти действия можно автоматизировать с помощью инструмента студии (мастера вставок).

1.  Поставьте клавиатурный фокус в конец тела конструктора.

2.  Введите имя события и два символа операции добавки (в коллекцию делегатов): Paint +=. Мастер откликнется и подскажет, что делать дальше.

3.  Нажмите Tab. Мастер создаст делегата с нужной сигнатурой.

4.  Еще раз нажмите Tab. Мастер создаст метод обработки события (задание делегата с нужной сигнатурой).

После выполнения этих действий (и вставки нашего кода рисования) класс будет выглядеть так.

class MyForm : Form

{

public static void Main()

{

  Application.Run (new MyForm());

}

public MyForm()

{

  Text = "MyForm";

  Width = 700;

  Height = 500;

  BackColor = Color.LavenderBlush;

  Button btnDraw = new Button();

  btnDraw.Text = "Click Me";

  btnDraw.Size = new Size(80,25);

  btnDraw.Location = new Point(5,10);

  Controls.Add (btnDraw);

  Paint += new PaintEventHandler (MyForm_PaintHandler); // Добавляем делегата

}

void MyForm_PaintHandler (object sender, PaintEventArgs e)

{

  Form f = (Form)sender; // Параметр нам не нужен, но интересно, что в нем. Просто убедитесь, что это — ссылка на объект MyForm

  Graphics g = e.Graphics;

  Brush br = new LinearGradientBrush (new Point(10,10), new Point(300,10),

      Color.Violet, Color.Yellow);

  g.DrawString ("We are painting", new Font("Arial",28), br, 120, 10);

  g.DrawBezier (new Pen(br, 10), new Point(20,250), new Point(5,50),

    new Point(300,300), new Point(250,50));

}

}

При запуске компилятор обнаружит ошибку, для исправления которой вам придется добавить директиву using. Нужные пространства имен подскажет (и вставит ссылки) механизм Inellisense (или определите их путем анализа сообщения и MSDN).

Вы заметили, сколько много "новых" (операций захвата памяти new) в этом примере? Как видите, память не жалеют. В Win32-приложениях нас учат запоминать старый инструмент, создавать новый, выбирать его в контекст устройства, использовать, затем восстанавливать старый и уничтожать вновь созданный. Теперь каждый раз, когда надо что-то сделать, все инструменты создаются заново. Это напоминает одноразовую посуду и горы мусора, которые остаются, после того как "новые" попировали. Но, как утверждает Microsoft, это не приводит к потерям — выручает инструмент под названием сборщик мусора (garbage collector).

Система присылает нам контекст устройства HDC (как и в других каркасах, например, MFC) в параметре. Но теперь он спрятан в объекте класса Graphics и передан в функцию с помощью PaintEventArgs.

Как ввести функцию-обработчик сообщения о нажатии кнопки? В конструктор вновь вставьте код, инициирующий мастер вставок: btnDraw.Click +=, и, не торопясь, два раза нажмите Tab.

Событие Click имеется в классе Control, а значит и классе Button (который от него происходит). В коллекцию делегатов события Click (кнопки btnDraw) мы добавили нового делегата со ссылкой на метод btnDraw_Click. Сам метод, реагирующий на событие Click, был создан мастером. В нем мы нарисуем еще одну кривую, соединяющую точки с помощью сплайн-аппроксимации. Здесь важно отметить тот факт, что объект класса Graphics создается локально и уничтожается после использования.