List control multiline tooltip(DataTip)
Click here for larger image
For end user, The list control that has long and multiple columns can be real hassle... Scrolling up and down, scrolling left and right, and resizing truncated column string. For this reason, almost all of the list control based control has ToolTip and/or TitleTip. Even ToolTip or TitleTip list controls, however, sometimes can't be enough to make a really good user-friendly list control.
This article show you a sort of data tip list control plus sophisticated(?) header tool tip.
Implementing data tip in list control is quite easy. All the functions you concern about is following two functions.
OnToolHitTest() is for detecting mouse movement and retriving list control item on which mouse is on, and OnToolTipText() is for supplying actual tip text to display.
Like OnMouseMove(), OnToolHitTest() is called every time mouse moves, and at this time, you can find current row and fill up TOOLINFO structure with some infomations
int CDataTipListCtrl::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
{
CRect rect;
GetClientRect(&rect);
if(rect.PtInRect(point))
{
if(GetItemCount())
{
int nTopIndex = GetTopIndex();
int nBottomIndex = nTopIndex + GetCountPerPage();
if(nBottomIndex > GetItemCount())
nBottomIndex = GetItemCount();
for(int nIndex = nTopIndex;
nIndex < = nBottomIndex; nIndex++)
{
GetItemRect(nIndex, rect, LVIR_BOUNDS);
if(rect.PtInRect(point))
{
pTI->hwnd = m_hWnd;
pTI->uId = (UINT)(nIndex+1);
pTI->lpszText = LPSTR_TEXTCALLBACK;
pTI->rect = rect;
return pTI->uId;
}
}
}
}
return -1;
}
After some delay, OnToolTipText() function is called. in this function, you supply actual tip text to display.
BOOL CDataTipListCtrl::OnToolTipText(UINT id,
NMHDR* pNMHDR,
LRESULT* pResult)
{
// I want to implement this in PreSubclassWindow(),
// but it crashes.
if(!m_bToolTipCtrlCustomizeDone)
{
AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
CToolTipCtrl *pToolTip = pThreadState->m_pToolTip;
// Set max tip width in pixel.
// you can change delay time, tip text or background
// color also. enjoy yourself!
pToolTip->SetMaxTipWidth(500);
m_bToolTipCtrlCustomizeDone = TRUE;
}
// need to handle both ANSI and UNICODE versions of
// the message
TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
UINT nID = pNMHDR->idFrom;
if(nID == 0) // Notification in NT from automatically
return FALSE; // created tooltip
int nItem = nID - 1;
CString strTip;
TCHAR buf[MAX_TIP_LENGTH+1];
HDITEM hdCol;
hdCol.mask = HDI_TEXT;
hdCol.pszText = buf;
hdCol.cchTextMax = MAX_TIP_LENGTH;
int nNumCol = m_Header.GetItemCount();
for(int col=0; col < nNumCol; col++)
{
m_Header.GetItem(col, &hdCol);
strTip += hdCol.pszText;
strTip += _T(": ");
strTip += GetItemText(nItem, col);
if(col < nNumCol-1) strTip += _T('\n');
}
#ifndef _UNICODE
if(pNMHDR->code == TTN_NEEDTEXTA)
{
if(m_pchTip != NULL)
delete m_pchTip;
m_pchTip = new TCHAR[strTip.GetLength()+1];
lstrcpyn(m_pchTip, strTip, strTip.GetLength());
m_pchTip[strTip.GetLength()] = 0;
pTTTW->lpszText = (WCHAR*)m_pchTip;
}
else
{
if(m_pwchTip != NULL)
delete m_pwchTip;
m_pwchTip = new WCHAR[strTip.GetLength()+1];
_mbstowcsz(m_pwchTip, strTip, strTip.GetLength());
m_pwchTip[strTip.GetLength()] = 0; // end of text
pTTTW->lpszText = (WCHAR*)m_pwchTip;
}
#else
if(pNMHDR->code == TTN_NEEDTEXTA)
{
if(m_pchTip != NULL)
delete m_pchTip;
m_pchTip = new TCHAR[strTip.GetLength()+1];
_wcstombsz(m_pchTip, strTip, strTip.GetLength());
m_pchTip[strTip.GetLength()] = 0; // end of text
pTTTA->lpszText = (LPTSTR)m_pchTip;
}
else
{
if(m_pwchTip != NULL)
delete m_pwchTip;
m_pwchTip = new WCHAR[strTip.GetLength()+1];
lstrcpyn(m_pwchTip, strTip, strTip.GetLength());
m_pwchTip[strTip.GetLength()] = 0;
pTTTA->lpszText = (LPTSTR) m_pwchTip;
}
#endif
*pResult = 0;
return TRUE; // message was handled
}
As you already noticed, to increase tip text's length, I introduced m_pchTip, m_pwchTip(for unicode) data member. Without this, you can't display a tip more than 80 characters. And allocated memory for tip text is always deleted next call, but the last call is not, so you must delete it in the destructor. Like this,
CDataTipListCtrl::~CDataTipListCtrl()
{
if(m_pchTip != NULL)
delete m_pchTip;
if(m_pwchTip != NULL)
delete m_pwchTip;
}
And for safety reason, this code should go to constructor too.
CDataTipListCtrl::CDataTipListCtrl()
{
m_pchTip = NULL;
m_pwchTip = NULL;
m_bToolTipCtrlCustomizeDone = FALSE;
}
pToolTip->SetMaxTipWidth(500); is quite essential to this article. Without this line, tool tip never display "multi line" tool tips. m_bToolTipCtrlCustomizeDone data member is for "Only once" purpose.
Don't forget to mapping messages for above two function by inserting the following two lines in you messge map macro.
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
And last, in PreSubclassWindow(), Enable our tool tip.
void CDataTipListCtrl::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call
// the base class
SetExtendedStyle(LVS_EX_FULLROWSELECT); // Enables full row
// selection
EnableToolTips(); // Enables list contrl ToolTip control
m_Header.SubclassDlgItem(0, this); // Replaces new header
// control with default
// list contrl header
// control.
CListCtrl::PreSubclassWindow();
}

