Опубликован: 17.08.2010 | Доступ: свободный | Студентов: 999 / 59 | Оценка: 4.11 / 3.89 | Длительность: 29:38:00
Самостоятельная работа 5:

Работа с таймерами 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
Функция Описание
GetYear Возвращает год (в int )
GetMonth Возвращает месяц (в int )
GetDay Возвращает день месяца (в int )
GetHour Возвращает часы (в int )
GetMinute Возвращает минуты (в int )
GetSecond Возвращает секунды (в int )
GetDayOfWeek Возвращает день недели (1 - воскресенье, ..., 7 - суббота) (в int )
Format Возвращает местное время в формате, определяемом строкой форматирования. Строка форматирования передается данной функции в качестве параметра (в CString ). Коды форматов даты и времени приведены ниже.
FormatGmt Возвращает среднее время по Гринвичу ( GMT ) в формате, определяемом строкой форматирования. Строка форматирования передается данной функции в качестве параметра (в CString ). Коды форматов даты и времени приведены ниже.
Коды форматов времени и даты класса 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
    }
  • Постройте приложение и убедитесь в работоспособности кода

Результат должен выглядеть приблизительно так:


Александр Даниленко
Александр Даниленко
Стоит Windows 8 Pro, Visual Studio 2010 Express Edition .