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 | < Назад | Оглавление | Далее > |