>#ifndef __TITLETIPLISTBOX_H__
>#define __TITLETIPLISTBOX_H__
>#include "TitleTip.h"
>class CTitleTipListBox : public CListBox { // Construction public:
> CTitleTipListBox();
>// Overrides
> // ClassWizard generated virtual function overrides
> //{{AFX_VIRTUAL(CTitleTipListBox)
>public:
> virtual BOOL PreTranslateMessage(MSG* pMsg);
> //}}AFX_VIRTUAL
> // Implementation
>public:
> virtual ~CTitleTipListBox();
>protected:
> const int m_nNoIndex; // Пустой индекс
> CPoint m_LastMouseMovePoint; // Последние координаты курсора мыши
> BOOL m_bMouseCaptured; // Захвачена ли мышь?
> CTitleTip m_TitleTip; // Показываемый элемент TitleTip
> // Этот метод должен быть переопределен элементом "список" с пользовательской отрисовкой.
> virtual int GetIdealItemRect(int nIndex, LPRECT lpRect);
> void AdjustTitleTip(int nNewIndex);
> void CaptureMouse();
> BOOL IsAppActive();
> // Generated message map functions
>protected:
> //{{AFX_MSG(CTitleTipListBox)
> afx_msg void OnMouseMove(UINT nFlags, CPoint point);
> afx_msg void OnSelchange();
> afx_msg void OnKillFocus(CWnd* pNewWnd);
> afx_msg void OnDestroy();
> afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
> afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
> //}}AFX_MSG
> afx_msg LONG OnContentChanged(UINT, LONG);
> DECLARE_MESSAGE_MAP()
>};
>#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));