netlib.narod.ru | < Назад | Оглавление | Далее > |
Когда программа должна нарисовать фигуру или выполнить действие в ответ на движение мыши, применяется методика отслеживания мыши (mouse tracking). Обычно отслеживание начинается с нажатием кнопки мыши и заканчивается, когда кнопка отпущена. Программе, написанной для среды, не поддерживающей обработку событий, скорее всего придется следить за мышью при помощи непрерывного мониторинга позиции курсора мыши в цикле while. В отличие от нее программа Windows Forms следит за мышью, отвечая на события. Такая архитектура заставляет подходить к решению подобных задач как к работе с конечным автоматом.
Вот небольшая, но забавная программа, демонстрирующая некоторые базовые методы отслеживания курсора мыши.
MouseConnect.cs
//--------------------------------------------- // MouseConnect.cs (C) 2001 by Charles Petzold //--------------------------------------------- using System; using System.Drawing; using System.Windows.Forms; class MouseConnect: Form { const int iMaxPoints = 1000; int iNumPoints = 0; Point[] apoint = new Point[iMaxPoints]; public static void Main() { Application.Run(new MouseConnect()); } public MouseConnect() { Text = "Mouse Connect: Press, drag quickly, release"; BackColor = SystemColors.Window; ForeColor = SystemColors.WindowText; ClientSize += ClientSize; // Удваиваем клиентсукю область } protected override void OnMouseDown(MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) { iNumPoints = 0; Invalidate(); } } protected override void OnMouseMove(MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) { apoint[iNumPoints++] = new Point(mea.X, mea.Y); Graphics grfx = CreateGraphics(); grfx.DrawLine(new Pen(ForeColor), mea.X, mea.Y, mea.X, mea.Y + 1); grfx.Dispose(); } } protected override void OnMouseUp(MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) Invalidate(); } protected override void OnPaint(PaintEventArgs pea) { Graphics grfx = pea.Graphics; Pen pen = new Pen(ForeColor); for (int i = 0 ; i < iNumPoints - 1; i++) for (int j = i + 1; j < iNumPoints; j++) grfx.DrawLine(pen, apoint[i], apoint[j]); } }
Чтобы воспользоваться этой программой, нажмите левую кнопку где-нибудь в пределах клиентской области, сделайте быстрое движение мышью и отпустите кнопку. При каждом вызове метода OnMouseMove программа сохраняет значения свойств X и Y объекта MouseEventArgs и рисует в этой точке крошечную метку.
Когда кнопка отпущена, метод OnMouseUp делает клиентскую область недействительной. OnPaint реагирует на это, соединяя все точки друг с другом, рисуя иногда просто большое пятно, а иногда — довольно интересный узор.
Как видите, двигая курсор, я дважды вышел за пределы клиентской области. Похоже, программу это ничуть не смутило. Она соединила линиями все точки, даже оказавшиеся за пределами клиентской области. Хотя линии были обрезаны по размерам клиентской области, она правильно запомнила расположение всех точек. Если создать аналогичную картину и чуть растянуть клиентскую область по высоте, то можно увидеть нижнюю часть фигуры. Можно даже отпустить кнопку за пределами клиентской области MouseConnect — программа все равно будет работать корректно.
Похоже, все идет, как задумано: пользователь сигнализирует о начале работы с MouseConnect нажатием кнопки мыши в клиентской области программы, и эта работа должна закончиться, как только он отпустит кнопку, независимо от прошлого или текущего положения курсора мыши.
Если нажать любую кнопку мыши, когда курсор находится над элементом управления или над клиентской областью формы, этот элемент управления или форма захватывают мышь и заставляют передавать им все следующие события мыши. Захват прекращается, как только пользователь отпустит кнопку мыши. Способность к захвату мыши фактически необходима для отслеживания мыши и поддерживается автоматически. У класса Control есть свойство типа bool, которое сообщает, идет ли захват мыши:
Свойства Control (выборочно)
Тип | Свойство | Доступ |
bool | Capture | Чтение/запись |
Это изменяемое свойство, но устанавливать произвольно его нельзя. Нельзя, в частности, принудительно включить захват мыши, если не нажата ее кнопка. Однако можно в любое время отменить захват мыши, присвоив этому свойству false (я покажу этот прием ниже). Это свойство также полезно для получения сведений о захвате. Оно равно true во время события MouseDown, с которого начинается захват мыши, и MouseMove, имеющего место при захвате мыши. Во время события MouseUp, освобождающего захват мыши, это свойство равно false. Второй щелчок двойного щелчка не активизирует автоматический захват мыши.
netlib.narod.ru | < Назад | Оглавление | Далее > |