Обработка событий в среде .NET Framework
93C# --- Руководство по C# --- Обработка событий в среде .NET Framework
В C# разрешается формировать какие угодно разновидности событий. Но ради совместимости программных компонентов со средой .NET Framework следует придерживаться рекомендаций, установленных для этой цели корпорацией Microsoft. Эти рекомендации, по существу, сводятся к следующему требованию: у обработчиков событий должны быть два параметра. Первый из них — ссылка на объект, формирующий событие, второй — параметр типа EventArgs, содержащий любую дополнительную информацию о событии, которая требуется обработчику. Таким образом, .NET-совместимые обработчики событий должны иметь следующую общую форму:
void обработчик(object отправитель, EventArgs е) { //... }
Как правило, отправитель — это параметр, передаваемый вызывающим кодом с помощью ключевого слова this. А параметр е типа EventArgs содержит дополнительную информацию о событии и может быть проигнорирован, если он не нужен.
Сам класс EventArgs не содержит полей, которые могут быть использованы для передачи дополнительных данных обработчику. Напротив, EventArgs служит в качестве базового класса, от которого получается производный класс, содержащий все необходимые поля. Тем не менее в классе EventArgs имеется одно поле Empty типа static, которое представляет собой объект типа EventArgs без данных.
В среде .NET Framework предоставляется встроенный обобщенный делегат под названием EventHandler<TEventArgs>. В данном случае тип TEventArgs обозначает тип аргумента, передаваемого параметру EventArgs события.
Для обработки многих событий параметр типа EventArgs оказывается ненужным. Поэтому с целью упростить создание кода в подобных ситуациях в среду .NET Framework внедрен необобщенный делегат типа EventHandler. Он может быть использован для объявления обработчиков событий, которым не требуется дополнительная информация о событиях.
Ниже приведен пример программы, в которой формируется .NET-совместимое событие:
// Реализуем программу реагирующую на события
// нажатия клавиш - вызывающих специализированные команды консоли
using System;
namespace ConsoleApplication1
{
// Производный класс от EventArgs
class MyEventArgs : EventArgs
{
public char ch;
}
class KeyEvent
{
// Создадим событие, используя обобщенный делегат
public event EventHandler<MyEventArgs> KeyDown;
public void OnKeyDown(char ch)
{
MyEventArgs c = new MyEventArgs();
if (KeyDown != null)
{
c.ch = ch;
KeyDown(this, c);
}
}
}
class Program
{
static void Main()
{
KeyEvent evnt = new KeyEvent();
evnt.KeyDown += (sender, e) =>
{
switch (e.ch)
{
case 'C':
{
MyColor(true);
break;
}
case 'B':
{
MyColor(false);
break;
}
case 'S':
{
Console.Write("\nВведите длину: ");
try
{
int Width = int.Parse(Console.ReadLine()) / 8;
Console.Write("Введите ширину: ");
int Height = int.Parse(Console.ReadLine()) / 8;
Console.WindowWidth = Width;
Console.WindowHeight = Height;
Console.WriteLine();
}
catch (FormatException)
{
Console.WriteLine("Неверный формат!");
}
catch (ArgumentOutOfRangeException)
{
Console.WriteLine("Окно настолько не растянется!");
}
break;
}
case 'T':
{
Console.Write("\nВведите новый заголовок: ");
string s = Console.ReadLine();
Console.Title = s;
Console.WriteLine();
break;
}
case 'R':
{
Console.ForegroundColor = ConsoleColor.White;
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine();
break;
}
case 'E':
{
Console.Beep();
break;
}
default:
{
Console.WriteLine("\nТакая команда не найдена!");
break;
}
}
};
ConsoleTitle();
char ch;
do
{
Console.Write("Введите комманду: ");
ConsoleKeyInfo key;
key = Console.ReadKey();
ch = key.KeyChar;
evnt.OnKeyDown(key.KeyChar);
}
while (ch != 'E');
}
// Несколько вспомогательных методов
static void ConsoleTitle()
{
CC(ConsoleColor.Green);
Console.WriteLine("***************************\n\nПрограмма настройки консоли"
+ "\n___________________________\n");
CC(ConsoleColor.Yellow);
Console.WriteLine("Управляющие команды: \n");
Command("C", "Поменять цвет текста");
Command("B", "Поменять цвет фона");
Command("S", "Поменять размер окна");
Command("T", "Поменять заголовок");
Command("R", "Сбросить изменения");
Command("E", "Выход");
Console.WriteLine();
}
static void CC(ConsoleColor color)
{
Console.ForegroundColor = color;
}
static void Command(string s1, string s2)
{
CC(ConsoleColor.Red);
Console.Write(s1);
CC(ConsoleColor.White);
Console.Write(" - " + s2+"\n");
}
static void MyColor(bool F_or_B)
{
link1:
Console.Write("\nВведите цвет: ");
string s = Console.ReadLine();
switch (s)
{
case "Black":
{
if (F_or_B)
Console.ForegroundColor = ConsoleColor.Black;
else
Console.BackgroundColor = ConsoleColor.Black;
break;
}
case "Yellow":
{
if (F_or_B)
Console.ForegroundColor = ConsoleColor.Yellow;
else
Console.BackgroundColor = ConsoleColor.Yellow;
break;
}
case "Green":
{
if (F_or_B)
Console.ForegroundColor = ConsoleColor.Green;
else
Console.BackgroundColor = ConsoleColor.Green;
break;
}
case "Red":
{
if (F_or_B)
Console.ForegroundColor = ConsoleColor.Red;
else
Console.BackgroundColor = ConsoleColor.Red;
break;
}
case "Blue":
{
if (F_or_B)
Console.ForegroundColor = ConsoleColor.Blue;
else
Console.BackgroundColor = ConsoleColor.Blue;
break;
}
case "Gray":
{
if (F_or_B)
Console.ForegroundColor = ConsoleColor.Gray;
else
Console.BackgroundColor = ConsoleColor.Gray;
break;
}
case "White":
{
if (F_or_B)
Console.ForegroundColor = ConsoleColor.White;
else
Console.BackgroundColor = ConsoleColor.White;
break;
}
default:
{
Console.WriteLine("Такой цвет я не знаю :(");
goto link1;
}
}
Console.WriteLine("Цвет изменился!");
}
}
}
Как видите, данный пример наглядно демонстрирует создание пользовательского события нажатия клавиш, при этом обработчик события, реализованный с помощью лямбда-выражения содержит целый набор команд, для работы с консолью.