| Стоит Windows 8 Pro, Visual Studio 2010 Express Edition . |
Работа с таймерами MFC
Обработка события срабатывания таймера
-
Добавьте к элементу управления IDC_STATICTIME, который сейчас имеет значение "Текущее время", переменную типа CString и назовите ее m_curTime. Для этого выделите элемент в дизайнере диалогового окна или через раскрывающийся список панели Properties. Затем через контекстное меню этого элемента или через меню оболочки Project вызовите мастер Add Variable...Мастер добавит переменную в объявление класса и в функцию обмена данными
Изменения в объявлении класса CTimersDlg файла TimersDlg.h class CTimersDlg : public CDialog { ............................................ public: // Переменная значения поля текста элемента IDC_STATICTIME CString m_curTime; };Изменения в функции DoDataExchange() класса CTimersDlg файла TimersDlg.cpp void CTimersDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_STATICTIME, m_curTime); } -
Добавьте к объекту класса CTimersDlg функцию-обработчик сообщения WM_TIMER, генерируемого таймером. Для этого в панели Class View выделите класс CTimersDlg и в панели свойств Properties установите режим Messages. Найдите сообщение WM_TIMER и назначьте для него обработчик OnTimer()Обработчик OnTimer() класса CTimersDlg файла TimersDlg.cpp void CTimersDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default // Получить текущее время CTime curTime = CTime::GetCurrentTime(); // Отобразить текущее время в нужном формате m_curTime = curTime.Format("%H:%M:%S"); // Переслать значения из переменных приложения на экран UpdateData(FALSE); CDialog::OnTimer(nIDEvent); } -
Постройте приложение и убедитесь, что время появляется с задержкой в одну секунду после появления окна приложения. Исправьте это, добавив в функцию OnInitDialog() код посылки сообщения принудительного срабатывания таймера сразу после создания окна. Для этого примените API -функцию PostMessage(), которую разместите сразу после строки создания объекта таймераИзменения в функции OnInitDialog() класса CTimersDlg файла TimersDlg.cpp BOOL CTimersDlg::OnInitDialog() { ..................................... // TODO: Add extra initialization here // Запустить таймер часов SetTimer(ID_CLOCK_TIMER, 1000, NULL); PostMessage(WM_TIMER); return TRUE; // return TRUE unless you set the focus to a control } -
Постройте приложение и убедитесь, что при появлении окна время уже установлено без задержки.
Извлечение текущей даты
Класс CTime библиотеки ATL имеет много функциональных возможностей для работы с временем и датой. Некоторые функции, связанные с нашей задачей, приведены в таблице.
| Коды форматов времени и даты класса CTime | |
|---|---|
| Функция | Описание |
| %a | Сокращенное название дня недели |
| %A | Полное название дня недели |
| %b | Сокращенное название месяца |
| %B | Полное название месяца |
| %c | Стандартный формат даты и времени для данной местности (определяется параметрами, задаваемыми с помощью панели управления) |
| %d | День месяца |
| %D | Целое количество дней |
| %H | Время в 24-часовом формате |
| %I | Время в 12-часовом формате |
| %j | День года |
| %m | Порядковый номер месяца |
| %M | Минуты |
| %p | Индикатор AM/PM |
| %S | Секунды |
| %U | Порядковый номер недели в году (первым днем недели считается воскресенье) |
| %w | Порядковый номер дня недели |
| %W | Порядковый номер недели в году (первым днем недели считается понедельник) |
| %x | Дата в стандартном формате для данной местности |
| %X | Время в стандартном формате для данной местности |
| %y | Две последние цифры года (двузначное число) |
| %Y | Год полностью (четырехзначное число) |
| %z, %Z | Сокращенное или полное название часового пояса |
| %% | Знак процента |
Мы создали экземпляр curTime класса CTime как локальную переменную в функции - обработчике OnTimer(), который виден только внутри этой функции. Нам нужно вывести дату в диалоговую панель приложения только один раз при запуске приложения. Поэтому перенесем создание объекта curTime в описание класса CTimersDlg, чтобы он был виден во всех функциях этого класса, в том числе в функции OnInitDialog(), которая сработает один раз и выведет нам текущую дату.
-
Измените обработчик OnTimer(), убрав из него создание объекта curTimeИзменения в обработчике OnTimer() файла TimersDlg.cpp void CTimersDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default // Получить текущее время // CTime curTime = CTime::GetCurrentTime(); curTime = CTime::GetCurrentTime(); // Отобразить текущее время в нужном формате m_curTime = curTime.Format("%H:%M:%S - %m"); // Переслать значения из переменных приложения на экран UpdateData(FALSE); CDialog::OnTimer(nIDEvent); } -
Добавьте объявление переменной curTime в объявление класса CTimersDlg файла TimersDlg.h (выполните это без применения мастера - вручную!)Изменения в файлe TimersDlg.h class CTimersDlg : public CDialog { ................................ private: // Переменная-объект таймера CTime curTime; };
Добавим в функцию OnInitDialog() код извлечения текущей даты. Для этого создадим переменную m_strDate, ассоциированную с ресурсом IDC_STATICDATE:
-
Перейдите в дизайнер форм и выделите форму -
В раскрывающемся списке панели Properties выделите ресурс IDC_STATICDATE
-
Через меню Project/Add Variableвызовите мастер добавления переменных и настройте его так
Мастер внесет такие изменения в программу:
Изменения в файлe TimersDlg.h
class CTimersDlg : public CDialog
{
................................
private:
// Переменная-объект таймера
CTime curTime;
// Переменная для отображения текущей даты
CString m_strDate;
};Изменения в файлe TimersDlg.cpp
CTimersDlg::CTimersDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTimersDlg::IDD, pParent)
, m_curTime(_T(""))
, m_strDate(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CTimersDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_STATICTIME, m_curTime);
DDX_Text(pDX, IDC_STATICDATE, m_strDate);
}Поскольку код извлечения даты предполагается относительно большой, упакуем его в отдельную функцию. Добавьте в класс CTimersDlg функцию-член извлечения текущей даты. Для этого:
-
В панели Class View выделите класс CTimersDlg и через контекстное меню Add/Add Function вызовите мастер добавления функций. Настройте его так, как приведено на рисункеМастер добавит код в два файла
Добавления в файлe TimersDlg.h class CTimersDlg : public CDialog { ............................................ private: // Переменная-объект таймера CTime curTime; // Переменная для отображения текущей даты CString m_strDate; // Извлечение текущей даты CString GetCurDate(void); };Добавления в файлe TimersDlg.cpp // Извлечение текущей даты CString CTimersDlg::GetCurDate(void) { return CString(); } -
Наполните функцию GetCurDate() кодом извлечения датыФункция GetCurDate() файла TimersDlg.cpp // Извлечение текущей даты CString CTimersDlg::GetCurDate(void) { // массив месяцев char *month[] = {"января" ,"февраля" ,"марта" ,"апреля" ,"мая" ,"июня" ,"июля" ,"августа" ,"сентября" ,"октября" ,"ноября" ,"декабря"}; // массив дней недели char *week[] = { "воскресенье" ,"понедельник" ,"вторник" ,"среда" ,"четверг" ,"пятница" ,"суббота" }; CString str; // Инициализируется пустой строкой при создании int m_day, m_month, m_week, m_year; m_day = curTime.GetDay(); // Число месяца m_month = curTime.GetMonth(); // 1 - Январь m_week = curTime.GetDayOfWeek(); // 1 - Воскресенье m_year = curTime.GetYear(); // Год char tmp[5]; // Для размещения числа месяца, года и нуль-символа itoa(m_day, tmp, 10);// Преобразуем целое в строку в десятичном формате str += tmp; str += " "; str += month[m_month - 1]; str += " ("; str += week[m_week - 1]; str += ") - "; itoa(m_year, tmp, 10); // Преобразуем число-год в строку-год str += tmp; str += " г."; return str; } -
Разместите в функции OnInitDialog() вызов нашей функции извлечения датыДобавление кода в функцию OnInitDialog() файла TimersDlg.cpp BOOL CTimersDlg::OnInitDialog() { .................................................... // TODO: Add extra initialization here // Запустить таймер часов SetTimer(ID_CLOCK_TIMER, 1000, NULL); curTime = CTime::GetCurrentTime(); // Заполнить объект таймера m_strDate = GetCurDate(); // Наша функция извлечения даты PostMessage(WM_TIMER); // Исполнить функцию-обработчик OnTimer() return TRUE; // return TRUE unless you set the focus to a control } -
Постройте приложение и убедитесь в работоспособности кода
Результат должен выглядеть приблизительно так:





