Таймер. Создание таймера. Пример использования таймера. Тестирование работы таймера, страница 2

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

Код, включённый в класс CTimerDlg, имеет вид:

class CTimerDlg : public CDialog

{

public :

     int m_count1 ;                             // переменная, ассоциированная с текстовым полем IDC_COUNT1

     int m_count2 ;                             // переменная, ассоциированная с текстовым полем IDC_COUNT2

     CString m_time ;                              // переменная, ассоциированная с текстовым полем IDC_TIME

     int m_elapse1 ;                             // время срабатывания первого таймера

     int m_elapse2 ;                             // время срабатывания второго таймера

};

// функция обработки инициализации диалогового окна

BOOL CTimerDlg :: OnInitDialog ( )

{

     CDialog :: OnInitDialog ( ) ;

     • • •

     SetDlgItemInt ( IDC_ELAPSE1 , 100 ) ;   

     SetDlgItemInt ( IDC_ELAPSE2 , 1000) ;   // определяет значения текстовых полей по умолчанию SetTimer ( 3 , 1000 , NULL ) ;                              // создаёт третий системный таймер

     return TRUE ;

}

// функция обработки щелчка на кнопке IDC_ON ("Включить")

void CTimerDlg :: OnOn ( )

{

     m_elapse1 = GetDlgItemInt ( IDC_ELAPSE1 ) ;

     m_elapse2 = GetDlgItemInt ( IDC_ELAPSE2 ) ;

     // считывает данные из текстовых полей IDC_ELAPSE1 IDC_ELAPSE2

     // в переменные m_elapse1 и m_elapse2

     SetTimer ( 1 , m_elapse1 , NULL ) ;      // создаёт первый системный таймер

     SetTimer ( 2 , m_elapse2 , NULL ) ;      // создаёт второй системный таймер

}

// функция обработки щелчка на кнопке IDC_OFF ("Выключить")

void CTimerDlg :: OnOff ( )

{

     KillTimer ( 1 ) ;                      // останавливает первый системный таймер

     KillTimer ( 2 ) ;                      // останавливает второй системный таймер

}

// функция обработки щелчка на кнопке IDC_OFF ("Выключить")

void CTimerDlg :: OnTimer ( UINT nIDEvent )

{

     CTime curTime = CTime::GetCurrentTime ( ) ;

     // создаёт переменную типа CTime и инициализирует её текущим системным временем

     switch ( nIDEvent )

     {

     case 1:    m_count1++;        break;                                                        // наращивает первый счётчик

     case 2:    m_count2 += m_elapse2 / m_elapse1 ;   break ;                      // наращивает второй счётчик

     case 3:    m_time = curTime.Format ("%d-%m-%y  %H:%M:%S") ;

                                           // формирует строку с текущим системным временем

     }

     UpdateData ( false ) ;                   // считывает данные

                                                         // из ассоциированных переменных m_count1, m_count2 и m_time

                                                         // текстовые поля IDC_COUNT1, IDC_COUNT2 и IDC_TIME

     CDialog :: OnTimer ( nIDEvent ) ;

}

// функция обработки закрытия диалогового окна

void CTimerDlg :: OnClose ( )

{

     KillTimer ( 3 ) ;                      // останавливает третий системный таймер

     CDialog :: OnClose ( ) ;

}

Тестирование работы таймера

Вид диалогового окна после 100 секунд работы показан на рисунке. Нетрудно видеть, что значения счётчиков лишь приблизительно соответствуют системному времени.

Если мы уменьшим интервал срабатывания таймеров, то разница будет ещё больше. Несмотря на то, что время срабатывания первого таймера установлено равным 1 мс, его реальное значение составило 16 мс.

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