Опубликован: 13.07.2010 | Доступ: свободный | Студентов: 890 / 20 | Оценка: 4.40 / 4.20 | Длительность: 77:34:00    
    
                Тема: Программирование    
    
                Специальности: Программист, Архитектор программного обеспечения    
            
                  
        
        Самостоятельная работа 24: 
                  
          Пользовательские компоненты
Тестирование компонента AlarmClock
- 
 Поместите
    новый компонент AlarmClock  из панели Toolbox  на
    форму Form1     приложения ComponentTest,
    выделите его экземпляр alarmClock1  и через
    панель Properties  в режиме Events  создайте обработчик для
    события Alarm Поместите
    новый компонент AlarmClock  из панели Toolbox  на
    форму Form1     приложения ComponentTest,
    выделите его экземпляр alarmClock1  и через
    панель Properties  в режиме Events  создайте обработчик для
    события Alarm
- 
 Обработчик,
    добавленный в класс Form1  приложения ComponentTest,
     заполните следующим кодом Обработчик,
    добавленный в класс Form1  приложения ComponentTest,
     заполните следующим кодом
private void alarmClock1_Alarm(object sender, AlarmClock.AlarmEventArgs e)
        {
            // Если оператор выключения будильника поставить после
            // вызова модального диалогового окна, то генерация
            // событий прекратиться только после закрытия
            // очередного модального окна, поскольку только тогда
            // управление дойдет до этого оператора
            alarmClock1.Enabled = false;// Останавливаем системный таймер
    
            int hour = alarmClock1.CurrentTime.Hour;
            int minute = alarmClock1.CurrentTime.Minute;
            int second = alarmClock1.CurrentTime.Second;
            MessageBox.Show(String.Format("Сработал будильник!!!\n"
                + "Текущее время: {0} ч. {1} м. {2} с.", hour, minute, second),
                "Доцент Снетков В.М.");
        }
                            Листинг
                        24.15.
                        Обработчик события Alarm в тестирующем классе Form1    
- 
 Добавьте
    в конец конструктора формы Form1  код установки времени срабатывания
    будильника и запуска системного таймера Добавьте
    в конец конструктора формы Form1  код установки времени срабатывания
    будильника и запуска системного таймера
// Конструктор формы
        public Form1()
        {
            InitializeComponent();
    
            // Заполнение списка планетами
            for (int i = 0; i <= planets1.MaxIndex; i++)
            {
                listPlanets.Items.Add(String.Format(
                    "{0}) {1}", i, planets1[i]));
            }
    
            listPlanets.SelectedIndex = 0;
    
            // Устанавливаем время срабатывания будильника 
            // через 5 сек. после запуска системного таймера
            alarmClock1.AlarmTime = DateTime.Now.AddSeconds(5d);
            alarmClock1.Enabled = true;// Запускаем системный таймер
        }
                            Листинг
                        24.16.
                        Конструктор формы Form1 файла Form1.cs приложения ComponentTest  
- 
 Запустите
    приложение и убедитесь, что обработчик нашего события Alarm     срабатывает
    через 5 секунд после запуска системного таймера, генерируя
    окно с примерно следующим сообщением Запустите
    приложение и убедитесь, что обработчик нашего события Alarm     срабатывает
    через 5 секунд после запуска системного таймера, генерируя
    окно с примерно следующим сообщением
Добавление в компонент пользовательского события расширенным способом
Рассмотрим другой способ работы с событиями, использующий базовое поле типа делегата. Для этого модифицируем наш компонент таким образом, чтобы будильник срабатывал два раза: по первому и второму событию. Но второе событие определим по иному.
- 
 Перейдите
    в режим редактирования компонента AlarmClock.cs [Design]  и
    добавьте из панели Toolbox  двойным щелчком
    кнопки мыши еще один системный таймер Timer Перейдите
    в режим редактирования компонента AlarmClock.cs [Design]  и
    добавьте из панели Toolbox  двойным щелчком
    кнопки мыши еще один системный таймер Timer
- 
 Выделите
    экземпляр таймера timer2  и в панели Properties     установите свойство Interval=1000 Выделите
    экземпляр таймера timer2  и в панели Properties     установите свойство Interval=1000
