На этом шаге мы рассмотрим алгоритм отображения элемента управления.
Нам осталось реализовать код для отображения элемента управления на экране. Как и MFC-класс COleControl, ATL-класс CComControl предоставляет функцию OnDraw(), содержащую весь код отображения. В CComControl::OnDraw() передается указатель на структуру ATL_DRAWINFO, помимо всего прочего содержащую описатель контекста устройства и указатель на структуру RECT со сведениями об ограничивающем прямоугольнике элемента управления. Контекст устройства - это HDC, тип "сырых" данных Windows, скрытый MFC-классом CDC. Это означает, что для отображения нашего элемента управления мы должны применять функции GDI API. GDI-функции идентичны своим CDC-аналогам за исключением того, что в качестве первого параметра они получают HDC. Сравнив реализацию функций CATLBandit::OnDraw() и COneArmedBanditCtrl::OnDraw(), Вы поймете, как все это работает.
Замените тело функции CATLBandit::OnDraw() в файле ATLBandit.h следующим кодом:
HRESULT OnDraw(ATL_DRAWINFO& di) { const RECT& rc = *reinterpret_cast<const RECT*>(di.prcBounds); HDC dc = di.hdcDraw; COLORREF colorBack, colorFore; OleTranslateColor( m_clrForeColor, NULL, &colorFore ); OleTranslateColor( m_clrBackColor, NULL, &colorBack ); // Получаем размеры элемента управления float ctrlWidth = float( rc.right - rc.left ); float ctrlHeight = float( rc.bottom - rc.top ); // Настройка контекста устройства HBRUSH brush = CreateSolidBrush( colorBack ); HBRUSH oldBrush = static_cast<HBRUSH>(SelectObject( dc, brush ) ); HPEN pen = CreatePen( PS_SOLID, 3, colorFore ); HPEN oldPen = static_cast<HPEN>(SelectObject( dc, pen ) ); HFONT SymbolFont = CreateFont( long(ctrlHeight / 1.1), long(ctrlWidth/6), 0, 0, 0, 0, 0, 0, SYMBOL_CHARSET, 0, 0, 0, 0,"WingDings" ); HFONT oldFont = static_cast<HFONT>(SelectObject( dc, SymbolFont ) ); // Отображаем ограничивающий прямоугольник Rectangle( dc, rc.left, rc.top, rc.right, rc.bottom ); SetBkMode( dc, TRANSPARENT ); // Выводим текст SetTextColor( dc, colorFore ); RECT rect; CopyRect( &rect, &rc ); TCHAR strDisplay[ 5 ]; _stprintf( strDisplay, "%c %c %c", m_symbols[ 0 ], m_symbols[ 1 ], m_symbols[ 2 ] ); DrawText( dc, strDisplay, 5, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER ); // Отображаем вертикальные панели long onethird = long(ctrlWidth / 3); POINT ptTop = { rc.left, rc.top }; POINT ptBtm = { rc.left, rc.bottom }; ptTop.x += onethird; ptBtm.x += onethird; MoveToEx( dc, ptTop.x, ptTop.y, NULL ); LineTo( dc, ptBtm.x, ptBtm.y ); ptTop.x += onethird; ptBtm.x += onethird; MoveToEx( dc, ptTop.x, ptTop.y, NULL ); LineTo( dc, ptBtm.x, ptBtm.y ); // Восстанавливаем контекст устройства SelectObject( dc, oldFont ); SelectObject( dc, oldPen ); SelectObject( dc, oldBrush ); DeleteObject( brush ); DeleteObject( pen ); DeleteObject( SymbolFont ); return S_OK; }
Теперь мы готовы перейти к сборке элемента управления ATLBandit. Загрузите его в ActiveX Control Test Container, чтобы просмотреть внешний вид, страницы свойств, поддержку постоянства свойств метод Рlау() и события Click и Jackpot.
Текст приложения можно взять здесь (40,1 Кб).
На следующем шаге мы сравним MFC и ATL.