Стоит 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 }
- Постройте приложение и убедитесь в работоспособности кода
Результат должен выглядеть приблизительно так: