Click here to Skip to main content
Licence 
First Posted 4 Jan 2002
Views 161,201
Bookmarked 44 times

ListBox With ToolTip Support

By | 4 Jan 2002 | Article
A CListBox derived class providing Item tooltips

Sample Image - CExListBoc.gif

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

About the Author

ran wainstein

Web Developer

United Kingdom United Kingdom

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionFixes for no TTN_NEEDTEXT, no tip, tip under listbox in CComboBox list PinmemberGregSmith1:01 23 Jan '12  
GeneralCould provide the details of the license this code it shared under is it COPL PinmemberPSVN Roy7:18 13 Oct '10  
Generalproblem found when 2 listboxes on a dialog. PinmemberMember 37416422:03 25 Feb '08  
QuestionRe: problem found when 2 listboxes on a dialog. PinmvpDavidCrow3:05 6 May '09  
GeneralSubclassed CListBox don't receive TTN_NEEDTEXT Pinmemberk200v34:29 14 Nov '07  
GeneralRe: Subclassed CListBox don't receive TTN_NEEDTEXT PinmemberMember 322918923:27 2 Sep '09  
GeneralI add \r\n in tooltip text, but the tooltip still showed as a single line! PinmemberTcpip200519:29 1 Nov '05  
GeneralThank you for your work. PinmemberDavid.Kelly10:30 26 Aug '05  
QuestionHow to delay the tooltip text? Pinmemberdaveice20:31 21 Aug '05  
GeneralTooltip Flickeing in HTML PinsussAnonymous0:30 28 Aug '04  
GeneralToolTip For ComboBox PinmemberBitsAndBytes23:19 29 Jul '04  
GeneralSelective tooltips Pinmemberandrew.truckle@atkinsglobal.com5:15 4 Mar '04  
GeneralRe: Selective tooltips Pinsussccl07512:14 26 Jul '04  
GeneralRe: Selective tooltips Pinmemberandrew.truckle@atkinsglobal.com19:52 26 Jul '04  
GeneralRe: Selective tooltips Pinsussccl0755:59 27 Jul '04  
GeneralRe: Selective tooltips Pinmemberandrew.truckle@atkinsglobal.com19:15 27 Jul '04  
GeneralRe: Selective tooltips PinmemberChunyun8:18 29 Jul '04  
GeneralRe: Selective tooltips PinsussAnonymous8:24 13 Aug '04  
GeneralRe: Selective tooltips PinmemberChunyun16:49 13 Aug '04  
General_mbstowcsz() on VS.NET PinmemberAmit Gefen11:24 22 Jan '04  
GeneralTooltip Flickering PinmemberKaren03023:27 1 Jan '04  
GeneralEmpty list boxes go boom... PinsussDavant10:45 29 Apr '03  
GeneralRe: Empty list boxes go boom... Pinmemberran wainstein23:17 3 May '03  
QuestionHow to Hook TTN_NEEDTEXT? Pinsuss4888558422:28 27 Apr '03  
QuestionWhy this project doesn't work on my machine? I cannot see the tooltip. Can you tell me ? PinsussAnonymous15:43 16 Oct '02  

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.

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