Назад | Начало урока | Вперед
Содержание

День 5

Работа с таймерами

Сегодня вы научитесь:

Вверх
Функционирование таймеров Windows

Таймеры в операционной системе Windows представляют собой механизмы, с помощью которых можно инициировать выполнение одного или нескольких действий через заданное количество миллисекунд. Таймер можно установить так, чтобы срабатывал с интервалом 1000 миллисекунд, то есть практически каждую секунду. Когда таймер срабатывает, приложению отсылается сообщение WM_TIMER. Можно добавить в приложение функцию, которая будет обрабатывать данное сообщение.

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

АВ: То есть у таймера есть такое свойство как Интервал и есть еще свойство отсылать сообщение (WM_TIMER) каждый раз по прошествии этого интервала. То есть таймер напоминает мигающий маяк, поскольку сообщения отсылаются через определенный промежуток времени называемый - Интервал. Величина Интервала проверяется по системным часам.Программист может устанавливать программно или интерактивно величину интервала. Программа может так же перехватывать и обрабатывать сообщение таймера - WM_TIMER. То есть получение сообщений от таймера можно привязывать к запуску определенных функций, или программ. У таймера должен быть свой идентификатор, поскольку одновременно может в программе действовать несколько таймеров.

События таймера ставятся в очередь событий приложения лишь в том случае, если эта очередь пуста и приложение неактивно (простаивает). И наоборот событие таймера не ставится в очередь событий,если оно произошло в тот момент, когда приложение занято.Windows ставит в очередь событий только одно сообщение таймера. Все сообщения о событиях, которые произойдут тогда, когда приложение занято, будут проигнорированы. Независимо от количества проигнорированных сообщений Windows может поставить в очередь только одно сообщение от таймера.

Чтобы запустить или остановить таймер,вам необходимо указать идентификатор таймера(ID), который может принимать любое целое значение. Этот идентификатор используется приложением для запуска или остановки таймера, а так же для определения сработавшего таймера.


Вверх

Приложение с часами

В нашем приложении будут использованы два таймера. Первый таймер будет применяться для отображения часов в окне нашего приложения. Второй таймер будет срабатывать через интервал времени указанный пользователем в диалоговом окне. Пользователь может в любой момент запустить или остановить таймер.

Создание проекта.

  1. Создайте новый проект по типу как это вы делали ранее, назовите его Timers.
  2. Укажите что проект будет диалоговым на основе MFC.
  3. Создайте макет диалогового окна согласно картинке

    Подсказка

  4. Определите порядок перехода по клавише табуляции .
  5. Обеспечьте выход из приложения связав его с кнопкой Exit
  6. Задайте значения свойств элементов управления согласно таблице 5.1

Таблица 5.1

Static Text Caption Timer &Interval
Edit Box ID IDC_EINTERVAL
Button ID
Caption
IDC_BSTARTTIME
&Start Time
Button ID
Caption
Disabled
IDC_BSTOPTIMER
S&top Timer
TRUE
Static Text Caption Time
Static Text ID
Caption
IDC_STATICTIME
Current Time
Static Text Caption Count
Static Text ID
Caption
IDC_STATICCOUNT
0
Button ID
Caption
IDC_EXIT
E&xit

АВ: В тех элементах управления называемых Static Text в которых будут содержаться определенные значения, в них определяем их идентификатор(ID). В таких элементах надпись будет меняться динамически в процессе выполнения программы.(Например часы будут показывать текущее время,таймер может показывать количество прошедших интервалов). К элементу Static Text можно добавлять переменную, которую затем можно будет инициализировать и затем показывать через элемент Static Text. В других элементах Static Text, с которыми в процессе работы программы не будет ни какого взаимодействия, определяем только их заголовок (Caption). Это просто надпись и все. В процессе работы программы она не меняется.

Вверх

Добавление идентификаторов таймеров
В данном приложении будут использоваться два таймера. Чтобы однозначно определить таймер,ему следует присвоить уникальный идентификатор. Добавьте в приложение идентификаторы используемых таймеров.

  1. Щелкните правой кнопкой на папке Timers.rc во вкладке Resourse View. Выберите пункт Resourse Sombols.
  2. В диалоговом окне Resourse Sombols щелкните на New
  3. В диалоговом окне New Simbol в качестве имени символа введите ID_CLOCK_TIMER,а в поле value в качестве значения - 1.Чтобы добавить новый символ ресурса в проект щелкните на OK.
  4. Повторите предыдущие шаги и в поле simbol укажите имя ID_COUNT_TIMER в качестве имени а в поле value - 2 в качестве значения.
  5. Закройте окно Resourse Sombols щелкнув на Close.
