Читать «Исчерпывающее руководство по написанию всплывающих подсказок» онлайн - страница 17

Роджер Джек

};

#endif // __TITLETIPLISTBOX_H__

/////////////////////////////////////////////////////////////////////////////

// TitleTipListBox.cpp : implementation file

//

#include "stdafx.h"

#include "TitleTipListBox.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CTitleTipListBox

CTitleTipListBox::CTitleTipListBox() : m_LastMouseMovePoint(0, 0) , m_nNoIndex(-1) {

 m_bMouseCaptured = FALSE;

}

CTitleTipListBox::~CTitleTipListBox() {

 ASSERT(!m_bMouseCaptured);

}

int CTitleTipListBox::GetIdealItemRect(int nIndex, LPRECT lpRect) {

 // Вычислить размеры идеальной строки. Размеры зависят

 // от длины строки. Это работает только для обычных элементов

 // "список"(без пользовательской отрисовки)

 ASSERT(lpRect);

 ASSERT(nIndex >= 0);

 DWORD dwStyle = GetStyle();

 int nStatus = GetItemRect(nIndex, lpRect);

 if (nStatus != LB_ERR && !(dwStyle & LBS_OWNERDRAWFIXED) && !(dwStyle & LBS_OWNERDRAWVARIABLE)) {

  CString strItem;

  GetText(nIndex, strItem);

  if (!strItem.IsEmpty()) {

   // Вычислить длину идеального текста.

   CClientDC DC(this);

   CFont* pOldFont = DC.SelectObject(GetFont());

   CSize ItemSize = DC.GetTextExtent(strItem);

   DC.SelectObject(pOldFont);

   // Взять максимум от обычной ширины и идеальной ширины.

   const int cxEdgeSpace = 2;

   lpRect->right = max(lpRect->right, lpRect->left + ItemSize.cx + (cxEdgeSpace * 2));

  }

 } else {

  TRACE("Owner-draw listbox detected – override CTitleTipListBox::GetIdeaItemRect()\n");

 }

 return nStatus;

}

void CTitleTipListBox::AdjustTitleTip(int nNewIndex) {

 if (!::IsWindow(m_TitleTip.m_hWnd)) {

  VERIFY(m_TitleTip.Create(this));

 }

 if (nNewIndex == m_nNoIndex) {

  m_TitleTip.Hide();

 } else {

  CRect IdealItemRect;

  GetIdealItemRect(nNewIndex, IdealItemRect);

  CRect ItemRect;

  GetItemRect(nNewIndex, ItemRect);

  if (ItemRect == IdealItemRect) {

   m_TitleTip.Hide();

  } else {

   // Поправить координаты рядом с краем экрана.

   ClientToScreen(IdealItemRect);

   int nScreenWidth = ::GetSystemMetrics(SM_CXFULLSCREEN);

   if (IdealItemRect.right > nScreenWidth) {

    IdealItemRect.OffsetRect(nScreenWidth – IdealItemRect.right, 0);

   }

   if (IdealItemRect.left < 0) {

    IdealItemRect.OffsetRect(-IdealItemRect.left, 0);

   }

   m_TitleTip.Show(IdealItemRect, nNewIndex);

  }

 }

 if (m_TitleTip.IsWindowVisible()) {

  // Удостовериться, что мышь захвачена, чтобы отследить

  // момент отключения подсказки.

  if (!m_bMouseCaptured && GetCapture() != this) {

   CaptureMouse();

  }

 } else {

  // Подсказка невидима, поэтому освободить мышь.

  if (m_bMouseCaptured) {

   VERIFY(ReleaseCapture());

   m_bMouseCaptured = FALSE;

  }

 }

}

void CTitleTipListBox::CaptureMouse() {

 ASSERT(!m_bMouseCaptured);

 CPoint Point;

 VERIFY(GetCursorPos(&Point));

 ScreenToClient(&Point);

 m_LastMouseMovePoint = Point;

 SetCapture();

 m_bMouseCaptured = TRUE;

}

/////////////////////////////////////////////////////////////////////////////