| netlib.narod.ru | < Назад | Оглавление | Далее > |
В начале этой главы я сказал, что надо пытаться писать программы Windows Forms так, чтобы с ними можно было работать как при помощи мыши, так и клавиатуры. Я бесстыдно игнорировал собственное правило, чтобы сосредоточиться на логике работы с мышью. Думаю, сейчас у нас есть хорошая возможность разобраться, что нужно для эмуляции мыши в программе Checker при помощи клавиатуры.
Во-первых, нужно решить, как должен работать интерфейс, использующий клавиатуру. Для этой программы разумно будет разрешить пользователю двигать курсор мыши по клиентской области стрелками и другими клавишами управления курсором. Щелчки мыши можно воспроизвести при помощи клавиши Enter или пробела.
В этой программе класс CheckerWithKeyboard является наследником Checker, в котором реализована поддержка интерфейса, использующего клавиатуру.
CheckerWithKeyboard.cs
//----------------------------------------------------
// CheckerWithKeyboard.cs (C) 2001 by Charles Petzold
//----------------------------------------------------
using System;
using System.Drawing;
using System.Windows.Forms;
class CheckerWithKeyboard: Checker
{
public new static void Main()
{
Application.Run(new CheckerWithKeyboard());
}
public CheckerWithKeyboard()
{
Text += " with Keyboard Interface";
}
protected override void OnGotFocus(EventArgs ea)
{
Cursor.Show();
}
protected override void OnLostFocus(EventArgs ea)
{
Cursor.Hide();
}
protected override void OnKeyDown(KeyEventArgs kea)
{
Point ptCursor = PointToClient(Cursor.Position);
int x = Math.Max(0, Math.Min(xNum - 1, ptCursor.X / cxBlock));
int y = Math.Max(0, Math.Min(yNum - 1, ptCursor.Y / cyBlock));
switch(kea.KeyCode)
{
case Keys.Up: y--; break;
case Keys.Down: y++; break;
case Keys.Left: x--; break;
case Keys.Right: x++; break;
case Keys.Home: x = y = 0; break;
case Keys.End: x = xNum - 1;
y = yNum - 1; break;
case Keys.Enter:
case Keys.Space:
abChecked[y, x] ^= true;
Invalidate(new Rectangle(x * cxBlock, y * cyBlock,
cxBlock, cyBlock));
return;
default:
return;
}
x = (x + xNum) % xNum;
y = (y + yNum) % yNum;
Cursor.Position = PointToScreen(new Point(x*cxBlock + cxBlock/2,
y*cyBlock + cyBlock/2));
}
}
Сначала рассмотрим обработку OnKeyDown. Программа определяет текущую позицию курсора при помощи свойства CursorPosition и преобразует полученные координаты в координаты клиентской области. Переменные x и y указывают строку и столбец, в которых находится ближайший к курсору прямоугольник; x варьируется от 0 до числа прямоугольников по горизонтали минус один, а y — от 0 до числа прямоугольников по вертикали минус один.
При нажатии клавиш управления курсором программа модифицирует переменные x и y. Клавиша Home помещает курсор в верхний левый прямоугольник, a End — в нижний правый. На нажатие Enter или пробела программа реагирует, как на событие OnMouseUp: она изменяет значение элемента массива для данного прямоугольника и делает этот прямоугольник недействительным. Обработка OnKeyDown завершается расчетом новой позиции курсора мыши и установкой свойства Cursor.Position.
Сама по себе обработка OnKeyDown работала бы замечательно, если бы не одно «но»: интерфейс, использующий клавиатуру, по-настоящему нужен лишь в отсутствие мыши. Но если нет мыши, то и курсор невидим! Поэтому программа и переопределяет методы OnGetFocus и OnLostFocus, просто вызывая CursorShow и Cursor.Hide.
| netlib.narod.ru | < Назад | Оглавление | Далее > |