为TreeCtrl中的项增加ToolTip

本文介绍如何在CTreeCtrl控件中实现ToolTip功能。主要包括三个步骤:启用ToolTip功能、重载OnToolHitTest确定何时显示ToolTip及处理TTN_NEEDTEXT消息以设置ToolTip文本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

要点:通过OnToolHitTest来增加ToolTip,CTreeCtrl::HitTest(...)的使用,TTN_NEEDTEXT消息的处理。

定义一个新类,有CTreeCtrl派生
Step 1:打开ToolTip 功能
void CTreeCtrlX::PreSubclassWindow()
{
     CTreeCtrl::PreSubclassWindow();

     EnableToolTips(TRUE);
}


Step 2: OnToolHitTest() 的重载
首先通过HitTest决定是否增加ToolTip,如果需要则返回非零。

在本例中ToolTip使用了LPSTR_TEXTCALLBACK,而没有立即设定显示字符串。

在本例只在鼠标指向每项的图片时才显示ToolTip



int CTreeCtrlX::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
{
     RECT rect;

     UINT nFlags;
     HTREEITEM hitem = HitTest( point, &nFlags );
     if( nFlags & TVHT_ONITEMICON )
     {
         CImageList *pImg = GetImageList( TVSIL_NORMAL );
         IMAGEINFO imageinfo;
         pImg->GetImageInfo( 0, &imageinfo );

         GetItemRect( hitem, &rect, TRUE );
         rect.right = rect.left - 2;
         rect.left -= (imageinfo.rcImage.right + 2);

         pTI->hwnd = m_hWnd;
         pTI->uId = (UINT)hitem;
         pTI->lpszText = LPSTR_TEXTCALLBACK;
         pTI->rect = rect;
         return pTI->uId;
     }
     else if( nFlags & TVHT_ONITEMSTATEICON )
     {
         CImageList *pImg = GetImageList( TVSIL_NORMAL );
         IMAGEINFO imageinfo;
         pImg->GetImageInfo( 0, &imageinfo );

         GetItemRect( hitem, &rect, TRUE );
         rect.right = rect.left - (imageinfo.rcImage.right + 2);

         pImg = GetImageList( TVSIL_STATE );
         rect.left = rect.right - imageinfo.rcImage.right ;

         pTI->hwnd = m_hWnd;
         pTI->uId = (UINT)hitem;
         pTI->lpszText = LPSTR_TEXTCALLBACK;
         pTI->rect = rect;

         // return value should be different from that used for item icon
         return pTI->uId*2;
     }
     return -1;
}
Step 3: ?? TTN_NEEDTEXT
由于在增加ToolTip是使用用了 LPSTR_TEXTCALLBACK,因此ToolTip在显示时会发送该消息来得到显示字符串。

BEGIN_MESSAGE_MAP(CTreeCtrlX, CTreeCtrl)
     //{{AFX_MSG_MAP(CTreeCtrlX)
     :
     :
     //}}AFX_MSG_MAP
     ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
     ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
protected:
     //{{AFX_MSG(CTreeCtrlX)
     :
     :
     //}}AFX_MSG
     afx_msg BOOL OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult );
     DECLARE_MESSAGE_MAP()

BOOL CTreeCtrlX::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;

// Do not process the message from built in tooltip
if( nID == (UINT)m_hWnd &&
(( pNMHDR->code == TTN_NEEDTEXTA && pTTTA->uFlags & TTF_IDISHWND ) ||
( pNMHDR->code == TTN_NEEDTEXTW && pTTTW->uFlags & TTF_IDISHWND ) ) )
return FALSE;

// Get the mouse position
const MSG* pMessage;
CPoint pt;
pMessage = GetCurrentMessage();
ASSERT ( pMessage );
pt = pMessage->pt;
ScreenToClient( &pt );

UINT nFlags;
HTREEITEM hitem = HitTest( pt, &nFlags );
if( nFlags & TVHT_ONITEMICON )
{
int nImage, nSelImage;
GetItemImage( (HTREEITEM ) nID, nImage, nSelImage );
strTipText.Format( "Image : %d", nImage );
}
else
{
strTipText.Format( "State : %d", GetItemState( (HTREEITEM ) nID,
      TVIS_STATEIMAGEMASK ) );
}

#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; // message was handled
}

 

=---------------------------------------------------

 

m_tooltip.Create(this);
m_tooltip.Activate(TRUE);
m_tooltip.SetTipBkColor(RGB(240,220,2040));
m_tooltip.SetTipTextColor(RGB(80,0,200));
m_tooltip.SetDelayTime(500);
m_tooltip.SetMaxTipWidth(5000);//只要加上此句,下面的就可以换行了!!用/r/n换行
m_tooltip.AddTool(GetDlgItem(IDC_EDIT1), "这里输入大概的编号,/r/n系统将会为你找到最近的最匹配的一条记录! ");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值