Click here to Skip to main content
Click here to Skip to main content

ListBox With ToolTip Support

, 4 Jan 2002
Rate this:
Please Sign up or sign in to vote.
A CListBox derived class providing Item tooltips
<!-- Download Links --> <!-- Article image -->

Sample Image - CExListBoc.gif

<!-- Add the rest of your HTML here -->

Introduction

I've needed a simple listbox with tool tip support for my project, i couldn't find a listbox derived class that will do job. Salman A Khilji offers tool tip support in his article "List Box with ToolTips", but he his offering a multi-line tool tip which display's a pre-defined string as set in the dialog function. Also, the tips are always shown in the upper right corner.

In order to add tool tips support do the following:

  1. Add ExListBox.cpp and ExListBox.h to your project. 
  2. Add include "ExListBox.h" to the header file of your dialog class. 
  3. Add a list box control to your dialog. 
  4. Use the ClassWizard to add a member variable of type CListBox for the list box you just added.
  5. Manually change the member variable type to CExListBox in your header file of your dialog class. 

That's it, your list box will now display tool tip according to the item's text!

CExListBox - Explanation 

First we must enable the tool tip, so we add the following line to the PreSubclassWindow function:

void CExListBox::PreSubclassWindow() 
{
// TODO: Add your specialized code here and/or call the base class

CListBox::PreSubclassWindow();
EnableToolTips(TRUE);

}

Now , we need to override OnToolHitTest function in order  to provide the struct(s) for the ListBox.

int CExListBox::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
{
    int row;
    RECT cellrect; // cellrect - to hold the bounding rect
    BOOL tmp = FALSE;
    row = ItemFromPoint(point,tmp); //we call the ItemFromPoint function to determine the row,
    //note that in NT this function may fail use the ItemFromPointNT member function
    if ( row == -1 ) 
        return -1;

    //set up the TOOLINFO structure. GetItemRect(row,&cellrect);
    GetItemRect(row,&cellrect);
    pTI->rect = cellrect;
    pTI->hwnd = m_hWnd;
    pTI->uId = (UINT)((row)); //The ‘uId’ is assigned a value according to the row value.
    pTI->lpszText = LPSTR_TEXTCALLBACK;  //Send a TTN_NEEDTEXT messages 
    return pTI->uId;

}

As you can see , we first find out on which item the mouse points using the ItemFromPoint function . NOTE: in NT this function may fail, so use the ItemFromPointNT function (included in this class )

After we obtained the item pointed by mouse , we need to assign the item tool tip text , we assign to the TOOLINFO text member the LPSTR_TEXTCALLBACK which sends TTN_NEEDTEXT messages.

All we need to do now , is to supply handles for TTN_NEEDTEXT messages (wide and ansi ).

In the implementation file we add :

BEGIN_MESSAGE_MAP(CExListBox, CListBox)
//{{AFX_MSG_MAP(CExListBox)
// NOTE - the ClassWizard will add and remove mapping macros here.

//}}AFX_MSG_MAP
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()

And then add the OnToolTipText function :

BOOL CExListBox::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
// need to handle both ANSI and UNICODE versions of the message
    TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
    TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
    CString strTipText;
    UINT nID = pNMHDR->idFrom;  //list box item index 
    GetText( nID ,strTipText); //get item text 

//display item text as tool tip 
#ifndef _UNICODE
    if (pNMHDR->code == TTN_NEEDTEXTA)
    lstrcpyn(pTTTA->szText, strTipText, 80);
else
    _mbstowcsz(pTTTW->szText, strTipText, 80);
#else
    if (pNMHDR->code == TTN_NEEDTEXTA)
    _wcstombsz(pTTTA->szText, strTipText, 80);
    else
    lstrcpyn(pTTTW->szText, strTipText, 80);
    #endif
    *pResult = 0;

return TRUE; 
}

The source code

//
//#include "stdafx.h"

#include "ExListBox.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CExListBox

CExListBox::CExListBox()
{
}

CExListBox::~CExListBox()
{
}


BEGIN_MESSAGE_MAP(CExListBox, CListBox)
    //{{AFX_MSG_MAP(CExListBox)
        // NOTE - the ClassWizard will add and remove mapping macros here.

    //}}AFX_MSG_MAP
    ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
    ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CExListBox message handlers

void CExListBox::PreSubclassWindow() 
{
    // TODO: Add your specialized code here and/or call the base class
    

    CListBox::PreSubclassWindow();
    EnableToolTips(TRUE);

}

int CExListBox::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
{
    int row;
    RECT cellrect;   // cellrect        - to hold the bounding rect
    BOOL tmp = FALSE;
    row  = ItemFromPoint(point,tmp);  //we call the ItemFromPoint function to determine the row,
    //note that in NT this function may fail  use the ItemFromPointNT member function

    if ( row == -1 ) 
        return -1;

    //set up the TOOLINFO structure. GetItemRect(row,&cellrect);
    GetItemRect(row,&cellrect);
    pTI->rect = cellrect;
    pTI->hwnd = m_hWnd;
    pTI->uId = (UINT)((row));   //The ‘uId’ is assigned a value according to the row value.
    pTI->lpszText = LPSTR_TEXTCALLBACK;
    return pTI->uId;

}