- 
 Создайте
    для объекта timer2  обработчик события Tick     с
    именем TimerHandlerExt,
    который переместите в отдельную часть класса AlarmClock  в
    файле AlarmClock.cs. Заполните эту часть
    следующим кодом Создайте
    для объекта timer2  обработчик события Tick     с
    именем TimerHandlerExt,
    который переместите в отдельную часть класса AlarmClock  в
    файле AlarmClock.cs. Заполните эту часть
    следующим кодом
// Часть 5
namespace MyCompany.MyComponents
{
    // Часть класса с определением обработчика события Tick 
    // системного таймера System.Windows.Forms.Timer timer2
    partial class AlarmClock
    {
        // Объявляем внутренние поля
        bool alarmFiredExt = false; // Состояние будильника (запущен/незапущен)
        DateTime alarmTimeExt = DateTime.Now; // Хранит время запуска будильника
    
        // Свойство для чтения и установки времени запуска будильника
        public DateTime AlarmTimeExt
        {
            get { return alarmTimeExt; }
            set
            {
                if (value != alarmTimeExt)
                {
                    alarmTimeExt = value;
                    alarmFiredExt = false;
                }
            }
        }
    
        // Свойство для проверки состояния хода второго
        // системного таймера, его остановки и запуска
        public bool EnabledExt
        {
            get { return timer2.Enabled; }
            set
            {
                timer2.Enabled = value;
                if (value)
                    alarmFiredExt = false;
            }
        }
        
        // Обработчик события срабатывания второго системного таймера
        private void TimerHandlerExt(object sender, EventArgs e)
        {
            DateTime now; // Текущее системное время
            AlarmEventArgs args;
    
            // В режиме разработки не выполнять
            if (!this.DesignMode)
            {
                now = DateTime.Now;
                // Если будильник не запущен и пришла пора запускать
                if (!alarmFiredExt && now >= alarmTimeExt)
                {
                    // Создаем объект для передачи аргументов в событии
                    args = new AlarmEventArgs();
                    // Заполняем объект текущим временем
                    args.Time = now;
                    // Вызываем метод диспетчеризации события AlarmExt
                    this.OnAlarmExt(args);
    
                    // Поднимаем флаг "Будильник запущен"
                    alarmFiredExt = true;
                }
            }
        }
    }
}
                            Листинг
                        24.17.
                       Часть класса с обработчиком таймера   timer2 в файле AlarmClock.cs
- 
 Создайте
    часть класса компонента, объявляющего пользовательское событие
    на базе внутреннего поля-ссылки на экземпляр делегата, который
    будет содержать список зарегистрированных обработчиков этого
    события Создайте
    часть класса компонента, объявляющего пользовательское событие
    на базе внутреннего поля-ссылки на экземпляр делегата, который
    будет содержать список зарегистрированных обработчиков этого
    события
// Часть 6 Extension
namespace MyCompany.MyComponents
{
    // Часть класса с определением собственного события
    // стандартным способом без использования базового поля
    partial class AlarmClock
    {
        // Закрытое поле-ссылка на экземпляр делегата
        // Для объявления поля решили использовать уже существующий 
        // делегат, но можно объявить и другой делегат с той же сигнатурой
        private AlarmHandler m_AlarmExt;
    
        // Объявляем пользовательское событие
        // с возможностью контроля доступа к нему
        public event AlarmHandler AlarmExt
        {
            // Эта функция будет вызвана при  попытке 
            // добавления обработчика в список вызова события
            add
            {
                // Здесь что-то можно проконтролировать, например, что
                // произошла попытка добавить обработчик в список вызова события
                Console.WriteLine("Добавлен обработчик в список события AlarmExt");
    
                // Расширяем список объекта-делегата, ссылающегося на обработчики события
                m_AlarmExt += value;
            }
            // Эта функция будет вызвана при попытке 
            // изъятия обработчика из списка вызова события
            remove
            {
                // Здесь что-то можно проконтролировать, например, что
                // произошла попытка изъять обработчик из списка вызова события
                Console.WriteLine("Изъят обработчик из списка события AlarmExt");
    
                // Удалим обработчик из списка объекта-делегата
                m_AlarmExt -= value;
            }
        }
    
