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

Разработка комбинированного компонента

Тестирование генерирующей кнопки ClickmaticButton

  • Закройте все редактируемые текущие документы командой меню Window/Close All Documents
  • В панели Solution Explorer вызовите на редактирование в режиме View Designer форму Form1 двойным щелчком по одноименному узлу
  • В панели Solution Explorer вызовите контекстное меню для узла UserControls проекта пользовательских DLL -компонентов и выполните команду Rebuild, чтобы заново откомпилировать единственный пока компонент ClickmaticButton
  • Откройте панель Toolbox, найдите в верхней ее части свиток для категории UserControls Components и двойным щелчком на расширенном компоненте ClickmaticButton создайте на форме Form1 его экземпляр. Присвойте его свойству Name значение btnClickGen, а свойству Text - значение ClickGen
  • Поместите на форму библиотечный компонент Label для счетчика тиков и присвойте его свойству Name значение lblTickCount
  • Двойным щелчком на экземпляре кнопки ClickmaticButton создайте обработчик события Click, который заполните так
private void btnClickGen_Click(object sender, EventArgs e)
        {
            int tickCount;
            if (!Int32.TryParse(lblTickCount.Text, out tickCount))
                tickCount = 1;  // При некорректном преобразовании установить 1
            else
                tickCount++;    // При корректоном преобразовании увеличить на 1
    
            lblTickCount.Text = tickCount.ToString();
        }
Листинг 19.11. Обработчик события щелчка на кнопке

Статический метод TryParse() структуры Int32 преобразует строковый тип в целый без генерации исключения в случае невозможности выполнить эту операцию. В нашем тесте при первом вызове этого метода свойство Text метки не содержит числовых символов, следовательно преобразование невозможно и метод возвращает false. Мы такую ситуацию контролируем и устанавливаем tickCount=1, иначе увеличиваем значение счетчика.

  • Поместите на форму экземпляр обычного библиотечного компонента Button и присвойте его свойству Text значение Simple
  • Выделите на форме экземпляр обычного компонента Button, переведите панель Properties оболочки в режим Events и через раскрывающийся список в поле события Click присоедините к обычной кнопке тот же обработчик btnClickGen_Click()

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


  • Запустите стартовую форму, выберите тест " Упражнение 1 " и убедитесь в том, что спроектированная нами кнопка имеет дополнительную функциональность генерации щелчков, а также - в том, что работает механизм приостановки таймера в случае выхода курсора за область чувствительности кнопки

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

  • Откройте файл Form1.cs (если он еще не открыт) в режиме View Designer и удалите на ней все экземпляры пользовательского интерфейса, созданные ранее для тестирования кнопки ClickmaticButton
  • С помощью контекстного меню для формы откройте Form1.cs в режиме View Code и удалите вручную обработчик btnClickGen_Click(), поскольку при удалении элементов заполненные обработчики автоматически не удаляются
  • Убедитесь, находясь в режиме Designer формы, что в панели Toolbox компонент ClickmaticButton пока присутствует и готов к размещению на форме
  • Откройте файл ClickmaticButton.cs в режиме View Code и добавьте перед объявлением класса ClickmaticButton ключевое слово abstract
namespace MyCompany.StudName
{
    abstract public partial class ClickmaticButton : Button // : Component
    {
        ......................................
    }
}
Листинг 19.12. Объявление класса ClickmaticButton абстрактным

Таким действием мы запретили создание экземпляров этого класса. Теперь его можно только наследовать.

  • В панели Solution Explorer вызовите контекстное меню для узла UserControls и выполните команду Build
  • Откройте файл Form1.cs в режиме View Designer и убедитесь, что пиктограмма компонента ClickmaticButton исчезла из панели Toolbox

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

  • Потренировались! А теперь восстановите тестовую форму Form1 для " Упражнения 1 ", убрав объявление abstract

Упражнение 2. Разработка кнопки в стиле полос прокрутки

