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

Создание собственного элемента управления ActiveX

Отображение текущего времени

Заменим нашу текстовую заглушку на строку, содержащую текущую дату и время. Подобную информацию мы уже получали в Lab6, поэтому повторим эти шаги

  • Добавьте объявление двух переменных m_strDate и m_strTime в объявление класса CMyClockCtrl файла MyClockCtrl.h для хранения текущих даты и времени. Выполните это без применения мастера - вручную
    Изменение в файле MyClockCtrl.h
    class CMyClockCtrl : public COleControl
    {
    ............................................
    private:
      // Переменная-член текущей даты
      CString m_strDate;
      // Переменная-член текущего времени
      CString m_strTime;
    };
  • В панели Class View выделите класс CMyClockCtrl и через контекстное меню Add/Add Function вызовите мастер добавления функций. Настройте его так, как приведено на рисунке

  • Вновь в панели Class View выделите класс CMyClockCtrl и через контекстное меню Add/Add Function вызовите мастер добавления функций. Настройте его так, как приведено на рисунке

  • Заготовку функции GetCurDate() в файле MyClockCtrl.cpp наполните следующим кодом
    Функция GetCurDate() в файле MyClockCtrl.cpp
    // Заполняет переменную-член  m_strDate текущей датой
    void CMyClockCtrl::GetCurDate(void)
    {
      // массив месяцев
      char *month[] = {"января"
              ,"февраля"
              ,"марта"
              ,"апреля"
              ,"мая"
              ,"июня"
              ,"июля"
              ,"августа"
              ,"сентября"
              ,"октября"
              ,"ноября"
              ,"декабря"};
      // массив дней недели
      char *week[] = { "воскресенье" 
              ,"понедельник"
              ,"вторник"
              ,"среда"
              ,"четверг"
              ,"пятница"
              ,"суббота" };
      
      int m_day, m_month, m_week, m_year;
      
      // Получить текущее время
      CTime curTime = CTime::GetCurrentTime();
      
      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);// Преобразуем целое в строку в десятичном формате
      
      m_strDate = ""; // Заполнить пустой строкой
      m_strDate += tmp;
      m_strDate += " ";
      m_strDate += month[m_month - 1];
      m_strDate += " (";
      m_strDate += week[m_week - 1];
      m_strDate += ") - ";
      
      itoa(m_year, tmp, 10);  // Преобразуем число-год в строку-год
      m_strDate += tmp;
      m_strDate += " г.";
    }
  • Заготовку функции GetCurTime() в файле MyClockCtrl.cpp наполните следующим кодом
    Функция GetCurTime() в файле MyClockCtrl.cpp
    // Заполняет переменную m_strTime текущим временем
    void CMyClockCtrl::GetCurTime(void)
    {
      // Получить текущее время
      CTime curTime = CTime::GetCurrentTime();
      
      // Сохранить текущее время в нужном формате
      m_strTime = "  "; // Два пробела
      m_strTime += curTime.Format("%H:%M:%S");
    }
  • Добавьте объявление суммарной переменной m_str в объявление класса CMyClockCtrl файла MyClockCtrl.h для хранения текущих даты и времени. Выполните это без применения мастера - вручную
    Изменение в файле MyClockCtrl.h
    class CMyClockCtrl : public COleControl
    {
    ............................................
      // Переменная-член текущей даты
      CString m_strDate;
      // Переменная-член текущего времени
      CString m_strTime;
      // Заполняет переменную-член  m_strDate текущей датой
      void GetCurDate(void);
      // Заполняет переменную m_strTime текущим временем
      void GetCurTime(void);
      CString m_str;
    };
  • Отредактируйте функцию OnDraw() так, чтобы она выводила текущие дату и время
    Функция OnDraw() в файле MyClockCtrl.cpp
    void CMyClockCtrl::OnDraw(
          CDC* pdc, 
          const CRect& rcBounds, 
          const CRect& rcInvalid)
    {
      if (!pdc)
        return;
      
      // TODO: Replace the following code with your own drawing code.
      
      // Залить элемент управления
      pdc->FillRect(rcBounds, 
        CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
    //  pdc->Ellipse(rcBounds); // Построить эллипс
      
      // Получить и вывести текст текущей даты и времени
      GetCurDate();
      m_str = m_strDate;
      GetCurTime();
      m_str += m_strTime;
      pdc->ExtTextOut(rcBounds.left,
        rcBounds.top,
        ETO_CLIPPED,
        rcBounds,
        m_str,
        m_str.GetLength(),
        NULL);
    }
  • Постройте проект и проверьте его в утилите ActiveX Control Test Container

Должен получиться такой результат


Вывод текущего времени в непрерывном режиме

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

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

  • Выделите в панели ресурсов Resource View узел MyClock.rc, затем либо через меню Edit оболочки, либо через контекстное меню узла выполните опцию Resource Symbols (символы резурсов)
  • В диалоговом окне Resource Symbols щелкните на New (создать)
  • В диалоговом окне New Symbol (создание символа) заполните поля как на рисунке

  • Значение поля Value окна New Symbol можно изменить или оставить по умолчанию

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

  • В панели Class View выделите класс CMyClockCtrl, а в панели Properties установите режим Messages

  • Создайте обработчик OnCreate(), который заполните так
    Обработчик OnCreate() в файле MyClockCtrl.cpp
    int CMyClockCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
      if (COleControl::OnCreate(lpCreateStruct) == -1)
        return -1;
      
      // TODO:  Add your specialized creation code here
      
      // Установить таймер
      SetTimer(ID_CLOCK_TIMER, 1000, NULL);
      
      return 0;
    }

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

  • В панели Class View выделите класс CMyClockCtrl, а в панели Properties установите режим Messages

  • Найдите сообщение WM_TIMER, создайте для него обработчик, который заполните так
    Обработчик OnTimer() в файле MyClockCtrl.cpp
    void CMyClockCtrl::OnTimer(UINT nIDEvent)
    {
      // TODO: Add your message handler code here and/or call default
      
      // Переключить вызов на функцию OnDraw()
      InvalidateControl();
      
      COleControl::OnTimer(nIDEvent);
    }

Предусмотрим остановку системного таймера при разрушении элемента управления.

  • В панели Class View выделите класс CMyClockCtrl, а в панели Properties установите режим Messages

  • Найдите сообщение WM_DESTROY, создайте для него обработчик, который заполните так
    Обработчик OnDestroy() в файле MyClockCtrl.cpp
    void CMyClockCtrl::OnDestroy()
    {
      COleControl::OnDestroy();
      
      // TODO: Add your message handler code here
      
      // Остановить таймер
      KillTimer(ID_CLOCK_TIMER); 
    }
  • Постройте проект и проверьте его в утилите ActiveX Control Test Container. Время должно меняться ежесекундно
  • Сохраните в своем каталоге сессию тестирования утилиты ActiveX Control Test Container под именем TestMyClock, чтобы при следующем тестировании можно было бы просто открыть нужную сессию, а не искать элемент управления MyClock

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