Шаг 282.
Язык программирования C#. Начала.
Приложения с графическим интерфейсом. Координаты курсора мыши

    На этом шаге мы рассмотрим пример использования параметров курсора мыши.

    Еще один пример, который мы рассмотрим в этом разделе, связан с использованием параметров курсора мыши. Кроме этого, мы увидим, как можно выполнять рисование в области графического компонента. Программа выполняется следующим образом. Вначале отображается окно с большой областью желтого цвета и меткой в верхней части окна. Как выглядит окно в начале выполнения программы, показано на рисунке 1.


Рис.1. При запуске программы отображается окно с меткой и большой желтой панелью в центре

    Если курсор мыши оказывается над желтой областью, то он приобретает вид ладони, а через точку размещения курсора проходят две толстые линии (горизонтальная и вертикальная) синего цвета. Также в метке отображаются координаты курсора в системе координат, связанной с желтой областью. Точка начала координат находится в левом верхнем углу области, координаты определяются в пикселях как расстояние по горизонтали и вертикали от точки начала координат до точки в области (для которой определяются координаты). Как выглядит окно при наведенном на желтую область курсоре мыши, показано на рисунке 2.


Рис.2. При наведении курсора на область панели отображаются две линии и координаты курсора

    При перемещении курсора мыши в области автоматически меняются значения координат в метке над областью, а также автоматически, вслед за курсором, перемещаются синие линии. Ситуацию иллюстрирует рисунок 3.


Рис.3. При перемещении курсора над панелью синхронно изменяются значения координат курсора и расположение линий

    В общих чертах так функционирует интересующая нас программа. Теперь проанализируем код программы, представленный ниже.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Drawing;
using System.Windows.Forms;

namespace pr282_1
{
    // Класс окна: 
    class MyForm: Form {
        // Ссылка на объект для рисования:
        Pen p;
        // Ссылка на объект графического контекста:
        Graphics g;
        // Конструктор: 
        public MyForm(): base() {
            // Размеры окна: 
            this.Width = 325;
            this.Height = 380;
            // Окно фиксированных размеров: 
            this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
            // Заголовок окна: 
            this.Text = "Координаты курсора";
            // Объект метки:
            Label lbl = new Label();
            // Размеры метки:
            lbl.Width = 300;
            lbl.Height = 30;
            // Положение метки: 
            lbl.Location = new Point(5,5);
            // Рамка для метки: 
            lbl.BorderStyle = BorderStyle.Fixed3D;
            // Шрифт для метки:
            lbl.Font = new Font("Arial", 10, FontStyle.Bold);
            // Способ выравнивания текста в метке: 
            lbl.TextAlign = ContentAlignment.MiddleCenter;
            // Добавление метки в окно: 
            this.Controls.Add(lbl);
            // Объект панели:
            Panel pnl = new Panel();
            // Размеры панели:
            pnl.Width = lbl.Width;
            pnl.Height = 300;
            // Положение панели:
            pnl.Top = lbl.Bottom + 5;
            pnl.Left = lbl.Left;
            // Рамка для панели: 
            pnl.BorderStyle = BorderStyle.Fixed3D;
            // Цвет панели:
            pnl.BackColor = Color.Yellow;
            // Вид курсора над панелью: 
            pnl.Cursor = Cursors.Hand;
            // Объект для рисования: 
            p = new Pen(Color.Blue, 3);
            // Объект графического контекста для панели: 
            g = pnl.CreateGraphics();
            // Обработчик события, связанного с движением курсора 
            // над областью панели: 
            pnl.MouseMove += (obj, ea) => {
                // Перерисовка панели: 
                pnl.Refresh();
                // Текст для метки: 
                lbl.Text = "Горизонталь: " + ea.X; 
                lbl.Text += "     ";
                lbl.Text += "Вертикаль: " + ea.Y;
                // Отображение линий:
                g.DrawLine(p, new Point(0, ea.Y), new Point(pnl.ClientSize.Width, ea.Y)); 
                g.DrawLine(p, new Point(ea.X, 0), new Point(ea.X, pnl.ClientSize.Height));
            };
            // Обработчик события, связанного с перемещением 
            // курсора за пределы панели: 
            pnl.MouseLeave += (obj, ae) => {
                // Текст для метки: 
                lbl.Text = "";
                // Перерисовка панели: 
                pnl.Refresh();
            };
            // Добавление панели в окно: 
            this.Controls.Add(pnl);
        }
        // Деструктор:
        ~MyForm() {
            // Освобождение ресурсов, задействованных
            // для рисования:
            g.Dispose();
            p.Dispose();
        }
    }