Наследуем от ClickmaticButton еще один класс ArrowButton, в котором переопределим виртуальный метод OnPaint() для отрисовки кнопки как в полосах прокрутки, где надпись будет замещена треугольной стрелкой. Образ скроллирующей кнопки будем отрисовывать методом ControlPaint. DrawScrollButton() из пространства имен System.Windows.Forms. Направление рисования функцией стрелки регулируется ее параметром типа библиотечного перечисления ScrollButton из того же пространства имен.

  • В панели Solution Explorer вызовите контекстное меню для узла UserControls и добавьте к проекту командой Add/Component класс для размещения нового компонента с именем ArrowButton
  • Перейдите в режим View Code, замените наследуемый класс Component на ClickmaticButton, чтобы не потерять ту функциональность, которую мы сделали ранее

Теперь нужно установить такой стиль для кнопки, чтобы в конечном пользовательском элементе (NumericScan - поле с кнопками) она никогда бы не получала фокус ввода. Фокус должен быть только у текстового поля.

  • Поместите в конец каждого из конструкторов ArrowButton() после вызова функции создания и инициализации дочерних компонентов инструкцию установки нужного стиля, а также добавьте подключение необходимых пространств имен

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

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
    
namespace MyCompany.StudName
{
    public partial class ArrowButton : ClickmaticButton
    {
        public ArrowButton()
        {
            InitializeComponent();
    
            // Отключение фокуса ввода 
            this.SetStyle(ControlStyles.Selectable, false);
        }
    
        public ArrowButton(IContainer container)
        {
            container.Add(this);
    
            InitializeComponent();
    
            // Отключение фокуса ввода 
            this.SetStyle(ControlStyles.Selectable, false);
        }
    }
}
Листинг 19.13. Некоторая модификация класса ArrowButton

Определим поле для хранения значения перечисления ориентации скроллирующей кнопки и обернем его в общедоступное свойство. Для этого

  • Дополните класс ArrowButton следующим кодом
// Управление ориентацией стрелки на кнопке
        System.Windows.Forms.ScrollButton scrollButton =
            System.Windows.Forms.ScrollButton.Right;
        public System.Windows.Forms.ScrollButton ScrollButton
        {
            set
            {
                scrollButton = value;
                this.Invalidate();  // Перерисовать
            }
            get { return scrollButton; }
        }
Листинг 19.14. Код поля и свойства управления ориентацией скроллирующей кнопки
  • Начав ввод с ключевого слова override, переопределите в классе ArrowButton унаследованный метод OnPaint() для отрисовки кнопки в стиле скроллирующей и заполните его следующим кодом
// Отрисовка кнопки в стиле со стрелкой
        protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent);       // Отправляем к базовому методу 
                                        // или вообще убираем!!!
    
            Graphics gr = pevent.Graphics;  // Извлекаем контекст устройства
    
            // Кнопка в контакте с мышью и курсор находится в области чувствительности
            bool mouseInButton = this.Capture &&
                this.ClientRectangle.Contains(this.PointToClient(MousePosition));
    
            // Флаг состояния кнопки для управления ее стилем отрисовки
            System.Windows.Forms.ButtonState buttonState =
                !this.Enabled ? ButtonState.Inactive        // Если кнопка недоступна
                : (mouseInButton ? ButtonState.Pushed       // Если доступна и нажата
                : ButtonState.Normal);                      // Если доступна и отпущена
    
            // Рисуем кнопку как кнопку со стрелкой
            ControlPaint.DrawScrollButton(gr, this.ClientRectangle,
                scrollButton,   // В какую сторону рисовать стрелку
                buttonState);   // Каким стилем рисовать
        }
Листинг 19.15. Переопределенный метод OnPaint() для отрисовки скроллирующей кнопки

Когда активная мышь теряет или восстанавливает контакт с кнопкой, кнопку со стрелкой нужно перерисовывать в соответствии с принятым стилем.

  • Начав ввод с ключевого слова override, переопределите в классе ArrowButton унаследованный метод OnMouseCaptureChanged() для повторения отрисовки кнопки в стиле со стрелкой и заполните его следующим кодом
// Повторяем отрисовку при потере или восстановлении контакта с мышью
        protected override void OnMouseCaptureChanged(EventArgs e)
        {
            base.OnMouseCaptureChanged(e);
    
            this.Invalidate();  // Инициировать перерисовку
        }
Листинг 19.16. Инициировать перерисовку при взаимодействии с мышью