Практическое занятие № 4
Тема: Обработка событий мыши и клавиатуры
Цель работы: на практике отработать принципы обработки событий клавиатуры при проектировании интерфейса пользователя
Ход работы
Создайте форму вида:
Форма не имеет заголовка и перемещается по экрану за любое пустое место на ней с помощью левой кнопки мыши при нажатых клавишах CTRL + ALT.
Указания: Для формы задайте свойства: FormBorderStyle=None, KeyPreview=True (чтобы форма реагировала на нажатие клавиш пользователем), StartPosition=CenterScreen.
Для перетаскивания формы за пустое место надо использовать специальные API функции Windows. Для их использование надо подключать специальный *.dll файл и экспортировать из него нужны процедуры и функции. Для этого нужно помнить имена таких функций и список их параметров.
Для простоты в нашей работе мы будем использовать готовый файл класса WinAPI со всеми необходимыми методами.
Для использование этого файла класса в окне "Обозреватель решений"вызовите контекстное меню проекта и выберите команду "Добавить - Существующий элемент"и укажите файл скачанного класса. В результате в структуре вашего проекта должен появиться новый файл класса WinAPI.cs Откройте файл класса и убедитесь, что его название пространства имен namespace ... совпадает с названием пространства имен класса формы namespace ... Если это не так, то поменяйте в файле добавленного класса название пространства имен на нужное.
Для перетаскивания формы в ее событии MouseDown напишите код:
void Form1_MouseDown(object sender, MouseEventArgs e)
{
//если пользователь удерживает клавиши CTRL + ALT
//и одновременно держит левую кнопку мыши
if ((ModifierKeys & Keys.Control) ==Keys.Control
&& (ModifierKeys & Keys.Alt)==Keys.Alt
&& e.Button== MouseButtons.Left)
{
//делаем форму полупрозрачной
Opacity=0.5;
//перетаскиваем форму по экрану
WinAPI.ReleaseCapture();
WinAPI.SendMessage(Handle, 0xa1, 0x2, 0);
//после отпускания кнопки мыши восстанавливаем прозрачность
Opacity=1;
}
}
При наведении мыши на текстовое поле меняется фон поля на желтый, а в строке статуса отображается текст "Первое поле" или "Второе поле"
Указания: На форму нанесите два текстовых поля, для которых в свойстве Text удалите данные.
На форму нанесите компонентов StatusStrip, с помощью свойства Items в новом окне добавьте 3 панели. Для каждой панели задайте свойство AutoSize = false, Text очистить, Width = 150 ( для первой панели) и 40 ( для двух других). Во второй панели будет отображаться состояние клавиши NumLock и по умолчанию она должна быть включена, поэтому для второй панели задайте свойство Text = NUM.
Для обработки наведения мыши на поле в событии MouseMove поля textBox1 напишем код:
void textBox1_MouseMove(object sender, MouseEventArgs e)
{
//поле становится желтым
textBox1.BackColor=Color.Yellow;
//в первой панели строки статуса появляется текст
toolStripStatusLabel1.Text="Первое поле";
}
В событии MouseMove поля textBox2 напишем код:
void textBox2_MouseMove(object sender, MouseEventArgs e)
{
//поле становится желтым
textBox2.BackColor=Color.Yellow;
//в первой панели строки статуса появляется текст
toolStripStatusLabel1.Text="Второе поле";
}
При перемещении мыши из полей надо восстанавливать начальное состояние компонентов на форме. Если пользователь перемещает мышь за пределы поля, то он автоматически наводит мышь на форму. Поэтому в событии MouseMove формы напишем код:
void Form1_MouseMove(object sender, MouseEventArgs e)
{
//восстанавливаем цвет обоих полей
textBox1.BackColor=textBox2.BackColor=SystemColors.Window;
//очищаем первую панель строки статуса
toolStripStatusLabel1.Text="";
}
При входе в первое поле язык на клавиатуре переключается на "английский". При входе во второе поле - на "русский".
Указания: для переключения языка в первом поле нужно в событии Enter поля textBox1 написать текст:
void textBox1_Enter(object sender, EventArgs e)
{
//включаем английский язык
InputLanguage.CurrentInputLanguage =
InputLanguage.FromCulture(new System.Globalization.CultureInfo("en-Us"));
}
Для переключения языка во втором поле нужно в событии Enter поля textBox2 написать текст:
void textBox2_Enter(object sender, EventArgs e)
{
//включаем русский язык
InputLanguage.CurrentInputLanguage =
InputLanguage.FromCulture(new System.Globalization.CultureInfo("ru-Ru"));
}
В первое текстовое поле можно ввести только числа, а во второе - только русские буквы;
Указания: Для ограничения ввода в первое текстовое поле только цифр необходимо в событии KeyPress поля textBox1 написать код:
void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
//если пользователь ввел точку или запятую в числе
//надо заменить ее на символ десятичной точки,
//принятый в настройках операционной системы пользователя
//например, русская Windows в качестве точки использую запятую
//английская Windows в качестве точки использует точку
// для этого опишем переменную и сохраним в нее символ разделителя, принятый в ОС пользователя
char ch = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator[0];
//если пользователь ввел точку или запятую в числе
if (e.KeyChar=='.' || e.KeyChar==',')
//заменяем
ее на соответствующий символ десятичной точки из операционной системы
e.KeyChar=ch;
//если введена не цифра (0..9), не Backspace (8), не десятичная точку, или не минус
if ((e.KeyChar <'0' || e.KeyChar >'9') && e.KeyChar !=8 && e.KeyChar !=ch && e.KeyChar !='-'
//или, если введена десятичная точка, но она уже есть (IndexOf(ch)!=-1)
|| (e.KeyChar == ch && textBox1.Text.IndexOf(ch)!=-1)
//или, если введен минус, но он уже есть (IndexOf('-')!=-1)
|| (e.KeyChar == '-' && textBox1.Text.IndexOf('-')!=-1)
//или, если введен минус, но он не первый в поле (SelectionStart>0)
|| (e.KeyChar == '-' && textBox1.SelectionStart>0))
//то введенный символ игнорируется
e.KeyChar='\0';
}
Для ограничения ввода во второе текстовое поле только русских букв необходимо для события KeyPress поля textBox2 написать код:
void textBox2_KeyPress(object sender, KeyPressEventArgs e)
{
//если введенный символ не русская буква (А..я) и не Backspace (8)
if ((e.KeyChar <'А' || e.KeyChar >'я') && e.KeyChar !=8)
//то символ заменяется на нулевой
e.KeyChar='\0';
}
Переключатели " Сумма" и "Разность" должны выбираться пользователем с помощью клавиш левый ALT + 1 и правый ALT+2;
Указания: На форму нанесите компонент GroupBox и в свойстве Text удалите текст. На созданном компоненте разместите два компонента RadioButton и в свойстве Text введите названия переключателей. Один из переключателей должен быть выбранным ( обычно первый). Для первого переключателя укажите свойство Checked = True.
Для того, чтобы форма могла реагировать на нажатие клавиш, нужно для формы установить свойство KeyPreview = True. Для распознавания левой или правой специальной клавиши будем использовать API функцию GetAsyncKeyState(код клавиши) из класса WinAPI.
Для включения переключателей с помощью комбинации клавиш необходимо в событии KeyDown формы написать код:
void Form1_KeyDown(object sender, KeyEventArgs e)
{
//если нажаты клавиши левый Alt + 1
if (WinAPI.GetAsyncKeyState(Keys.LMenu)!=0 && e.KeyCode == Keys.D1)
//включаем первый переключатель
radioButton1.Checked = true;
//иначе, если нажаты клавиши правый Alt + 2
else if (WinAPI.GetAsyncKeyState(Keys.RMenu)!=0 && e.KeyCode == Keys.D2)
//включаем второй переключатель
radioButton2.Checked = true;
}
Флажок на форме переключается комбинацией клавиш Ctrl + F.
Указания: На форму нанесите компонент CheckBox, в свойстве Text укажите текст надписи возле флажка. Для включения/выключение флажка с помощью комбинации клавиш необходимо в событии KeyDown формы к уже существующему коду добавить команды:
//если нажаты клавиши Ctrl + F
if (e.Control && e.KeyCode==Keys.F)
//переключатель переводим в противоположное состояние
checkBox1.Checked=!checkBox1.Checked;
В строке статуса в первом поле отображать текст "CAPS", если включена клавиша CapsLock, во втором поле отображать текст "NUM", если включенная клавиша NumLock
Указания: код обработки нажатий клавиш CapsLock и NumLock будем писать в событии формы KeyUp. Событие KeyDown не подходит, потому что в этом событии клавиша нажата и еще не отпущенная пользователем. Поэтому не всегда удается распознать состояние клавиши (включена или отключена). В событии KeyUp клавиша уже отпущена и ее состояние распознается верно.
В событии KeyUp формы напишите код:
void Form1_KeyUp(object sender, KeyEventArgs e)
{
//если NumLock нажата
if (Control.IsKeyLocked(Keys.NumLock))
// во второй панели строки статуса отображаем текст NUM
toolStripStatusLabel2.Text="NUM";
//иначе, если NumLock отжата
else
//во второй панели строки статуса удаляем текст
toolStripStatusLabel2.Text="";
//если CapsLock нажата
if (Control.IsKeyLocked (Keys.Capital))
// в третьей панели строки статуса отображаем текст CAPS
toolStripStatusLabel3.Text="CAPS";
//иначе, если CapsLock отжата
else
//в третьей панели строки статуса удаляем текст
toolStripStatusLabel3.Text="";
}
При запуске программы клавиатура должная автоматически переключаться на украинский язык, выключаться клавиши CapsLock (если она включена) и включаться клавиши NumLock (если она выключена)
Указания: Для автоматического переключения на украинский язык в событии формы Load введите команду:
void Form1_Load(object sender, EventArgs e)
{
//включаем украинский язык
InputLanguage.CurrentInputLanguage =
InputLanguage.FromCulture(new System.Globalization.CultureInfo("uk-Ua"));
}
Для настройки клавиш CapsLock и NumLock при старте программы необходимо проверить их состояние (вкл/выкл) и нажать на клавишу, если это нужно (если CapsLock включен - нажимаем для выключения, если NumLock выключен - нажимаем для включения). Для программного нажатия на клавишу будем использовать API функцию keybd_event()из класса WinAPI . При этом данная функция вызывается два раза с разным набором параметров. Первый вызов функции нажимает клавишу, второй - отпускает.
В событие Load формы к существующему коду добавьте команды:
//если клавиша NumLock выключена
if (!Control.IsKeyLocked (Keys.NumLock))
{
//нажимаем клавишу
WinAPI.keybd_event(Keys.NumLock, 0x45, 0, IntPtr.Zero );
//отпускаем клавишу
WinAPI.keybd_event(Keys.NumLock, 0x45, 2, IntPtr.Zero);
}
//если клавиша CapsLock включена
if (Control.IsKeyLocked (Keys.Capital))
{
//нажимаем клавишу
WinAPI.keybd_event(Keys.Capital, 0x45, 0, IntPtr.Zero );
//отпускаем клавишу
WinAPI.keybd_event(Keys.Capital, 0x45, 2, IntPtr.Zero);
}
На форме создайте кнопку, которая невидима при запуска программы, но становится видимой при нажатии на клавиши ALT + CTRL + F1. Кнопка должна перемещаться по форме с помощью клавиш управления курсором (стрелок). Для кнопки напишите код, который завершает работу с программой
Указания: Для создания скрытой кнопки нанесите на форму компонентов Button и задайте ей свойства: Text = Выход, Visible = False. Для отображения скрытой кнопки на форме в событии KeyDown формы к существующему коду добавьте команды:
//если нажати клавиши Alt + Ctrl + F1
if (e.Alt && e.Control && e.KeyCode==Keys.F1)
//кнопка становится видимой
button1.Visible=true;
Для перемещения кнопки с помощью стрелок управления курсором нужно в событие KeyDown формы добавить код:
//анализируем нажатую клавишу
switch (e.KeyCode)
{
//если нажата клавиша "вверх"
case Keys.Up:
//кнопка смещается вверх
button1.Top-=5;
break;
//если нажата клавиша "вниз"
case Keys.Down:
//кнопка смещается вниз
button1.Top+=5;
break;
//если нажата клавиша "влево"
case Keys.Left:
//кнопка смещается влево
button1.Left-=5;
break;
//если нажата клавиша "вправо"
case Keys.Right:
//кнопка смещается вправо
button1.Left+=5;
break;
}
Для того, чтобы кнопка завершала работу с программой необходимо в событии Click кнопки написать код:
void button1_Click(object sender, EventArgs e)
{
Close();
}