    // Главный класс: 
    class Programs
    {
        [STAThread]
        // Главный метод: 
        static void Main()
        {
            // Отображение окна:
            Application.Run(new MyForm());
        }
    }
}
Архив проекта можно взять здесь.

    В классе окна MyForm есть поле p класса Pen и поле g класса Graphics (оба класса из пространства имен System.Drawing). Это ссылки на объекты, которые нам понадобятся при рисовании линий.

    В конструкторе класса создается метка (объект lbl класса Label) и панель (объект pnl класса Panel). Для них и для объекта окна задаются их размеры и положение, а также ряд других параметров (назначение соответствующих команд должно быть понятно из контекста). Для панели командой

  pnl.BackColor = Color.Yellow;
задается желтый цвет фона. Команда
  pnl.Cursor = Cursors.Hand;
используется для того, чтобы задать вид курсора мыши, когда он находится над областью панели. В данном случае свойству Cursor объекта панели pnl в качестве значения присваивается константа Hand из перечисления Cursors, и поэтому над областью панели курсор будет принимать вид ладони.

    Поскольку мы собираемся рисовать линии, то нам понадобится два объекта. Первый объект создается на основе класса Pen. Объект создается командой

  p = new Pen(Color.Blue, 3);            . 
Он содержит информацию о цвете и толщине линий в процессе рисования. Командой
  g = pnl.CreateGraphics();
в поле g записывается ссылка на объект графического контекста для панели. Этот объект необходим для получения доступа к ресурсам, задействованным при рисовании в области графического компонента (в данном случае панели).

    Для панели определяются обработчики для события MouseMove, связанного с перемещением курсора над областью панели, а также для события MouseLeave, связанного с перемещением курсора за пределы панели. В частности, в список обработчиков события MouseMove объекта панели pnl добавляется ссылка на анонимный метод, определенный лямбда-выражением. В теле метода командой

  pnl.Refresh(); 
выполняется перерисовка панели. Это необходимо, чтобы стереть линии, нарисованные для предыдущего положения курсора. Командами
  lbl.Text = "Горизонталь: " + ea.X;    , 
  lbl.Text += "     ";
  и 
  lbl.Text += "Вертикаль: " + ea.Y;
определяется текст метки (команд три, хотя можно было воспользоваться и одной). Здесь использованы выражения ea.X и ea.Y, которые возвращают координаты (горизонтальную и вертикальную, соответственно) курсора мыши в области панели.


Делегат EventHandler, которому должны соответствовать методы-обработчики для событий графических компонентов, подразумевает наличие у метода второго аргумента (объявлен как переменная класса EventArgs), содержащего информацию о событии. В данном случае второй аргумент обозначен как ea. Его свойства X и Y позволяют определить координаты курсора мыши в момент события.

    Для отображения линий использованы команды

  g.DrawLine(p, new Point(0, ea.Y), new Point(pnl.ClientSize.Width, ea.Y));  и 
  g.DrawLine(p, new Point(ea.X, 0), new Point(ea.X, pnl.ClientSize.Height));  . 
В обоих случаях из объекта графического контекста g вызывается метод DrawLine(), предназначенный для отображения линии. Первым аргументом методу передается объект p класса Pen, который определяет цвет и толщину линии. Два других аргумента метода - объекты класса Point, определяющие начальную и конечную точки, которые соединяет линия.


Выражения pnl.ClientSize.Width и pnl.ClientSize.Height определяют, соответственно, ширину и высоту клиентской (внутренней, доступной для использования) области панели.

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

  lbl.Text = "";
выполняется очистка содержимого метки, а командой
  pnl.Refresh(); 
выполняется перерисовка панели.


В классе MyForm определен еще и деструктор. В деструкторе выполняются команды
  g.Dispose(); 
и 
  p.Dispose();   , 
которыми освобождаются ресурсы, задействованные для рисования. Правда в данном случае особого смысла в этих командах нет - при удалении объекта окна из памяти эти ресурсы и так освободятся. Главная причина, по которой описан деструктор, - подчеркнуть, что с ресурсами следует обращаться экономно.

    Для отображения окна в главном методе используется команда

  Application.Run(new MyForm());   .

    На следующем шаге мы подведем итог изученному материалу.




Предыдущий шаг Содержание Следующий шаг