        // Метод диспетчеризации события. Виртуальный и защищенный
        // для возможности переопределения в будущих потомках
        protected virtual void OnAlarmExt(AlarmEventArgs args)
        {
            // Проверяем наличие зарегистрированных обработчиков 
            // и генерируем событие через поле-делегат
            if (m_AlarmExt != null)
                m_AlarmExt(this, args);
        }
    }
}
                            Листинг
                        24.18.
                        Часть файла AlarmClock.cs объявления события с контролем списка делегата    
- 
 Откомпилируйте
      библиотеку наших компонентов, выполнив команду Build/Build
      MyComponents Откомпилируйте
      библиотеку наших компонентов, выполнив команду Build/Build
      MyComponents
- 
 Перейдите
    в файл Form1.cs [Design]  и добавьте
    в конструктор класса тестового приложения код настройки второго
    системного таймера экземпляра компонента alarmClock1 Перейдите
    в файл Form1.cs [Design]  и добавьте
    в конструктор класса тестового приложения код настройки второго
    системного таймера экземпляра компонента alarmClock1
// Конструктор формы
        public Form1()
        {
            InitializeComponent();
    
            // Заполнение списка планетами
            for (int i = 0; i <= planets1.MaxIndex; i++)
            {
                listPlanets.Items.Add(String.Format(
                    "{0}) {1}", i, planets1[i]));
            }
    
            listPlanets.SelectedIndex = 0;
    
            // Устанавливаем время срабатывания будильника 
            // через 5 сек. после запуска системного таймера
            alarmClock1.AlarmTime = DateTime.Now.AddSeconds(5d);
            alarmClock1.Enabled = true;// Запускаем системный таймер
    
            // Настраиваем второй системный таймер компонента
            alarmClock1.AlarmTimeExt = DateTime.Now.AddSeconds(10d);
            alarmClock1.EnabledExt = true;// Запускаем системный таймер
        }
                            Листинг
                        24.19.
                       Конструктор формы Form1 файла Form1.cs приложения   ComponentTest 
- 
 На
    форме Form1  приложения ComponentTest  
    выделите  экземпляр alarmClock1  и через
    панель Properties  в режиме Events  создайте
    обработчик для события AlarmExt На
    форме Form1  приложения ComponentTest  
    выделите  экземпляр alarmClock1  и через
    панель Properties  в режиме Events  создайте
    обработчик для события AlarmExt
- 
 Обработчик
     заполните следующим кодом Обработчик
     заполните следующим кодом
private void alarmClock1_AlarmExt(object sender, AlarmClock.AlarmEventArgs e)
        {
            alarmClock1.EnabledExt = false;// Останавливаем второй системный таймер
    
            int hour = alarmClock1.CurrentTime.Hour;
            int minute = alarmClock1.CurrentTime.Minute;
            int second = alarmClock1.CurrentTime.Second;
            MessageBox.Show(String.Format("Сработал будильник!!!\n"
                + "Текущее время: {0} ч. {1} м. {2} с.", hour, minute, second),
                "Доцент Снетков В.М.");
    
            // Для генерации сообщения в консольный вывод
            alarmClock1.AlarmExt -= alarmClock1_AlarmExt;
        }
                            Листинг
                        24.20.
                       Обработчик события AlarmExt в тестирующем классе Form1 
- 
 В панели Solution Explorer  вызовите контекстное меню
    для узла приложения ComponentTest  и выполните команду Properties В панели Solution Explorer  вызовите контекстное меню
    для узла приложения ComponentTest  и выполните команду Properties
- 
 В появившемся
    окне настроек оболочки выберите вкладку Application  и  в
    раскрывающемся списке Output type  включите окно консольного
    вывода Console Application В появившемся
    окне настроек оболочки выберите вкладку Application  и  в
    раскрывающемся списке Output type  включите окно консольного
    вывода Console Application
- 
 Запустите
    приложение и убедитесь, что оба способа определения пользовательского
    события работают одинаково, но в последнем способе мы можем
    контролировать процесс добавления обработчиков Запустите
    приложение и убедитесь, что оба способа определения пользовательского
    события работают одинаково, но в последнем способе мы можем
    контролировать процесс добавления обработчиков
 
                             

