|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionMicrosoft's
BackgroundThere are lots of advanced grid controls that extend the How to implement a tooltip in CListCtrlFor normal MFC controls, there are usually two methods for enabling tooltips:
The
This article will only focus on how to display a simple tooltip for a cell in CWnd::EnableToolTips()This method usually requires three steps:
The third step is only necessary if the second step specifies that the tooltip text should be retrieved using the callback ( BEGIN_MESSAGE_MAP(CListCtrl_EnableToolTip, CListCtrl)
ON_NOTIFY_EX(TTN_NEEDTEXTA, 0, OnToolNeedText)
ON_NOTIFY_EX(TTN_NEEDTEXTW, 0, OnToolNeedText)
END_MESSAGE_MAP()
void CListCtrl_EnableToolTip::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
GetToolTips()->Activate(FALSE);
// Activates the standard CWnd tooltip functionality
VERIFY( EnableToolTips(TRUE) );
}
INT_PTR CListCtrl_EnableToolTip::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
{
CPoint pt(GetMessagePos());
ScreenToClient(&pt);
if (!ShowToolTip(pt))
return -1;
int nRow, nCol;
CellHitTest(pt, nRow, nCol);
//Get the client (area occupied by this control
RECT rcClient;
GetClientRect( &rcClient );
//Fill in the TOOLINFO structure
pTI->hwnd = m_hWnd;
pTI->uId = (UINT) (nRow * 1000 + nCol);
// Send TTN_NEEDTEXT when tooltip should be shown
pTI->lpszText = LPSTR_TEXTCALLBACK;
pTI->rect = rcClient;
return pTI->uId;
// Must return a unique value for each cell (Marks a new tooltip)
}
BOOL CListCtrl_EnableToolTip::OnToolNeedText(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
{
CPoint pt(GetMessagePos());
ScreenToClient(&pt);
int nRow, nCol;
CellHitTest(pt, nRow, nCol);
CString tooltip = GetToolTipText(nRow, nCol);
if (tooltip.IsEmpty())
return FALSE;
// Non-unicode applications can receive requests for tooltip-text in unicode
TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
#ifndef _UNICODE
if (pNMHDR->code == TTN_NEEDTEXTA)
lstrcpyn(pTTTA->szText, tooltip.GetString(), sizeof(pTTTA->szText));
else
_mbstowcsz(pTTTW->szText, tooltip.GetString(), sizeof(pTTTW->szText));
#else
if (pNMHDR->code == TTN_NEEDTEXTA)
_wcstombsz(pTTTA->szText, tooltip.GetString(), sizeof(pTTTA->szText));
else
lstrcpyn(pTTTW->szText, tooltip.GetString(), sizeof(pTTTW->szText));
#endif
return TRUE;
}
The CToolTipCtrl member variableThis method usually requires four steps:
The last step is only required if supplying the tooltip text using The BEGIN_MESSAGE_MAP(CListCtrl_OwnToolTipCtrl, CListCtrl)
ON_WM_MOUSEMOVE()
ON_NOTIFY_EX(TTN_NEEDTEXTA, 0, OnToolNeedText)
ON_NOTIFY_EX(TTN_NEEDTEXTW, 0, OnToolNeedText)
END_MESSAGE_MAP()
void CListCtrl_OwnToolTipCtrl::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
GetToolTips()->Activate(FALSE);
VERIFY( m_OwnToolTipCtrl.Create(this, TTS_ALWAYSTIP) );
m_OwnToolTipCtrl.Activate(TRUE);
}
BOOL CListCtrl_OwnToolTipCtrl::PreTranslateMessage(MSG* pMsg)
{
if (m_OwnToolTipCtrl.m_hWnd)
m_OwnToolTipCtrl.RelayEvent(pMsg);
return CListCtrl::PreTranslateMessage(pMsg);
}
void CListCtrl_OwnToolTipCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
CPoint pt(GetMessagePos());
ScreenToClient(&pt);
// Find the subitem
LVHITTESTINFO hitinfo = {0};
hitinfo.flags = nFlags;
hitinfo.pt = pt;
SubItemHitTest(&hitinfo);
if (m_LastToolTipCol!=hitinfo.iSubItem || m_LastToolTipRow!=hitinfo.iItem)
{
// Mouse moved over a new cell
m_LastToolTipCol = hitinfo.iSubItem;
m_LastToolTipRow = hitinfo.iItem;
// Remove the old tooltip (if available)
if (m_OwnToolTipCtrl.GetToolCount()>0)
{
m_OwnToolTipCtrl.DelTool(this);
m_OwnToolTipCtrl.Activate(FALSE);
}
// Add the new tooltip (if available)
if (m_LastToolTipRow!=-1 && m_LastToolTipRow!=-1)
{
// Not using CToolTipCtrl::AddTool() because
// it redirects the messages to CListCtrl parent
TOOLINFO ti = {0};
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_IDISHWND; // Indicate that uId is handle to a control
ti.uId = (UINT_PTR)m_hWnd; // Handle to the control
ti.hwnd = m_hWnd; // Handle to window
// to receive the tooltip-messages
ti.hinst = AfxGetInstanceHandle();
ti.lpszText = LPSTR_TEXTCALLBACK;
m_OwnToolTipCtrl.SendMessage(TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
m_OwnToolTipCtrl.Activate(TRUE);
}
}
CListCtrl::OnMouseMove(nFlags, point);
}
CListCtrl::GetToolTips()This solution only requires that we create a A few quirks have been discovered with this solution:
Extended style label tipThis solution only requires that we add the extended style void CListCtrl_LabelTip::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
SetExtendedStyle(LVS_EX_INFOTIP | GetExtendedStyle());
}
Extended style Info TipThe Info Tip will only work for the label-column, and it is limited to 80 characters. The solution requires two steps:
BEGIN_MESSAGE_MAP(CListCtrl_InfoTip, CListCtrl)
ON_NOTIFY_REFLECT_EX(LVN_GETINFOTIP, OnGetInfoTip)
END_MESSAGE_MAP()
void CListCtrl_InfoTip::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
SetExtendedStyle(LVS_EX_INFOTIP | GetExtendedStyle());
}
BOOL CListCtrl_InfoTip::OnGetInfoTip(NMHDR* pNMHDR, LRESULT* pResult)
{
// Will only request tooltip for the label-column
NMLVGETINFOTIP* pInfoTip = (NMLVGETINFOTIP*)pNMHDR;
CString tooltip = GetToolTipText(pInfoTip->iItem, pInfoTip->iSubItem);
if (!tooltip.IsEmpty())
{
_tcsncpy(pInfoTip->pszText, tooltip.GetString(), pInfoTip->cchTextMax);
}
return FALSE; // Let parent-dialog get chance
}
Using the codeThe source code provides examples of how to implement the described tooltip solutions for History
|
||||||||||||||||||||||