Теперь в приложении можно использовать идентификаторы обоих таймеров.

АВ:Поскольку такой элемент как таймер не изображен непосредственно на форме и мы не можем его посадить на форму а затем выделить этот элемент на форме, как это было с другими управляющими элементами. То мы выбираем в ресурсах Мастера и объявляем новый элемент Таймер, придаем ему его идентификатор и кроме этого значение 1, для первого таймера. Затем делаем все то же самое: объяввляем для второго таймера его идентификатор и присваиваем этому таймеру значение 2. Теперь мастер создания приложений знает что у нас создано два таймера. Каждый таймер имеет свой идентификатор. Кроме того с каждым таймером будет ассоциирована своя переменная, чтобы через эту переменную выводить значения таймера на экран.
Вверх
Запуск таймера часов
Чтобы запустить таймер часов,отредактируйте функцию OnInitDialog Воспользуйтесь знаниями полученными в предыдущих главах и измените тело функции в соответствии с листингом 5.1

Листинг 5.1


BOOL CTimerDlg::OnInitDialog
{
CDialog::OnInitDialog();

//Добавить пункт меню
//"About ..." (О программе к системному меню
//IDM_ABOUTBOX должен быть в области системных команд

ASSERT(IDB_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDB_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSistemMenu(FALSE);//
if(pSysMenu != NULL) //пустой указатель
{

CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
//установить значек для этого диалога Каркас делает это автоматически
//если основное окно приложения не диалог

SetIcon(m_hIcon, TRUE);//установить большой значек
SetIcon(m_hIcon, FALSE);//установить маленький значек

//запустить таймер часов

SetTimer(ID_CLOCK_TIMER, 1000, NULL);

return TRUE;

}


Как видим здесь в функцию нам надо добавить всего одну строку кода:

SetTimer(ID_CLOCK_TIMER, 1000, NULL);

остальное все сделал мастер.

Из листинга видно, что запускает таймер часов функция SetTimer()

SetTimer(ID_CLOCK_TIMER, 1000, NULL);

В качестве первого аргумента функции SetTimer передается идентификатор таймера.

Второй аргумент определяет частоту, с которой будет запускаться событие таймера.В данном случае событие таймера запускается каждые 1000 миллисекунд, или раз в секунду.

Третьим необязательным аргументом является адрес функции обратного вызова. Функция обратного вызова предназначена для обработки событыя таймера. Если передать функции SetTimer в качестве третьего аргумента NULL(пустой указатель), тогда сообщение WM_TIMER будет отослано в очередь сообщений приложения.

Вот как эта функция объявлена в классе CWnd

// Timer Functions
UINT SetTimer(UINT nIDEvent, UINT nElapse,

void (CALLBACK* lpfnTimer)(HWND, UINT, UINT, DWORD));
BOOL KillTimer(int nIDEvent);


Функция обратного вызова -это созданная разработчиком приложения функция, которая вызывается непосредственно операционной системой Windows. Если функция определена правильно то в нее может быть добавлен любой программный код.
Вызов этой функции организован так : Ее адрес передается функции Windows в качестве аргумента.Теперь.когда операционная система знает адрес этой функции, она вызывает ее непосредственно каждый раз, когда определит что произошло событие, для обработки которого операционная система должна вызывать функцию обратного вызова.

АВ: То есть вот оно:таймер срабатывает и функция вызывается! Поскольку в нашем конкретном случае в качестве третьего аргумента передано значение NULL то в очередь сообщений операционной системы Windows передается сообщение о срабатывании таймера.

Вверх

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

  1. Добавьте к элементу управления IDC_STATICTIME переменную типа CString и назовите ее m_sTime.
  2. Добавьте к объекту типа CTimersDlg функцию которая будет обрабатывать сообщения WM_TIMER.
  3. Измените тело функции OnTimer, добавив код, приведенный в листинге 5.2

Листинг 5.2 Функция OnTimer


void CTimersDlg::OnTimer(UINT nIDEvent)
{

//получить текущее время

CTime curTime = CTime::GetCurrentTime();

//поместить текущее время в переменную в соответствующем формате

m_sTime = curTime.Format("%H:%M:%S");

UpdateData(FALSE);

CDialog::OnTimer(nIDEvent);

}

Эта функция OnTimer в данном случае нами переопределяется.
А вот как она объявлена в классе CWnd

afx_msg void OnTimer(UINT nIDEvent);

Этой функции передается в аргумент идентификатор таймера, и эта функция будет вызываться системой всякий раз, когда наступит событие таймера. А событие (сигнал от таймера) будет наступать всякий раз по прошесвию интервала, который мы указали в функции SetTimer при установке таймера.

В листинге 5.2 декларируется экземпляр класса CTime и его значение инициализируется текущим системным значением.

CTime curTime = CTime::GetCurrentTime();

Затем вызывается метод Format() объекта curTime класса CTime. Этот метод преобразует полученное в предыдущей строке системное время в общепринятый стандарт. Текущее время записывается в строке m_sTime.Для преобразования текущего времени в общепринятый формат используется метод Format.

m_sTime = curTime.Format("%H:%M:%S");

После этого диалоговое окно обновляется текущим временем. UpdateData(FALSE);

Скомпилируйте и запустите приложение.В центре диалогового окна появятся часы.-они будут отображать текущее время.


АВ: Итак здесь функция OnTimer привязана к событию таймера WM_TIMER. То есть каждый раз когда таймер срабатывает, вызывается эта функция которая вызывает текущее время, преобразует его в удобный для восприятия формат и помещает это значение в управляющий элемент Static Text А событие таймера (срабатывание таймера) происходит как мы помним один раз в секунду.Следовательно каждую секунду отражается текущее время в элементе Static Text

Вверх

Библиотека MFC Класс CTime
Класс CTime охватывает многие функциональные возможности, необходимые при создании приложений, работающих с датой/временем.В классе CTime используется универсальное глобальное время(по Гринвичу).Это позволяет легко работать как с местным временем (определяется параметрами заданными при настройке компьютера), так и со средним временем по гринвичскому мередиану.

Вверх

Создание и инициализация даты и времени
При простом декларировании объекта CTime создается пустой объект. Он не может быть использован до тех пор, пока не будет инициализирован временем.Но есть несколько методов создания объекта данного класса. И в них объект инициализируется сразу после его создания.

В Листинге 5.2 приведен один из этих методов:

CTime curTime = CTime::GetCurrentTime();

Здесь для инициализации нового объекта текущим временем используется метод GetCurrentTime(), который возвращает объект CTime.

Другим методом создания и инициализиции объекта CTime является использование следующей версии конструктора :

CTime(int Year, int iMonth, int iDay, int iHour, int iMin, int iSec, int iDst);

Данный конструктор инициализирует объект значениями года, месяца, дня, часа, минут, секунд.Последний параметр (Daylight Saving Time) летнее время, указывает следует ли учитывать переход на летнее время и обратно. Если значение этого параметра 0. - тогда используется стандартное поясное время.Если значение больше 0, - учитывается переход на летнее время, Если значение меньше 0 (значение по умолчанию) то будет ли учитываться переход на летнее время зависит от значений параметров заданных при конфигурации компьютера.

Вверх

Извлечение даты и времени

После создания и инициализации объекта CTime необходимо извлечь из объекта значение даты и времени.Функции которые используются для этой цели перечислены ниже в таб.5.2

Таблица 5.2

GetYear Возвращает год
GetMonth Возвращает месяц
GetDay Возвращает день месяца
GetHour Возвращает часы
GetMinute Возвращает минуты
GetSecond Возвращает секунды
GetDayWeek Возвращает дни недели(1=воскресенье, 7=суббота)
Format Возвращает в CString местное время в формате определяемом строкой форматирования.Строка форматирования передается данной функции в качестве параметра.Коды форматов даты и времени приведены в таб 5.3
FormatGmt Возвращает в CString среднее время по Гринвичу в формате определяемом строкой форматирования.Строка форматирования передается данной функции в качестве параметра.Коды форматов даты и времени приведены в таб 5.3
%a Сокращенное название дня недели
%A Полное название дня недели
%b Сокращенное название месяца
%B Полное название месяца
%c Стандартный формат даты и времени для данной местности
(Определяется параметрами задаваемыми с помощью панели управления)
%d День месяца
%D Целое количество дней в CTime
%H Время в 24-часовом формате
%I Время в 12-часовом формате
%J День года
%m Порядковый номер месяца
%M Минуты
%p Индикатор AM/PM
%S Секунды
%U Порядковый номер недели в году;первым днем недели считается воскресенье
%w Порядковый номер дня недели
%W Порядковый номер недели в году;первым днем недели считается понедельник
%x Дата в стандартном формате для данной местности
%X Время в стандартном формате для данной местности
%y Две последние цифры года (двузначное число)
%Y Год полностью
%z %Z Полное или сокращенное название часового пояса
%% Знак процента

Назад | Вверх | Вперед
Содержание

Hosted by uCoz