//Define OnToolTipText(). This is the handler for the TTN_NEEDTEXT notification from 
//support ansi and unicode 
BOOL CExListBox::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
    // need to handle both ANSI and UNICODE versions of the message
    TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
    TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
    CString strTipText;
    UINT nID = pNMHDR->idFrom;

    
    GetText( nID ,strTipText);

#ifndef _UNICODE
    if (pNMHDR->code == TTN_NEEDTEXTA)
        lstrcpyn(pTTTA->szText, strTipText, 80);
    else
        _mbstowcsz(pTTTW->szText, strTipText, 80);
#else
    if (pNMHDR->code == TTN_NEEDTEXTA)
        _wcstombsz(pTTTA->szText, strTipText, 80);
    else
        lstrcpyn(pTTTW->szText, strTipText, 80);
#endif
    *pResult = 0;

    return TRUE;    
}




UINT CExListBox::ItemFromPoint2(CPoint pt, BOOL& bOutside) const

// CListBox::ItemFromPoint does not work on NT.

{
    int nFirstIndex, nLastIndex;
    //GetFirstAndLastIndex(nFirstIndex, nLastIndex);
    nFirstIndex = GetTopIndex();
    nLastIndex = nFirstIndex  + GetCount(); 


    
    bOutside = TRUE;
    
    CRect Rect;
    int nResult = -1;
    
    for (int i = nFirstIndex; nResult == -1 && i <= nLastIndex; i++)
    {
        if (GetItemRect(i, &Rect) != LB_ERR)
        {
            if (Rect.PtInRect(pt))
            {
                nResult  = i;
                bOutside = FALSE;
            }
        }
        
    }
    
    return nResult;
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

ran wainstein
Web Developer
United Kingdom United Kingdom
No Biography provided

Comments and Discussions

 
QuestionFixes for no TTN_NEEDTEXT, no tip, tip under listbox in CComboBox list PinmemberGregSmith23-Jan-12 2:01 
GeneralCould provide the details of the license this code it shared under is it COPL PinmemberPSVN Roy13-Oct-10 8:18 
Generalproblem found when 2 listboxes on a dialog. PinmemberMember 37416425-Feb-08 23:03 
QuestionRe: problem found when 2 listboxes on a dialog. PinmvpDavidCrow6-May-09 4:05 
GeneralSubclassed CListBox don't receive TTN_NEEDTEXT Pinmemberk200v314-Nov-07 5:29 
GeneralRe: Subclassed CListBox don't receive TTN_NEEDTEXT PinmemberMember 32291893-Sep-09 0:27 
GeneralI add \r\n in tooltip text, but the tooltip still showed as a single line! PinmemberTcpip20051-Nov-05 20:29 
GeneralThank you for your work. PinmemberDavid.Kelly26-Aug-05 11:30 
QuestionHow to delay the tooltip text? Pinmemberdaveice21-Aug-05 21:31 
GeneralTooltip Flickeing in HTML PinsussAnonymous28-Aug-04 1:30 
GeneralToolTip For ComboBox PinmemberBitsAndBytes30-Jul-04 0:19 
GeneralSelective tooltips Pinmemberandrew.truckle@atkinsglobal.com4-Mar-04 6:15 
GeneralRe: Selective tooltips Pinsussccl07526-Jul-04 13:14 
GeneralRe: Selective tooltips Pinmemberandrew.truckle@atkinsglobal.com26-Jul-04 20:52 
GeneralRe: Selective tooltips Pinsussccl07527-Jul-04 6:59 
GeneralRe: Selective tooltips Pinmemberandrew.truckle@atkinsglobal.com27-Jul-04 20:15 
GeneralRe: Selective tooltips PinmemberChunyun29-Jul-04 9:18 
GeneralRe: Selective tooltips PinsussAnonymous13-Aug-04 9:24 
GeneralRe: Selective tooltips PinmemberChunyun13-Aug-04 17:49 
General_mbstowcsz() on VS.NET PinmemberAmit Gefen22-Jan-04 12:24 
GeneralTooltip Flickering PinmemberKaren03021-Jan-04 4:27 
GeneralEmpty list boxes go boom... PinsussDavant29-Apr-03 11:45 
GeneralRe: Empty list boxes go boom... Pinmemberran wainstein4-May-03 0:17 
QuestionHow to Hook TTN_NEEDTEXT? Pinsuss4888558427-Apr-03 23:28 
QuestionWhy this project doesn't work on my machine? I cannot see the tooltip. Can you tell me ? PinsussAnonymous16-Oct-02 16:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411028.1 | Last Updated 5 Jan 2002
Article Copyright 2002 by ran wainstein
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid