На этом шаге мы рассмотрим алгоритм отображения элемента управления.
Нам осталось реализовать код для отображения элемента управления на экране. Как и 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.