Стоит Windows 8 Pro, Visual Studio 2010 Express Edition . |
Создание собственного элемента управления ActiveX
Придание функциональности добавленным свойствам
Напишем код, который делает свойства BackColor и ForeColor функциональными. Это позволит после задания новых значений свойствам сразу повлиять на элемент управления.
- Откройте файл MyClockCtrl.cpp и найдите функцию 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. // Задать цвет переднего плана (т.е. цвет текста) // согласно значения свойства ForeColor pdc->SetTextColor(TranslateColor(GetForeColor())); // Установить режим прозрачного фона pdc->SetBkMode(TRANSPARENT); // Создать кисть на основе значения свойства BackColor CBrush bkBrush(TranslateColor(GetBackColor())); // Залить элемент управления, используя значение BackColor pdc->FillRect(rcBounds, &bkBrush); // Получить и вывести текст текущей даты и времени 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); }
-
Установите начальные размеры элемента управления, добавив в конструктор класса CMyClockCtrl следующий код
Добавления в конструктор CMyClockCtrl в файле MyClockCtrl.cpp CMyClockCtrl::CMyClockCtrl() { InitializeIIDs(&IID_DMyClock, &IID_DMyClockEvents); // TODO: Initialize your control's instance data here. // Установить начальные размеры SetInitialSize(300, 15); }
Включение специального свойства в элемент управления MyClock
Базовые свойства предусмотрены оболочкой при создании каркаса. Но во многих случаях может понадибиться включение своих собственных свойств в элемент управления, со своим названием и кодом, который делает свойство функционирующим. Эти свойства называются специальными ( Custom ). Включим в элемент управления MyClock дополнительное свойство с именем UpdateInterval, которое будем использовать для хранения чисел, устанавливающих период обновления таймера.
Добавление свойства UpdateInterval
- Откройте панель Class View и раскройте узел MyClockLib
- Через контекстное меню элемента _DMyClock выполните команду
- Появится мастер, в котором установите переключатель в положение Member variable, а в поле Property name введите текст UpdateInterval. Установите поле Property type в значение LONG. Остальные поля при этом автоматически заполнятся и мастер должен выглядеть так
- Нажмите кнопку Finish для завершения процесса. Убедитесь, что в панели Class View появилось новое свойство
Таким образом мы определили, что новое свойство будет иметь имя UpdateInterval и что это свойство будет использоваться для хранения чисел в переменной m_UpdateInterval типа long. В поле Notification function (функция уведомления) установлено имя обработчика OnUpdateIntervalChanged(), который будет срабатывать всякий раз, когда значение свойства UpdateInterval изменяется.
Инициализация свойства UpdateInterval
Необходимо инициализировать свойство UpdateInterval начальным значением. Для этого
- Откройте файл MyClockCtrl.cpp и найдите функцию DoPropExchange()
-
Дополните код этой функции так
Добавления кода в функцию DoPropExchange() void CMyClockCtrl::DoPropExchange(CPropExchange* pPX) { ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor)); COleControl::DoPropExchange(pPX); // TODO: Call PX_ functions for each persistent custom property. // Инициализировать свойство UpdateInterval // значением 1000 PX_Long(pPX, _T("UpdateInterval"), m_UpdateInterval, 1000); }
Для инициализации свойства UpdateInterval в приведенном коде используется функция PX_Long(), поскольку свойство имеет тип long. Для инициализации свойств других типов можно использовать другие PX -функции, например, PX_Bool(), PX_Short(), PX_String().
Придание функциональности свойству UpdateInterval
Свойство UpdateInterval должно устанавливать частоту срабатывания системного таймера. В настоящий момент это происходит каждые 1000 миллисекунд, поскольку мы установили ранее такой интервал в функции OnCreate() класса CMyClockCtrl. Сейчас нам нужно модифицировать код элемента управления так, чтобы он свое состояние каждые X миллисекунд, где X - текущее значение свойства UpdateInterval.
- Откройте файл MyClockCtrl.cpp и найдите функцию OnUpdateIntervalChanged(), которую создал мастер при добавлении нового свойства
-
Введите следующий код в функцию OnUpdateIntervalChanged()
Добавления кода в функцию OnUpdateIntervalChanged() void CMyClockCtrl::OnUpdateIntervalChanged(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // TODO: Add your property handler code here // Заново установить таймер с периодом, // заданным значением свойства UpdateInterval SetTimer(ID_CLOCK_TIMER, (UINT)m_UpdateInterval, NULL); SetModifiedFlag(); }
Оператор UINT - это переопределенный тип unsigned int. Он обеспечивает явное приведение типа long свойства к ожидаемому функцией SetTimer () значению.
-
Поскольку у нас появилось свойство, где при создании элемента управления хранится значение периода срабатывания таймера, то в код функции OnCreate() также внесите следующие коррективы
Корректирование кода в функции OnCreate() int CMyClockCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (COleControl::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here // Установить таймер SetTimer(ID_CLOCK_TIMER, (UINT)m_UpdateInterval, NULL); return 0; }
Проверка допустимости значения свойства UpdateInterval
Напишем код, который защитит элемент управления от некорректного ввода значения в свойство UpdateInterval (например, отрицательного). Для этого скорректируем функцию OnUpdateIntervalChanged().
- Откройте файл MyClockCtrl.cpp и найдите функцию OnUpdateIntervalChanged(), которую создал мастер при добавлении нового свойства и которую мы уже корректировали
-
Введите следующий код в функцию OnUpdateIntervalChanged()
Повторное корректирование функции OnUpdateIntervalChanged() void CMyClockCtrl::OnUpdateIntervalChanged(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // TODO: Add your property handler code here // Проверка того, что введенное пользователем // значение свойства неотрицательно if(m_UpdateInterval < 0){ MessageBox("Недопустимое значение!!!" "\nУстанавливаю 1000!!!"); m_UpdateInterval = 1000; } // Заново установить таймер с периодом, // заданным значением свойства UpdateInterval SetTimer(ID_CLOCK_TIMER, (UINT)m_UpdateInterval, NULL); SetModifiedFlag(); }