Форма
Стандартный делегат
Существует соглашение, по которому обработчик событий в .NET Framework не возвращает значений (тип возвращаемого значения void) и принимает два параметра.
Первый параметр – ссылка на источник события (объект-издатель), второй параметр – ссылка на объект, производный от класса EventArgs. Сам по себе базовый класс НЕ НЕСЕТ никакой "полезной" информации о конкретных событиях. Назначение данного класса заключается в поддержке универсального стандартного механизма реализации событий (в том числе и передачи параметров). Забота о представлении информации о событии возлагается на разработчика производного класса.
Делегат EventHandler
Представляет метод со стандартной сигнатурой, который предназначен для обработки события, не содержащего дополнительной информации.
Объявляется следующим образом:
public delegate void EventHandler(object sender, EventArgs e);
Параметры
object sender — представляет ссылку на объект – источник события.
EventArgs e — таким образом кодируется информация о событии.
Модель событий в .NET Framework основывается на механизме ссылок на функции ( events – разновидности класса-делегата), которые обеспечивают стандартную стыковку события с обработчиком. Для возбуждения события необходимы два элемента:
- Класс – носитель информации о событии. Должен наследовать от базового класса EventArgs.
- Делегат, который настроен на метод, обеспечивающий реакцию на данное событие. Когда создается делегат – представитель класса-делегата EventHandler, прежде всего определяется соответствующий метод, выполнение которого обеспечивает реакцию на событие.
Таким образом, для реализации перехвата события достаточно использовать:
- базовый класс EventArgs, если уведомление о произошедшем событии не связано с генерацией дополнительной информации, или производный от данного класса класс, если необходимо передавать дополнительную информацию, связанную с событием;
- предопределенный класс EventHandler для реализации ссылки на метод – обработчик события.
Пример:
using System; namespace Events00 { // Однопоточное приложение, в котором для реализации механизма // реакции на события используется стандартный класс-делегат // System.EventHandler. // Объявляется класс события, производный от System.EventArgs. //=============================================================== class EventPosition:System.EventArgs { // Дополнительная информация о событии. public int X; // Конструктор... public EventPosition(int key) { X = key; } } //=============================================================== //Базовый класс действующих в приложении объектов. //Содержит ВСЕ необходимое для того, чтобы объекты производных классов // могли адекватно реагировать на заложенные в базовом классе события. class BaseClass { // Ссылка на это событие идентифицируется как xEvent. // Это "стандартное" событие. // xEvent стыкуется со стандартным классом-делегатом System.EventHandler. public static event System.EventHandler xEvent; // Статическая переменная - носитель дополнительной информации. static int xPosition = 0; // Статическая функция. Это модель процесса непрерывного сканирования. // Аналог цикла обработки сообщений приложения. public static void XScaner() { while (true) {//============================================================= while(true) {//============================================================= // Источником события является вводимая с клавиатуры // последовательность символов, соответствующая целочисленному // значению 50. При получении этого значения происходит уведомление // подписанных на событие объектов.============================= try { Console.WriteLine("new xPosition, please: "); xPosition = Int32.Parse(Console.ReadLine()); break; } catch { Console.WriteLine("Incorrect value of xPosition!"); } }//============================================================== if (xPosition < 0) break; // Отрицательные значения являются сигналом // к прекращению выполнения, а при получении 50 – возбуждается событие! if (xPosition == 50) xEvent(new BaseClass(), new EventPosition(xPosition)); }//============================================================== } } //================================================================= // Важное обстоятельство! В этом приложении событие возбуждается // ПРЕДКОМ, а реагирует на него объект - представитель класса ПОТОМКА! //================================================================= // Объявление первого производного класса. // Надо сделать дополнительные усилия для того, чтобы объекты этого класса // стали бы реагировать на события. class ClassONE:BaseClass { public void MyFun(object obj, System.EventArgs ev) { Console.Write("{0} – ",this.ToString()); Console.WriteLine ("{0}:YES! {1}",((BaseClass)obj).ToString(),((EventPosition)ev). X.ToString()); } } // Второй класс чуть сложнее. // Снабжен конструктором, который позволяет классу // самостоятельно "подписаться" на "интересующее" его событие. class ClassTWO:BaseClass { public ClassTWO() { BaseClass.xEvent += new System.EventHandler(this.MyFun); } public void MyFun(object obj, System.EventArgs ev) { Console.Write("{0} – ",this.ToString()); Console.WriteLine ("{0}:YES! {1}",((BaseClass)obj).ToString(),((EventPosition)ev).X.ToString()); } } class mainClass { static void Main(string[] args) { Console.WriteLine("0______________________________"); // Создали первый объект и подписали его на получение события. ClassONE one = new ClassONE(); BaseClass.xEvent += new System.EventHandler(one.MyFun); // Второй объект подписался сам. ClassTWO two = new ClassTWO(); // Запустили цикл прослушивания базового класса. BaseClass.XScaner(); // При получении отрицательного значения цикл обработки // сообщений прерывается. Console.WriteLine("1______________________________"); // Объект - представитель класса ClassONE перестает // получать уведомление о событии. BaseClass.xEvent –= new System.EventHandler(one.MyFun); // После чего повторно запускается цикл прослушивания, // который прекращает выполняться после повторного // получения отрицательного значения. BaseClass.XScaner(); Console.WriteLine("2______________________________"); } } }Листинг 16.5.
Класс Application
Public sealed class Application – класс, закрытый для наследования.
Предоставляет СТАТИЧЕСКИЕ (и только статические!) методы и свойства для общего управления приложением, предоставляет статические методы и свойства для управления приложением, в том числе:
- методы для запуска и остановки приложения;
- методы для запуска и остановки потоков в рамках приложения;
- методы для обработки сообщений Windows;
- свойства для получения сведений о приложении.
AllowQuit | Получает значение, определяющее, может ли вызывающий объект выйти из этого приложения |
CommonAppDataPath | Получает путь для данных приложения, являющихся общими для всех пользователей |
CommonAppDataRegistry | Получает раздел реестра для данных приложения, являющихся общими для всех пользователей |
CompanyName | Получает название компании, связанное с приложением |
CurrentCulture | Получает или задает данные о культурной среде для текущего потока |
CurrentInputLanguage | Получает или задает текущий язык ввода для текущего потока |
ExecutablePath | Получает путь для исполняемого файла, запустившего приложение, включая исполняемое имя |
LocalUserAppDataPath | Получает путь для данных приложения местного, не перемещающегося пользователя |
MessageLoop | Получает значение, указывающее, существует ли цикл обработки сообщений в данном потоке |
ProductName | Получает название продукта, связанное с данным приложением |
ProductVersion | Получает версию продукта, связанную с данным приложением |
SafeTopLevelCaptionFormat | Получает или задает строку формата для использования в заголовках окон верхнего уровня, когда они отображаются с предупреждающим объявлением |
StartupPath | Получает путь для исполняемого файла, запустившего приложение, не включая исполняемое имя |
UserAppDataPath | Получает путь для данных приложения пользователя |
UserAppDataRegistry | Получает раздел реестра для данных приложения пользователя |
ApplicationExit | Происходит при закрытии приложения. |
Idle | Происходит, когда приложение заканчивает обработку и собирается перейти в состояние незанятости. |
ThreadException | Возникает при выдаче неперехваченного исключения потока. |
ThreadExit | Происходит при закрытии потока. Перед закрытием главного потока для приложения вызывается данное событие, за которым следует событие ApplicationExit. |
IMessageFilter позволяет остановить вызов события или выполнить специальные операции до вызова обработчика событий.
Класс имеет свойства CurrentCulture и CurrentInputLanguage, чтобы получать или задавать сведения о культурной среде для текущего потока.
ApplicationExit | Статическое. Происходит при закрытии приложения |
Idle | Статическое. Происходит, когда приложение заканчивает обработку и собирается перейти в состояние незанятости |
ThreadException | Статическое. Возникает при выдаче неперехваченного исключения потока |
ThreadExit | Статическое. Происходит при закрытии потока. Перед закрытием главного потока для приложения вызывается данное событие, за которым следует событие ApplicationExit |
Итак, класс Application располагает методами для запуска и останова ПОТОКОВ и ПРИЛОЖЕНИЙ, а также для обработки Windows messages.
Вызов методов Run обеспечивает выполнение цикла обработки сообщений (an application message loop) в текущем потоке, а также, возможно, делает видимой соответствующую форму.
Вызов методов Exit и ExitThread приводит к остановке цикла обработки сообщений.
Вызов DoEvents позволяет активизировать обработку сообщений практически из любого места выполняемого программного кода — например во время выполнения операторов цикла.
Вызов AddMessageFilter обеспечивает добавление фильтра Windows сообщений для работы с сообщениями.
Интерфейс IMessageFilter позволяет реализовывать специальные алгоритмы непосредственно перед вызовом обработчика сообщения.
Класс статический, и объектов – представителей этого класса создать невозможно!