要点:通过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系统将会为你找到最近的最匹配的一条记录! ");