Читать «Исчерпывающее руководство по написанию всплывающих подсказок» онлайн - страница 22
Роджер Джек
}
return nResult;
}
BEGIN_MESSAGE_MAP(CODListBox, CTitleTipListBox)
//{{AFX_MSG_MAP(CODListBox)
// NOTE – the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CODListBox message handlers
void CODListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) {
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
ASSERT_VALID(pDC);
int nSavedDC = pDC->SaveDC();
CString strItem;
if (lpDrawItemStruct->itemID != –1) {
GetText(lpDrawItemStruct->itemID, strItem);
}
COLORREF TextColor;
COLORREF BackColor;
UINT nItemState = lpDrawItemStruct->itemState;
if (nItemState & ODS_SELECTED) {
TextColor = RGB(255, 255, 255); // Белый
BackColor = RGB(255, 0, 0); // Красный
} else {
TextColor = RGB(255, 0, 0); // Красный
BackColor = RGB(255, 255, 255); // Белый
}
CRect ItemRect(lpDrawItemStruct->rcItem);
// Нарисовать фон
pDC->FillSolidRect(ItemRect, BackColor);
// Нарисовать текст
pDC->SetTextColor(TextColor);
pDC->SetBkMode(TRANSPARENT);
pDC->SelectObject(&m_Font);
ItemRect.left += m_nEdgeSpace;
pDC->DrawText(strItem, ItemRect, DT_LEFT | DT_SINGLELINE | DT_VCENTER);
ItemRect.left –= m_nEdgeSpace;
// Нарисовать по необходимости рамку фокуса
if (nItemState & ODS_FOCUS) {
pDC->DrawFocusRect(ItemRect);
}
pDC->RestoreDC(nSavedDC);
}
void CODListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) {
lpMeasureItemStruct->itemHeight = m_nFontHeight + (m_nEdgeSpace * 2);
}
CODListBox::GetIdealItemRect перекрывает такой же метод в классе CTitleTipListBox. Как вы видите, его реализация похожа на реализацию метода в базовом классе, за исключением того, что новый метод использует для шрифта переменную m_Font. Конечно, я мог бы добиться результата и без переопределения метода базового класса, если бы воспользовался CWnd::SetFont для установки шрифта для списка. Однако я хотел показать, как нужно перекрывать этот метод в других случаях. Например, вам придется переопределить CTitleTipListBox::GetIdealItemRect, если вы захотите показывать в списке картинки.
CODListBox::DrawItem рисует строку по информации из структуры DrawItemStruct. Этот код аналогичен коду в функции CTitleTip::OnPaint, за исключением того, что вместо цветов по умолчанию используются красный и белый цвета. Помните, что этот метод может вызываться из класса CTitleTip для рисования внутри его окна.
CODListBox::MeasureItem вычисляет высоту строки на основе шрифта и заданного пустого пространства вокруг текста. Этот метод вызывается Windows только один раз, потому что у этого элемента "список" установлен стиль LBS_OWNERDRAWFIXED. В случае со стилем LBS_OWNERDRAWVARIABLE метод будет вызываться для каждой строки.
В диалоге CTTDemoDlg присутствуют оба рассмотренных элемента "список", и большая часть кода была сгенерирована AppWizard'ом (см. рис.14). Я добавил в класс переменные m_RegListBox и m_ODListBox для обычного списка и списка с пользовательской отрисовкой, соответственно. Еще я добавил код в функцию CTTDemoDlg::OnInitDialog, где производится сабклассинг обоих элементов "список" вызовом CWnd::SubclassWindow. Я загружаю оба списка из статического массива pszItemArray.