Comments
Come across who's preaching about gucci and also as to why you should feel concerned.
Posted by BobHotgloff on 05/02/2013 03:11amA quick article content teaches you the most important cogs and wheels on nike and things you ought to do immediately. [url=http://www.mizunogoruhujp.com/]ããºã[/url] The Industry secrets For nike [url=http://www.mizunogoruhujp.com/ããºã-ã´ã«ãã¯ã©ã-c-1.html]ããºã ã¢ã¤ã¢ã³[/url] Short post teaches you all intricacies for nike as well as things you must do straight away. [url=http://www.mizunogoruhujp.com/ã´ã«ãã°ãã¼ã-c-33.html]ããºã ã°ãã¼ã[/url] What everyone else has been doing with regards to mizuno and furthermore what that you might want to complete different. [url=http://www.mizunogoruhujp.com/ã´ã«ãããã°-c-7.html]ããºã[/url] Unprejudiced summary presents you with 4 brand new things on mizuno that noone is bringing up. [url=http://www.mizunogoruhu.com/]ããºã ã°ãã¼ã[/url] 1 particular double sprain on nike [url=http://www.mizunogoruhu.com/ããºãmizuno-ã¯ã©ã-c-4.html]ããºã mp[/url] Products and assembly throughout Manhattan - nike actually leaves with no bon voyage [url=http://www.mizunogoruhu.com/ããºãmizuno-ã¢ã¤ã¢ã³-c-3.html]ããºã ã¢ã¤ã¢ã³[/url] Highly effective strategies for nike that can be used starting right now. [url=http://www.mizunogoruhu.com/ããºãmizuno-ããã°-c-5.html]ããºã[/url] Short study reveals the proven information regarding nike as well as how it might have an affect on your business.
Replymultiline tooltip displaying does not work
Posted by aditzabici on 03/20/2006 09:26amI ran your code, but it seems that it doesn't work in the way showed in the picture. The \n is displayed like some squares and the text is not moved to the next line. Do you have any idea?
ReplyModification for compiling succeeded under the VC.net(V7.0)
Posted by Legacy on 09/29/2003 12:00amOriginally posted by: Frank Han
Replytooltip in listview
Posted by Legacy on 09/17/2003 12:00amOriginally posted by: sansingh
This works fine with listctrl but what if i want to display the same tooltip in a Listview derived class
ReplyThnx But dont work in VC.Net
Posted by Legacy on 07/21/2003 12:00amOriginally posted by: MAbolghasemi
Thank you,
But When I want to compile it in MFC 7.0 (VC.Net), I have this error :
e:\Internet\DTListDemo\DataTipListCtrl.cpp(125): error C2039: 'm_pToolTip' : is not a member of '_AFX_THREAD_STATE'
please help me.
ReplyMAbolghasemi@yahoo.com
Multiline tooltip problem
Posted by Legacy on 01/21/2002 12:00amOriginally posted by: Helamonster
Replydisplaying two tool tip
Posted by Legacy on 12/18/2001 12:00amOriginally posted by: chittaranhan
i have added tool tips to my ListCtrl program containing thumbnails, which is showing the thumb nail name. but some cases it is showing two tool tips( one what i have added and another provided by OS) when the text length is comparatively large(172 pixel).so how to show only one tool tips.
ReplyPlease suggest me regarding this.
Works for top and bottom rows but not for middle row
Posted by Legacy on 12/12/2001 12:00amOriginally posted by: Haobin Xu
My app contains a listview control that has 3 row and 9 column data on it. The code works perfectly for top and bottom row data but it could not display ToolTips for middle row data. Any idea would be greatly appreciated!
Haobin
ReplyVery good !!!!! I have only one problem
Posted by Legacy on 12/03/2001 12:00amOriginally posted by: Volki
I selected "kein Bildlauf" in the properties
and the program chrashed. Can you help me.
Thanks !
ReplyVolki
Just what I wanted! And a question
Posted by Legacy on 11/29/2001 12:00amOriginally posted by: Sun-A, Shin
except a minor bug (related lpstrcpyn)...
Thank you!
How can I modify the default tooltip-font using this way?
I've tried in tooltip attribute init block in my code,
but there comes no text in my tooltip window...
ReplyLoading, Please Wait ...