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

Особенностью перерисовки COM-объекта является то, что он изображает себя в чужом окне. Поэтому, получив контекст устройства, связвнный с этим окном, он должен постараться не рисовать вне пределов прямоугольника, отведенного для него. В Windows существует понятие поврежденной области окна (Clip region). Это обычно прямоугольная область в пределах которой система позволяет приложению рисовать. Если рисующие функции GDI попробуют выйти за границы этой области, то система не отобразит этих изменений. Следующий код интенсивно работает с clip region, поэтому для понимания алгоритма рекомендуем получить справку о функциях GetClipRgn и SelectClipRgn. В этой реализации функции OnDraw мы намеренно пошли на поводу у схемы, предложенной в заготовке. Позже мы рассмотрим свою, более простую версию. Введите изменения в уже существующее тело функции OnDraw так, чтобы она приобрела следующий вид.

HRESULT OnDraw(ATL_DRAWINFO& di)

{

RECT& r = *(RECT*)di.prcBounds;             // Преобразование RECTL в RECT

HRGN hRgnOld = 0;          // Запоминаем текущую поврежденную область

if (GetClipRgn (di.hdcDraw, hRgnOld) != 1) // Функция GetClipRgn может возвратить: 0, 1 или -1

hRgnOld = 0;

HRGN hRgnNew = CreateRectRgn(r.left,r.top,r.right,r.bottom); // Создание новой области

bool bSelectOldRgn = false; // Оптимистический прогноз (новая область воспринята)

if (hRgnNew)       // Устанавливаем поврежденную область равной r

{

bSelectOldRgn = SelectClipRgn (di.hdcDraw, hRgnNew) == ERROR;

}

::SelectObject (di.hdcDraw, ::CreateSolidBrush (m_clrFillColor));// Изменяем цвет фона

Rectangle (di.hdcDraw, r.left, r.top, r.right, r.bottom);

SetTextAlign (di.hdcDraw, TA_CENTER | TA_BASELINE); // Выравнивание текста и сам текст

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

// Вывод в центр прямоугольника

TextOut (di.hdcDraw,(r.left + r.right)/2,(r.top + r.bottom)/2,

pszText, lstrlen(pszText));

if (bSelectOldRgn) // Если был сбой, то устанавливаем старую область

SelectClipRgn (di.hdcDraw, hRgnOld);

return S_OK;

}

Структура RECTL, на которую указывает prcBounds, идентична структуре RECT, но при заливке она ведет себя на один пиксел лучше (см. справку). Здесь это никак не используется. Автору стандартного фрагмента не хотелось много раз писать выражение di.prcBounds->, поэтому он завел ссылку на объект типа RECTL, приведя ее к типу RECT.

Здесь хочется "взять в руки" CRect, CString и переписать фрагмент заново в более компактной форме, однако, если вы попробуете это сделать, то получите сообщения о том, что CRect и CString неизвестные сущности. Они из другого царства MFC. Мы можем подключить поддержку MFC, но при этом многое потеряем. Одной из причин создания ATL была непоротливость объектов на основе MFC в условиях Web-страниц. Мы не можем себе этого позволить, так как собираемся работать с трехмерной графикой. Поэтому надо привыкать работать по правилам Win32-API и классов COM.

Тестирование объекта

Вновь запустите приложение и убедитесь в том, что нам удалось слегка подкрасить объект. Теперь исследуем функциональность, которую получили бесплатно при оформлении заказа у мастера.

1.  Поместите указатель мыши внутрь рамки объекта, вызовите контекстное меню и дайте команду OpenGL Class Object. При этом появится диалог свойств внедренного объекта, состоящий из двух станиц (Property Pages);

2.  Сдвиньте окно диалога в сторону, чтобы он не заслонял внедренный объект. На первой странице диалога с заголовком Цвет, выберите из списка другой цвет и нажмите кнопку Apply (Применить). Цвет должен измениться;

3.  В выпадающем списке Набор цветов выберите строку Системные цвета Windows и вновь попробуйте изменить цвет объекта. На сей раз произойдет осечка (во всяком случае в моей версии студии).