Модель программирования Component Object Model. Разработка COM-сервера, страница 26

Попробуем это исправить. Событие, заключающееся в том, что пользователь объекта изменил одно из его стандарных свойств, поддерживаемых страницами не менее стандартного дилога, будет обработано каркасом COM-сервера и при этом будет вызвана функция COpenGL::OnFillColorChanged, код которой мы не трогали. Сейчас там есть только одна строка ATLTRACE(_T("OnFillColorChanged\n")); которая в режиме отладки (F5) выводит в окно Debug студии текстовое сообщение. Внесите в тело этой функции изменения.

void OnFillColorChanged()

{

if (m_clrFillColor & 0x80000000) // Если выбран системный цвет, то выбираем его по индексу

m_clrFillColor = ::GetSysColor(m_clrFillColor & 0x1f);

}

Признаком выбора системного цвета является единица в старшем разряде m_clrFillColor. В этом случае цвет задан не тремя байтами (red, green, blue), а индексом в таблице системных цветов (см. справку по GetSysColor). Выделяя этот случай, мы выбираем системный цвет с помощью API-функции GetSysColor. Заодно подправим функцию перерисовки, чтобы убедиться, что объект нам подчиняется, а мы умеем программировать с минимумом лишнего кода.

HRESULT OnDraw (ATL_DRAWINFO& di)

{

LPCRECTL p = di.prcBounds;           // Не будем преобразовывать в RECT

HDC dc = di.hdcDraw;

::SetBkColor (dc, m_clrFillColor);   // Цвет подложки текста

::SetTextColor (dc, ~m_clrFillColor & 0xffffff); // Инвертируем цвет текста

::SelectObject (dc, ::CreateSolidBrush (m_clrFillColor));// Цвет фона

Rectangle (dc, p->left, p->top, p->right, p->bottom);

SetTextAlign (dc, TA_CENTER | TA_BASELINE);

LPCTSTR s = _T ("ATL 7.0 : OpenGL");

TextOut (dc, (p->left + p->right)/2, (p->top + p->bottom)/2, s, lstrlen(s));

return S_OK;

}

Запустите и убедитесь, что системные цвета выбираются корректно, а перерисовка при изменении размеров объекта не нарушает заданных границ. Некоторые проблемы возникают при инвертировании цвета фона, если он близок к нейтральному (128,128,128). В качестве упражнения решите эту проблему самостоятельно.

Страницы свойств

Перед тем как мы начнем работать с окном COM-объекта, превращая его в окно OpenGL, покажем как добавить страницу свойств (property page) в уже существующий блок страниц объекта, который активизируется с помощью контекстного меню. Страница свойств является отдельным элементом управления, называемым Property Page, интерфейсы которого должны быть реализованы в рамках отдельного ко-класса. Такая структура позволяет нескольким ко-классам одновременно пользоваться страницами свойств, размещенными в COM DLL-сервере. Новый COM-класс помещается в COM DLL-сервер с помощью той же процедуры, которую вы использовали при вставке класса COpenGL, но при этом вы выбираете другой тип элемента управления.

1.  Дайте команду Add4Add Class, выберите шаблон (Templates) ATL Property Page и нажмите кнопку Open;

2.  В окне следующего мастера (ATL Property Page Wizard) введите имя (Short Name) класса GraphProp. Обратите внимание на то, что поля с именем интерфейса нет. Это объясняется тем, что страницы свойств не нуждаются в специальном интерфейсе;

3.  Перейдите на другую страницу (Options) мастера и установите следующие значания переключателей и флажков: Threading Model: Apartment, Aggregation: Yes.

4.  На последней вкладке Strings вы можете указать некоторые строковые ресурсы для новой страницы свойств, которая попадает в блок уже существующих страниц свойств. В поле Title введите заголовок вкладки, например: Parameters, в поле Doc String поместите строку OpenGL Graphic Property, которая в дальнейшем может попасть в Status line или Tool tip, но пока не используется. Поле Helpfile очистите, так как мы не будем поддерживать Help;

5.  Нажмите кнопку Finish.

Просмотрите результаты работы мастера. Прежде всего, убедитесь, что в idl-файле появилось описание нового ко-класса (coclass GraphProp), затем просмотрите файл декларации класса (GraphProp.h). В нем появился новый элемент, который привязывает к классу "номерок".