Исчерпывающее руководство по написанию всплывающих подсказок | страница 20



>    CRect ItemRect;

>    GetItemRect(n, ItemRect);

>    if (ItemRect.PtInRect(point)) {

>     nIndexHit = n;

>    }

>   }

>  }

>  AdjustTitleTip(nIndexHit);

> }

> CListBox::OnMouseMove(nFlags, point);

>}


>void CTitleTipListBox::OnSelchange() {

> int nSelIndex;

> if (GetStyle() & LBS_MULTIPLESEL) {

>  nSelIndex = GetCaretIndex();

> } else {

>  nSelIndex = GetCurSel();

> }

> AdjustTitleTip(nSelIndex);

> m_TitleTip.InvalidateRect(NULL);

> m_TitleTip.UpdateWindow();

>}


>void CTitleTipListBox::OnKillFocus(CWnd* pNewWnd) {

> CListBox::OnKillFocus(pNewWnd);

> if (pNewWnd != &m_TitleTip) {

>  AdjustTitleTip(m_nNoIndex);

> }

>}


>void CTitleTipListBox::OnDestroy() {

> AdjustTitleTip(m_nNoIndex);

> m_TitleTip.DestroyWindow();

> CListBox::OnDestroy();

>}


>void CTitleTipListBox::OnLButtonDown(UINT nFlags, CPoint point) {

> // Временно отключить захват мыши, так как базовый класс может

> // захватить мышь.

> if (m_bMouseCaptured) {

>  ReleaseCapture();

>  m_bMouseCaptured = FALSE;

> }

> CListBox::OnLButtonDown(nFlags, point);

> if (m_TitleTip.IsWindowVisible()) {

>  m_TitleTip.InvalidateRect(NULL);

>  if (this != GetCapture()) {

>   CaptureMouse();

>  }

> }

>}


>void CTitleTipListBox::OnLButtonUp(UINT nFlags, CPoint point) {

> CListBox::OnLButtonUp(nFlags, point);

> if (this != GetCapture() && m_TitleTip.IsWindowVisible()) {

>  CaptureMouse();

> }

>}


>BOOL CTitleTipListBox::PreTranslateMessage(MSG* pMsg) {

> switch (pMsg->message) {

> case WM_RBUTTONDOWN:

> case WM_RBUTTONUP:

> case WM_LBUTTONDBLCLK:

> case WM_RBUTTONDBLCLK:

> // Активизировать окно представления, потому что такое

> // поведение подразумевается по сообщению WM_MOUSEACTIVATE,

> // когда над окном нет никаких подсказок.

>  AdjustTitleTip(m_nNoIndex);

>  CFrameWnd* pFrameWnd = GetParentFrame();

>  if (pFrameWnd) {

>   BOOL bDone = FALSE;

>   CWnd* pWnd = this;

>   while (!bDone) {

>    pWnd = pWnd->GetParent();

>    if (!pWnd || pWnd == pFrameWnd) {

>     bDone = TRUE;

>    }

>    else if (pWnd->IsKindOf(RUNTIME_CLASS(CView))) {

>     pFrameWnd->SetActiveView((CView*)pWnd);

>     bDone = TRUE;

>    }

>   }

>  }

>  break;

> }

> return CListBox::PreTranslateMessage(pMsg);

>}

Функция CTitleTipListBox::GetIdealItemRect вычисляет размер и координаты идеальной строки списка. Параметр nIndex – это индекс нужной строки. Параметр lpRect используется для того, чтобы вернуть идеальный размер и координаты в клиентской системе координат. Вы должны переопределить этот метод для элемента "список" с пользовательской отрисовкой, и далее я покажу, как с этим справляется CODListBox. Если не переопределить этот метод для элемента "список" с пользовательской отрисовкой, то метод CTitleTipListBox::GetIdealItemRect выдаст TRACE-сообщение об ошибке. Однако для обычных элементов "список" этот метод автоматически вычисляет размер и координаты идеальной строки списка. Сначала он вызывает функцию CListBox::GetItemRect для вычисления высоты и ширины строки. Ширина строки, возвращенная CListBox::GetItemRect является шириной самого элемента "список", а не шириной текста. Чтобы вычислить настоящую ширину текста подсказки, я получаю текст и шрифт для строки и вызываю CDC::GetTextExtent. Затем в lpRect подставляется максимум от ширины строки и вычисленной ширины строки (плюс немного места по краям из эстетических соображений).