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

Form f1 = new Form(), f2 = new Form();

f1.Text = "First";  f2.Text = "Second";

f2.Visible = true;

Application.Run (f1);

MessageBox.Show("App has ended");

Почему f1 is Visible? Равноправны ли окна? Меняйте порядок закрытия и объясняйте происходящее. Какая из форм является главной? Сделайте главной другую форму и сравните результат.

Класс формы (окна)

Обычно вместо надуманного, ни с кем (кроме Object) не связанного, класса Program, в Windows-приложениях используется класс, который происходит от Windows.Forms. В этом случае многое упрощается. Создайте новую версию кода (новый файл) и не забудьте вставить директивы using.

class MyForm : Form

{

public MyForm()   // Конструктор задает свойства формы. Опробуйте другие свойства (увеличьте размер и т.д.)

{

  Text = "MyForm";   BackColor = Color.AliceBlue; // Вставьте Size = new . . .

}

public static void Main() // Запускальщик приложения

{

  Application.Run (new MyForm()); // Вызываем конструктор и связываем приложение с MyForm

  Console.WriteLine ("App has ended"); // Где искать этот текст?

}

}

Как создавать элементы управления

Класс Form (а, следовательно, и класс MyForm) происходит от класса Control (см. MSDN). Он унаследовал функциональность элемента управления. Более того, класс Form является контейнером элементов управления, то есть он способен вместить множество (коллекцию) элементов управления. Смотрите, как просто добавить в эту коллекцию новую кнопку. Вставьте этот код в конструктор формы и запустите на выполнение.

Button btnDraw = new Button();

btnDraw.Text = "Click Me";

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

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

Controls.Add (btnDraw);

Обработка сообщений

Вы знаете, что Windows-приложения должны реагировать на сообщения о событиях (обрабатывать их), иначе они выглядят мертвыми. В .NET принято говорить об обработке событий (event handling). Событие ассоциируется с сообщением (message), сигнализирующем о том, что произошло какое-то событие. Объект, который возбудил (raise или trigger) событие, называется источником (event sender). Объект, реагирующий на событие, называется приемником (event receiver). Самым распространенным событием является посылка системой сообщения о перерисовке. Рассмотрим как ввести реакцию на это событие.

Каждый объект класса Form имеет в своем составе событие Paint. Класс Form получил его в наследство от класса Control. Событие можно представить себе в виде некоего объекта, который содержит множество вспомогательных объектов (делегатов), которые по очереди вступают в игру при наступлении события. Каждый делегат содержит список того, что ему нужно сделать — некий перечень заданий делегата, которые он должен выполнить. Каждое задание можно представить себе как вызов функции обработки (event handler).

Итак, класс Form, а значит и MyForm, инкапсулирует событие Paint. Нам осталось лишь ввести реакцию на него. Для этого надо добавить в список делегатов события Paint нового (нашего собственного) делегата и снабдить его заданием, которое представляет собой адрес функции обработки события. Вспомните, что имя функции является ее адресом (также, как и имя массива — адресом его начала). Следовательно задание делегата — это просто имя функции, которую он должен вызвать в момент возникновения события.

Функция обработки каждого события имеет свой прототип (теперь, принято говорить—сигнатуру), но большинство из них стандартно. Так, обработчик WM_PAINT должен иметь сигнатуру:

void MyPaintHandler (object sender, PaintEventArgs e);

Под сигнатурой понимают правила игры (что на входе, что на выходе). Имя метода, обрабатывающего событие (то есть, задания делегата) произвольно. Вместо MyPaintHandler вы можете записать MyForm_PaintHandler или что-то еще, но есть договоренность (convention) о том, что имя метода должно намекать на делегатный тип (в нашем случае — PaintHandler), который определен в библиотеке .NET (или нами, в случае, если мы создадим свое собственное событие). Договорились также, что первый параметр любого метода, реагирующего на событие, содержит ссылку на того, кто сгенерировал событие (object sender — это наша форма), второй — сопровождает событие и содержит данные (PaintEventArgs e), сформированные системой в момент его возникновения (аналог wParam и lParam).