Click here to Skip to main content
11,485,564 members (80,158 online)
Click here to Skip to main content

ListBox With ToolTip Support

, 4 Jan 2002 176.4K 3.1K 46
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 Pin
GregSmith23-Jan-12 2:01
memberGregSmith23-Jan-12 2:01 
GeneralCould provide the details of the license this code it shared under is it COPL Pin
PSVN Roy13-Oct-10 8:18
memberPSVN Roy13-Oct-10 8:18 
Generalproblem found when 2 listboxes on a dialog. Pin
Member 37416425-Feb-08 23:03
memberMember 37416425-Feb-08 23:03 
QuestionRe: problem found when 2 listboxes on a dialog. Pin
DavidCrow6-May-09 4:05
mvpDavidCrow6-May-09 4:05 
GeneralSubclassed CListBox don't receive TTN_NEEDTEXT Pin
k200v314-Nov-07 5:29
memberk200v314-Nov-07 5:29 
GeneralRe: Subclassed CListBox don't receive TTN_NEEDTEXT Pin
Member 32291893-Sep-09 0:27
memberMember 32291893-Sep-09 0:27 
GeneralI add \r\n in tooltip text, but the tooltip still showed as a single line! Pin
Tcpip20051-Nov-05 20:29
memberTcpip20051-Nov-05 20:29 
GeneralThank you for your work. Pin
David.Kelly26-Aug-05 11:30
memberDavid.Kelly26-Aug-05 11:30 
QuestionHow to delay the tooltip text? Pin
daveice21-Aug-05 21:31
memberdaveice21-Aug-05 21:31 
GeneralTooltip Flickeing in HTML Pin
Anonymous28-Aug-04 1:30
sussAnonymous28-Aug-04 1:30 
GeneralToolTip For ComboBox Pin
BitsAndBytes30-Jul-04 0:19
memberBitsAndBytes30-Jul-04 0:19 
GeneralSelective tooltips Pin
andrew.truckle@atkinsglobal.com4-Mar-04 6:15
memberandrew.truckle@atkinsglobal.com4-Mar-04 6:15 
GeneralRe: Selective tooltips Pin
ccl07526-Jul-04 13:14
sussccl07526-Jul-04 13:14 
GeneralRe: Selective tooltips Pin
andrew.truckle@atkinsglobal.com26-Jul-04 20:52
memberandrew.truckle@atkinsglobal.com26-Jul-04 20:52 
GeneralRe: Selective tooltips Pin
ccl07527-Jul-04 6:59
sussccl07527-Jul-04 6:59 
GeneralRe: Selective tooltips Pin
andrew.truckle@atkinsglobal.com27-Jul-04 20:15
memberandrew.truckle@atkinsglobal.com27-Jul-04 20:15 
GeneralRe: Selective tooltips Pin
Chunyun29-Jul-04 9:18
memberChunyun29-Jul-04 9:18 
GeneralRe: Selective tooltips Pin
Anonymous13-Aug-04 9:24
sussAnonymous13-Aug-04 9:24 
GeneralRe: Selective tooltips Pin
Chunyun13-Aug-04 17:49
memberChunyun13-Aug-04 17:49 
General_mbstowcsz() on VS.NET Pin
Amit Gefen22-Jan-04 12:24
memberAmit Gefen22-Jan-04 12:24 
GeneralTooltip Flickering Pin
Karen03021-Jan-04 4:27
memberKaren03021-Jan-04 4:27 
GeneralEmpty list boxes go boom... Pin
Davant29-Apr-03 11:45
sussDavant29-Apr-03 11:45 
GeneralRe: Empty list boxes go boom... Pin
ran wainstein4-May-03 0:17
memberran wainstein4-May-03 0:17 
QuestionHow to Hook TTN_NEEDTEXT? Pin
4888558427-Apr-03 23:28
suss4888558427-Apr-03 23:28 
QuestionWhy this project doesn't work on my machine? I cannot see the tooltip. Can you tell me ? Pin
Anonymous16-Oct-02 16:43
sussAnonymous16-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.150520.1 | Last Updated 5 Jan 2002
Article Copyright 2002 by ran wainstein
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid