Методы класса
События
В реальном мире события происходят непрерывно, причем некоторые от нас совсем не зависят. Например, восход и закат солнца (хотел бы я посмотреть, как вы пытаетесь заставить солнце вставать и садиться). Другие события мы вызываем сами: скажем, заставляем громкоговоритель издавать звуки.
Рассмотрим несколько событий, которые часто встречаются в мире компьютеров:
- нажатие на кнопку, изображенную на экране монитора;
- истечение времени таймера;
- перемещение мыши;
- нажатие клавиши на клавиатуре.
Очевидно, что, нажав на кнопку, мы хотим заставить компьютер выполнить определенное действие. (Если нет – зачем вообще ее трогать?) Но компьютер ждет не только подтверждения, что нажатие этой кнопки имеет для вас какое-то значение, но и указания на действие, которое нужно выполнить.
Рассмотрим подробнее этот пример, поскольку нажатие на кнопку, возможно, является наиболее распространенным событием, и детально разберем порядок работы. Допустим, в вашей программе есть объект — кнопка с именем mrButton, на которой написано "Нажми меня".
По ходу обсуждения попробуйте все делать сами. Для начала:
- Запустите Visual C# Express.
- Создайте новый проект приложения Windows: в меню File ("Файл") выберите Create project ("Создать проект") и затем тип проекта Windows Application ("Приложение Windows Forms").
- В Visual C# Express откроется несколько файлов, где содержится "скелет" кода программы.
- В окне обозревателя решений справа (в списке всех файлов) удалите файл с именем Form1.cs.
- Дважды щелкните имя файла Program.cs и удалите весь автоматически вставленный "скелет" кода.
- Чтобы создать программу с экземпляром кнопки, наберите следующий код в окне Program.cs так, как показано ниже (написание слов курсивом или жирным шрифтом можно не учитывать.
using System; using System.Windows.Forms; class MyButtonClass: Form { private Button mrButton; // Метод-конструктор public MyButtonClass() { mrButton = new Button(); mrButton.Text = "Нажми меня"; this.Controls.Add(mrButton); } // Основной метод static void Main() { Application.Run(new MyButtonClass()); } }
Выполните программу при помощи клавиши F5 (или щелкните по зеленой кнопке "Выполнить"). Если возникнут сообщения об ошибках, тщательно проверьте, нет ли опечаток в коде. Если программа будет выполнена успешно, вы увидите форму с кнопкой "Нажми меня". Пока при нажатии на кнопку никаких действий происходить не будет. Конечно, вы ожидали другого результата, но все еще впереди.
Событие нажатия кнопки. Указание действия в случае события
Теперь мы должны задать метод, выполняющий действие при нажатии на кнопку. Такие методы называются обработчиками событий, поскольку они именно "обрабатывают" событие. В приведенном ниже примере код обработчика события просто изменяет надпись на кнопке, поэтому он совсем короткий:
using System; using System.Windows.Forms; class MyButtonClass: Form { private Button mrButton; // Метод-конструктор public MyButtonClass() { mrButton = new Button(); mrButton.Text = "Нажми меня!"; this.Controls.Add(mrButton); } // Основной метод static void Main() { Application.Run(new MyButtonClass()); } // Метод-обработчик событий void MyButtonClickEventHandler(object sender, EventArgs e) { mrButton.Text = "Вы нажали меня!"; } }
Ваша программа еще выполняется?
- Остановите ее (нажмите на кнопку X в верхнем правом углу окна, в котором открыта форма).
- Добавьте в программу выделенный код и нажмите на клавишу F5 для выполнения измененной программы.
- Попробуйте теперь щелкнуть по кнопке "Нажми меня". И теперь ничего не происходит?!
Поскольку вы уже прочитали те страницы, где мы говорили про методы, то должны узнать основную структуру приведенного выше метода. Слово void означает, что по его завершении ничего не возвращается. Мы назвали этот метод MyButtonClickEventHandler.
Возможно, то, что вы видите, кажется немного странным. Вы понимаете, что в скобках присутствуют два параметра, но почему у них такие необычные типы ( object sender, EventArgs e )? К сожалению, с методами обработчиков событий нельзя использовать собственные типы параметров. Когда у кнопки возникает событие "Click", она посылает сообщение о нем операционной системе, а та находит и вызывает соответствующий обработчик события. При вызове такого метода система сама определяет типы параметров и передает обработчику их значения. Это факт, с которым мы ничего поделать не можем.
Поэтому придется просто смириться и всегда использовать ожидаемые типы параметров с обработчиком событий. Очень часто подставляемые параметры имеют тип object и EventArgs. В приведенном выше примере мы выбрали имена параметров sender и e, но могли бы выбрать любые другие — для компьютера важны имена типов этих параметров. Например, следующий код будет работать точно так же, как и код, рассмотренный в предыдущем примере. Можете проверить это сами, изменив имена параметров в вашей программе на x и y.
void MyButtonClickEventHandler(object x, EventArgs y) { mrButton.Text = "Вы нажали меня!"; }
В первом параметре обычно содержится некоторая информация об объекте, который инициировал событие. Второй параметр относится к данным о самом событии.
Очень важно знать следующее: система всегда подставляет некоторые значения в эти два параметра, но зачастую необходимости в их использовании нет — они отправляются в метод обработчика событий "на всякий случай".
Подключение метода обработчика событий к событию
Вы удивляетесь, почему ничего не происходит при нажатии на кнопку? Дело в том, что указанный метод вызывается только тогда, когда мы свяжем с ним событие нажатия на кнопку, указав в программе: при нажатии на кнопку необходимо перейти к определенному обработчику событий.
Когда в программе используются разные кнопки и несколько обработчиков событий, без такого уточнения не обойтись, так как компьютер должен знать, какой именно метод следует выполнять при нажатии на определенную кнопку.
Код для связывания события объекта с методом обработчика события выглядит тоже несколько странно.
using System; using System.Windows.Forms; class MyButtonClass : Form { private Button mrButton; // Метод-конструктор public MyButtonClass() { mrButton = new Button(); mrButton.Text = "Нажми меня"; // Код для связывания события объекта с методом обработчика события mrButton.Click += new System.EventHandler(MyButtonClickEventHandler); this.Controls.Add(mrButton); } // Основной метод static void Main() { Application.Run(new MyButtonClass()); } // Метод-обработчик событий void MyButtonClickEventHandler(object sender, EventArgs e) { mrButton.Text = "Вы нажали меня!"; } }
С компьютерного языка это можно перевести следующим образом:
"Путем нажатия на кнопку mrButton надо связать событие Click с методом обработчика событий, который называется MyButtonClickEventHandler ".
При нажатии на кнопку приведенная выше строка кода позволяет системе вызвать метод обработчика событий, после его выполнения надпись на кнопке меняется на "Вы нажали меня!".
Чтобы использовать этот код, остановите свою программу, добавьте в нее выделенный код и нажмите клавишу F5 для выполнения программы. Нажмите на кнопку, и надпись на ней изменится. Рабочую программу — пример события нажатия на кнопку — можно найти в папке примеров, прилагаемых к курсу (Проект Example5).
public MyButtonClass() { mrButton = new Button(); mrButton.Text = "Нажми меня"; mrButton.Top = 100; mrButton.Left = 100; mrButton.Height = 50; mrButton.Width = 70; mrButton.Click += new System.EventHandler(MyButtonClickEventHandler); this.Controls.Add(mrButton); }
Теперь мы попробуем описать основную структуру метода обработчика событий мыши. Вероятно, в этом случае вы захотите использовать информацию, подставляемую в параметр MouseEventArgs, хотя бы для того, чтобы выяснить, какая из кнопок мыши нажимается.
public void TheMouseIsDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) this.Text = "Нажата левая кнопка мыши"; }
Далее показано, как связать событие с методом. В переводе с компьютерного в тексте написано следующее: "Если при выполнении этой программы нажимается кнопка мыши, надо перейти к методу TheMouseIsDown ", которому известно, как следует обрабатывать события мыши:
this.MouseDown += new MouseEventHandler(TheMouseIsDown);
Можно внести некоторые улучшения, чтобы при запуске следующего обработчика код, содержащийся в нем, делал окно более широким или узким в зависимости от нажимаемой кнопки.
public void TheMouseWasClicked(object sender, MouseEventArgs e) { // При нажатии левой кнопки if (e.Button == MouseButtons.Left) // Расширение текущего окна this.Width = this.Width + 100; else if (e.Button == MouseButtons.Right) // Сужение текущего окна this.Width = this.Width – 100; }
Другой обработчик событий позволяет обнаружить перемещение мыши и рисовать окружность в том месте, где находится курсор:
public void TheMouseMoved(object sender, MouseEventArgs e) { // Подготовка области рисования System.Drawing.Graphics g = this.CreateGraphics(); // Использование красной ручки System.Drawing.Pen redPen = new System.Drawing.Pen(System.Drawing.Color.Red, 3); // Рисуем окружность как эллипс с равными осями. // Окружность рисуется в охватывающем ее квадрате. // Координаты X и Y левого верхнего угла квадрата // определяются координатами текущего положения мыши. g.DrawEllipse(redPen, e.X, e.Y, 40, 40); // Очистка g.Dispose(); }
На снимке экрана показано, как это выглядит при перемещении мыши: