Шаг 274.
Язык программирования C#. Начала.
Приложения с графическим интерфейсом. Окно и обработка событий

    На этом шаге мы рассмотрим пример обработки событий окна.

    Еще один пример, который мы рассмотрим далее, также связан с созданием пустого окна. Но на этот раз окно будет более функциональным. Кроме того, если в предыдущем примере все команды по созданию и отображению окна размещались в главном методе программы, то теперь мы пойдем другим путем. Мы опишем класс, на основе которого будет создаваться окно, и этот класс будет наследовать класс Form. Для отображения окна в классе описан специальный статический метод. Также окно реагирует на действия мыши: при наведении курсора мыши на область окна фон окна становится красным. Когда курсор мыши перемещается за пределы области окна, цвет фона окна возвращается к первоначальному значению.

    Рассмотрим представленный ниже программный код.

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

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

namespace pr274_1
{
    // Класс создается наследованием класса Form: 
    class MyForm: Form
    {
        // Закрытое поле для запоминания фонового цвета окна: 
        private Color baseColor;
        // Конструктор:
        public MyForm(string txt)
            : base()
        {
            // Заголовок окна:
            Text = txt;
            // Высота окна:
            Height = 200;
            // Ширина окна:
            Width = 300;
            // Окно неизменных размеров: 
            FormBorderStyle = FormBorderStyle.Fixed3D;
            // Считывание значения для фонового цвета окна: 
            baseColor = BackColor;
            // Обработчик для события, связанного с наведением 
            // курсора мыши на область окна: 
            MouseEnter += (a, b) =>
            {
                // Цвет фона окна - красный:
                BackColor = Color.Red;
            };
            // Обработчик события, связанного с выходом курсора 
            // мыши за пределы области окна: 
            MouseLeave += (a, b) =>
            {
                // Применение исходного цвета для фона окна: 
                BackColor = baseColor;
            };
        }
        // Статический метод для отображения окна: 
        public static void show(string txt)
        {
            // Отображение окна:
            Application.Run(new MyForm (txt));
        }
    }

    // Главный класс:
    class Program
    {
        // Атрибут использования однопоточной модели:
        [STAThread]
        // Главный метод: 
        static void Main()
        {
            // Отображение первого окна:
            MyForm.show("Первое окно");
            // Отображение второго окна:
            MyForm.show("Второе окно");
        }
    }
}
Архив проекта можно взять здесь.

    Класс MyForm создается наследованием класса Form. Конструктору класса MyForm при создании объекта передается текстовый аргумент (обозначен как txt). В теле конструктора командой

  Text = txt; 
аргумент присваивается в качестве значения свойству Text. Таким образом, аргумент конструктора определяет заголовок окна, реализуемого через объект класса MyClass.

    Высота окна определяется командой

  Height = 200;           , 
а команда
  Width = 300; 
определяет ширину окна. Кроме этого, мы хотим, чтобы окно имело постоянный размер (то есть чтобы размер окна нельзя было изменить с помощью мыши). Для этого присваивается значение свойству FormBorderStyle объекта окна. Значением присваивается константа Fixed3D из перечисления FormBorderStyle (название такое же, как у свойства). Данная константа означает, что для окна используется объемная рамка, а само окно имеет фиксированные размеры.

    Командой

  baseColor = BackColor; 
