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

Сайт управляется системой uCoz