Читать «Исчерпывающее руководство по написанию всплывающих подсказок» онлайн - страница 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.