Практическое занятие № 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();

}