Опубликован: 13.07.2010 | Доступ: свободный | Студентов: 889 / 20 | Оценка: 4.40 / 4.20 | Длительность: 77:34:00
Самостоятельная работа 26:

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

Переопределение наследуемого от Control виртуального метода диспетчеризации события Click

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

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

Воспользуемся этой возможностью в нашем классе расширения кнопки, упаковав переопределение метода в отдельную часть класса BeepButton.

  • Дополните конец файла BeepButton.cs следующим кодом
namespace MyCompany.UserControls
{
    partial class BeepButton
    {
        // Переопределяем виртуальный метод диспетчеризации
        // класса Control (задействуется наследуемый метод
        // диспетчеризации класса кнопки)
        protected override void OnClick(EventArgs e)
        {
            // Проиграть системный звук 
            SystemSounds.Exclamation.Play();// Сочный через внешние динамики
            //SystemSounds.Beep.Play();     // Простой через внешние динамики
            //System.Console.Beep();        // Простой через внутренний динамик
    
            // Подняться до базового класса Control,
            // чтобы сгенерировать его событие Click и 
            // запустить наш будущий обработчик ButtonOnClick
            base.OnClick(e);
        }
    }
}
Листинг 19.2. Переопределение метода диспетчеризации OnClick() в файле BeepButton.cs

В переопределенном методе диспетчеризации события Click кнопки мы предусмотрели вызов базового метода диспетчеризации непосредственно кнопки Button, чтобы дать возможность клиентам нашего класса BeepButton подписать свои обработчики на это событие. Событие Click, в свою очередь, унаследовано классом Button от класса Control и генерируется его методом OnClick примерно так

protected virtual void OnClick(EventArgs args)
        {
            //...
            // Если хоть один обработчик зарегистрирован
            if (Click != null)
                Click(this, args);
            //...
        }

Испытание кнопки BeepButton мы проведем позднее, разработав для этого тестовую исполнимую Windows -сборку.

Упражнение 2. Проектирование диалогового окна сообщений MyDialogBox

Для целей выдачи пользователю простых сообщений существует стандартное диалоговое окно, поддерживаемое классом System.Windows.Forms. MessageBox. Но в целях тренировки в данном разделе мы спроектируем собственное простое диалоговое окно сообщений с именем MyDialogBox, которое и будет вызываться из обработчика события Click нашей кнопки, если на него подпишется клиент компонента BeepButton.

Создание диалогового окна будет состоять из трех шагов:

  1. Создание самой формы диалогового окна (класс MyDialogForm )
  2. Размещение на форме интерфейсных элементов пользователя
  3. Создание класса MyDialogBox.cs, управляющего диалоговым окном
  • В панели Solution Explorer выделите узел проекта UserControls и командой Add/Windows Form добавьте к компоненту файл формы с именем MyDialogForm.cs

  • Удалите из узла References лишние добавленные мастером ссылки на библиотечные сборки System.Data и System.Xml


  • Удалите соответствующие инструкции using подключения пространств имен в начале файла MyDialogForm.cs
  • Настройте форму MyDialogForm в соответствии с таблицей
Таблица свойств формы MyDialogForm
Свойство Значение Пояснения
StartPosition CenterScreen Открывать в центре экрана
FormBorderStyle FixedDialog Запретить пользователю менять размер
MaximizeBox false Отключить системную кнопку развертывания
MinimizeBox false Отключить системную кнопку свертывания
ShowInTaskbar false Запретить появление в панели задач
AutoSize true Подстраиваться под содержимое
AutoSizeMode GrowAndShrink Подстраиваться под содержимое (расширяться и сжиматься)
Text Пусто Заголовок окна
  • Из свитка Containers панели инструментов Toolbox поместите на форму компоновочную панель FlowLayoutPanel и настройти ее в соответствии с таблицей
Таблица свойств компоновочной панели FlowLayoutPanel
Свойство Значение Пояснения
Name flow Имя компоновочной панели
AutoSize true Подстраиваться под содержимое
FlowDirection TopDown Размещать сверху вниз
WrapContents false Не переносить дочерние элементы в следующий столбец
Padding.All 8 Внутренний отступ дочерних элементов по периметру окна
Dock Fill Распахнуть на всю клиентскую область родителя (формы)

Эта панель будет следить за размещением своих дочерних элементов в соответствии с настройками.

  • Поместите внутрь экземпляра компоновочной панели flow из свитка Common Controls текстовую метку Label и настройте ее свойства в соответствии с таблицей
Таблица свойств текстовой метки Label
Свойство Значение Пояснения
Name lblMessage Имя текстовой метки
AutoSize true Подстраиваться под содержимое
Anchor None Расположить посредине
Margin.All 8 Отступ по наружному периметру текстовой метки
Modifiers Public Публичный доступ для клиентов формы (для класса MyDialogBox)

Для того, чтобы объект lblMessage был доступен из метода класса MyDialogBox, при его создании мы сделали его общедоступным.

  • Поместите внутрь компоновочной панели flow из свитка Common Controls кнопку Button и настройте ее свойства в соответствии с таблицей
Таблица свойств кнопки Button
Свойство Значение Пояснения
Name btnShowDialog Имя кнопки
AutoSize true Подстраиваться под содержимое
Anchor None Расположить посредине
Margin.All 8 Отступ по наружному периметру кнопки
Text OK Надпись
DialogResult OK Назначить статус "кнопки OK" в родительской форме

Свойству дочерних кнопок формы DialogResult можно присвоить любое значение из перечисления System.Windows.Forms. DialogResult ( Abort, Cancel, Ignore, No, None, OK, Retry, 26_23 ). Оно и будет возвращено функцией ShowDialog() формы, если пользователь выберет именно эту кнопку.

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

  • В панели Solution Explorer выделите узел проекта UserControls и, выполнив команду меню Project/Add Class, добавьте к проекту новый класс с именем MyDialogBox

  • Заполните файл MyDialogBox.cs следующим кодом
using System;
using System.Windows.Forms;
    
namespace MyCompany.UserControls
{
    // Наше диалоговое окно сообщения
    public class MyDialogBox
    {
        public static DialogResult Show(string strMessage, string strCaption)
        {
            // Создаем диалоговое окно
            MyDialogForm frm = new MyDialogForm();
            // Заголовок окна
            frm.Text = strCaption;
            // Содержимое текстовой метки
            frm.lblMessage.Text = strMessage;
    
            // Отобразить диалоговое окно в модальном режиме,
            // а после его закрытия вернуть выбор пользователя 
            // вызывающему коду
            return frm.ShowDialog();// Выполняем диалоговое окно
                                    // и возвращаем статус нажатой кнопки
        }
    }
}
Листинг 19.4. Код управления диалоговым окном в файле MyDialogBox.cs

Класс MyDialogBox нужно объявить с модификатором public, чтобы он был виден в клиентских сборках. Объявление метода Show() в классе MyDialogBox как статического позволяет его вызывать без создания экземпляра этого класса в клиенте. Через аргументы метода Show() можно задавать заголовок диалогового окна и содержимое текстовой метки lblMessage, как это принято в библиотечном классе System.Windows.Forms.MessageBox.

Теперь осталось собрать все вместе и испытать на тестовом приложении, но прежде нужно откомпилировать проект UserControls и убедиться, что нет синтаксических ошибок.

  • Выполните команду меню оболочки Build/Build UserControls, чтобы откомпилировать проект нашей библиотеки пользовательских элементов управления