netlib.narod.ru< Назад | Оглавление | Далее >

Упражнение на определение позиции курсора

Изображая на форме графические фигуры и текст, обычно сначала определяют координаты всех элементов, после чего рисуют их, вызывая соответствующие методы. Но часто в программах применяют интерфейс на основе мыши, чтобы дать пользователю возможность выбирать графические объекты и манипулировать ими. Значит, программа должна работать по обратному принципу, определяя координаты указателя, чтобы выяснить, на какой графический элемент указывает мышь.

Этот процесс называется определением позиции курсора (hit-testing). Он может быть довольно сложным, особенно если клиентское окно содержит перекрывающиеся фигуры и текст, набранный пропорциональным шрифтом, но иногда определить позицию курсора довольно просто. Фактически показанная выше программа MouseCursors определяет позицию курсора, чтобы узнать, какой вид ему следует придать.

Программа Checker рисует в своей клиентской области несколько прямоугольников. Если щелкнуть по нарисованному программой прямоугольнику, в нем появится крестик, который исчезнет при повторном щелчке.

Checker.cs

  //----------------------------------------
  // Checker.cs (C) 2001 by Charles Petzold
  //----------------------------------------
  using System;
  using System.Drawing;
  using System.Windows.Forms;

  class Checker: Form
  {
      protected const int     xNum = 5;  // Кличество клеток по горизонтали
      protected const int     yNum = 4;  // Количество клеток по вертикали
      protected       bool[,] abChecked = new bool[yNum, xNum];
      protected       int     cxBlock, cyBlock;

      public static void Main()
      {
          Application.Run(new Checker());
      }
      public Checker()
      {
          Text = "Checker";
          BackColor = SystemColors.Window;
          ForeColor = SystemColors.WindowText;
          ResizeRedraw = true;

          OnResize(EventArgs.Empty);
      }
      protected override void OnResize(EventArgs ea)
      {
          base.OnResize(ea);      // Иначе ResizeRedraw не будет работать

          cxBlock = ClientSize.Width  / xNum;
          cyBlock = ClientSize.Height / yNum;
      }
      protected override void OnMouseUp(MouseEventArgs mea)
      {
          int x = mea.X / cxBlock;
          int y = mea.Y / cyBlock;

          if (x < xNum && y < yNum)
          {
              abChecked[y, x] ^= true;
              Invalidate(new Rectangle(x * cxBlock, y * cyBlock,
                                       cxBlock,     cyBlock));
          } 
      }
      protected override void OnPaint(PaintEventArgs pea)
      {
          Graphics grfx = pea.Graphics;
          Pen      pen  = new Pen(ForeColor);

          for (int y = 0; y < yNum; y++)
          for (int x = 0; x < xNum; x++)
          {
              grfx.DrawRectangle(pen, x * cxBlock, y * cyBlock,
                                      cxBlock,     cyBlock);
              if (abChecked[y, x])
              {
                  grfx.DrawLine(pen, x      * cxBlock,  y      * cyBlock,
                                    (x + 1) * cxBlock, (y + 1) * cyBlock);
                  grfx.DrawLine(pen, x      * cxBlock, (y + 1) * cyBlock,
                                    (x + 1) * cxBlock,  y      * cyBlock);
              }
          }
      }
  }

При любом изменении размеров формы программа пересчитывает значения cxBlock и cyBlock, задающие размеры каждого прямоугольника. Программа также поддерживает массив abChecked, хранящий значения типа bool, каждое из которых указывает, есть ли крестик в некотором прямоугольнике. Метод OnPaint рисует контур каждого прямоугольника и, если значение abChecked для этого прямоугольника равно true, рисует в нем крестик.

Определение позиции курсора происходит при исполнении метода OnMouseUp (я выбрал именно его, а не OnMouseDown, чтобы точнее воспроизвести событие OnClick, происходящее при отпускании кнопки мыши). Программа делит значения координат мыши на cxBlock и cyBlock, чтобы получить значения индексов в массиве abChecked. После этого она инвертирует значение переменной типа bool и делает недействительным соответствующий прямоугольник.

Вот типичный вид программы Checker после зачеркивания нескольких прямоугольников:


Рис. 8.4.


netlib.narod.ru< Назад | Оглавление | Далее >

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