Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

VC Лекции PDF / VC 14 Лек Таймер

.pdf
Скачиваний:
36
Добавлен:
15.02.2015
Размер:
214.09 Кб
Скачать

Лекция 14

Таймер

1

 

Л Е К Ц И Я

1 4

ТАЙМЕР ________________________________________________________________________________ 1

Создание таймера ______________________________________________________________________ 1 Остановка таймера _____________________________________________________________________ 1 Пример использования таймера___________________________________________________________ 2 Тестирование работы таймера____________________________________________________________ 3

ТАЙМЕР

Создание таймера

Для создания системного таймера оконный класс может использовать функцию-член SetTimer ( ) класса CWnd со следующим прототипом:

UINT SetTimer ( UINT nIDEvent , UINT nElapse ,

void ( CALLBACK EXPORT* lpfnTimer ) (HWND , UINT , UINT , DWORD )) ;

Эта функция возвращает идентификатор таймера, если она выполнена успешно, и ноль противном случае. Параметры:

nIDEvent

идентификатор таймера;

nElapse

задает время срабатывания таймера в миллисекундах;

lpfnTimer

указатель на callback-функцию, которая обрабатывает сообщения WM_TIMER. Если

 

этот параметр равен NULL, сообщения WM_TIMER помещаются в очередь сообще-

 

ний приложения и обрабатываются оконным объектом.

По истечении времени в nElapse миллисекунд после установки таймера или предыдущего его срабатывания система посылает сообщение WM_TIMER в очередь приложения или передает его для обработки функции, на которую указывает параметр IpfnTimer. Прототип функции, на которую ссылается этот указатель, должен быть следующим:

void CALLBACK EXPORT

TimerProc ( HWND hWnd , UINT nMsg , UINT nIDEvent , DWORD dwTime ) ;

Здесь

 

hWnd

дескриптор оконного объекта, который вызвал функцию SetTimer ( ),

nMsg

идентификатор сообщения WM_TIMER,

nIDEvent

идентификатор таймера;

dwTime

системное время.

Имя этой функции не обязательно должно быть TimerProc, однако она должна возвращать 0.

Остановка таймера

Остановить установленный таймер можно с помощью функции-члена того же класса KillTimer ( ) со следующим прототипом:

BOOL KillTimer ( int nIDEvent ) ;

В качестве параметра nIDEvent этой функции передается идентификатор таймера. Функция возвращает TRUE, если таймер остановлен, и FALSE – если нет.

При размещении указанных функций в программе следует иметь в виду, что эти функции в конечном итоге вызывают функции Windows, каким передается в качестве параметра дескриптор окна, с которым связывается таймер. Это означает, что установка таймера не может быть произведена раньше, чем будет создано окно. Наиболее ранней в смысле выполнения программы точкой для установки таймера является обработчик события OnNcCreate ( ). Уничтожение таймера также должно производиться, когда окно еще существует. Последней возможностью для вас в этом смысле является обработчик события OnNcDestroy ( ) (но до вызова обработчика базового класса). Мы рекомендуем вам всегда делать это несколько раньше – в обработчике события OnClose ( ) или OnDestroy ( ).

Обработчик событий таймера называется OnTimer ( ) и имеет прототип: afx_msg void OnTimer (UINT nIDEvent ) ;

Его единственный параметр nIDEvent задает идентификатор таймера. Эта функция вызывается операционной системой, чтобы позволить вашему приложению обработать сообщение Windows WM_TIMER. Параметр, передаваемый функции, отражает значение. которое он имел в момент получения его функцией окна приложения. Если вы вызовете в этом обработчике обработчик базового класса,

Выжол Ю.А.

Программирование на Visual C++

Лекция 14

Таймер

2

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

Пример использования таймера

Рассмотрим пример, который не только демонстрирует основные приёмы использования таймера, но и позволяет тестировать его работу. Диалоговое окно IDD_TIMER_DIALOG содержит три таймера. Первый и второй таймер создаются после щелчка на кнопке “Включить”. Время срабатывания каждого таймера пользователь может установить в соответствующих текстовых полях. Каждый таймер увеличивает значение соответствующего счётчика, которые также отображаются в текстовых полях. Второй таймер срабатывает реже, но увеличивает значение своего счётчика на большее значение. В среднем значения обоих счётчиков должны быть равны. Оба таймера останавливаются при щелчке на кнопке “Выключить”.

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

Код, включённый в класс 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") ;

Выжол Ю.А.

 

 

Программирование на Visual C++

Лекция 14

Таймер

3

}

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

 

 

 

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 в очередь приложения и эта очередь не может продвигаться быстрее, чем происходит опрос внешних устройств.

Выжол Ю.А.

Программирование на Visual C++