значение свойства BackColor объекта окна присваивается полю baseColor. Поле объявлено как относящееся к типу Color. Это структура из пространства имен System.Drawing. Экземпляры этой структуры определяют цвет, который можно применять, присваивая в том числе и в качестве значения свойству BackColor.


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

    Поскольку цвет фона окна может меняться, мы используем поле baseColor для того, чтобы запомнить, каким был цвет фона окна в самом начале, при его создании.

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

    У объектов класса Form (а значит, и у объектов класса MyForm) есть разные события, и среди них: событие MouseEnter и событие MouseLeave. Событие MouseEnter происходит, когда курсор оказывается над областью компонента, для которой определено событие. Событие MouseLeave происходит, когда курсор мыши перемещается за область компонента (окна). В обоих случаях для добавления в список обработчиков событий мы используем лямбда-выражения. Здесь нужно учесть, что для классов графических компонентов события (в том числе MouseEnter и MouseLeave) определены с типом делегата EventHandler (пространство имен System). Это означает, что в список обработчиков событий могут добавляться ссылки на экземпляры делегата EventHandler или ссылки на методы, соответствующие этому делегату. Делегат EventHandler соответствует методам, которые не возвращают результат и у которых два аргумента. Первым аргументом является ссылка класса Object. Подразумевается, что это ссылка на объект компонента, который вызвал событие (с которым событие произошло). Второй аргумент является объектной ссылкой класса EventArgs (пространство имен System). Этот аргумент нужен для передачи информации о параметрах события, которое произошло. Такая информация содержится в объекте, переданном методу в качестве второго аргумента. Что касается класса EventArgs, то он является базовым для классов, объекты которых реально передаются вторым аргументом методам-обработчикам.


Когда на компоненте происходит некоторое событие, то для его обработки вызываются методы из списка обработчиков события. Этим методам передается по два аргумента. Первый аргумент - это ссылка на объект компонента, на котором произошло событие. Второй аргумент - это объект, содержащий сведения о событии. Метод может использовать эти аргументы, а может не использовать. Но аргументы у метода должны быть.

    Компоненты разные, и поэтому объекты компонентов относятся к разным классам. Но поскольку первый аргумент делегата EventHandler является ссылкой класса Object, то фактически этот аргумент может быть ссылкой на объект любого класса. Похожая ситуация имеет место со вторым аргументом. Реальные объекты, которые передаются в качестве второго аргумента при вызове методов из списка обработки события, относятся к классам, производным от класса EventArgs.


    Таким образом, метод, который добавляется в список обработчиков события, должен иметь два аргумента (даже если мы не собираемся эти аргументы использовать). Как отмечалось выше, методы для обработки событий мы определяем с помощью лямбда-выражений. У этих лямбда-выражений есть два формальных аргумента (обозначены как а и b), которые не используются. В теле метода, добавляемого обработчиком для события MouseEnter, выполняется команда

  BackColor = Color.Red;    , 
которой устанавливается красный цвет фона окна. В теле метода, добавляемом обработчиком для события MouseLeave, выполняется команда
  BackColor = baseColor;    , 
которой для фона окна устанавливается исходный цвет (который был у окна при создании).

    Помимо конструктора и закрытого поля baseColor, в классе MyForm описан статический метод Show() с текстовым аргументом (обозначен как txt). При вызове метода выполняется команда

  Application.Run(new MyForm(txt));     . 

    В качестве аргумента метода Run() указана инструкция new MyForm(txt), которой создается анонимный объект класса MyForm. В результате создается объект окна, и это окно отображается на экране. Выполнение метода Run() состоит в опросе на предмет событий, связанных с окном. Проще говоря, пока окно не закрыто, метод Run() продолжает работу.

    В главном методе программы командой

  MyForm.show("Первое окно");
отображается первое окно, представленное на рисунке 1.


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

    Заголовок окна определяется текстом, переданным в качестве аргумента методу show(). Размеры окна изменить нельзя (но при этом с помощью системной пиктограммы можно развернуть окно на весь экран), а если навести курсор мыши на область окна, то фон окна станет красным (рисунок 2).


Рис.2. При наведении курсора мыши на область окна фон окна становится красным

    Если курсор переместить за пределы области окна, то фон окна станет прежним.

    После закрытия окна появляется еще одно окно (результат выполнения команды

  MyForm.show("Второе окно");
). Оно показано на рисунке 3.


Рис.3. После закрытия первого окна появляется еще одно (второе) окно

    От первого окна оно отличается только заголовком. Как и первое окно, второе окно меняет цвет фона при наведении на него курсора мыши.

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




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