原创作者:boqing
原文地址:
http://tb.blog.csdn.net/TrackBack.aspx?PostId=1895519
源码下载地址:
http://download.csdn.net/source/290421
图形界面如下:
l 新建一个MFC工程,命名:TreeViewTipp
l 设置为单文档程序,注意语言选择中文(中国)
l 关键的一步:把基类设置为CTreeView
在TreeViewTippView.h中定义两个CString变量,用于显示提示的内容。
注意:变量类型必须是CString的,并且最好是全局变量,若在函数中定义,需要在堆上分配(new)内存。代码需要稍微改动。
public:
CString m_tip1,m_tip2;
在构造函数中初始化,
CTreeViewTippView::CTreeViewTippView():m_tip1(_T("level-1")),m_tip2(_T("level-2"))
{
// TODO: 在此处添加构造代码
}
说明:m_tip1用来显示一级目录的提示信息,m_tip1用来显示二级目录的提示信息。
在OnInitialUpdate()中添加函数EnableToolTips(TRUE);允许弹出提示窗口
EnableToolTips(TRUE);
OnInitialUpdate()改变CtreeCtrl的风格
long lStyle=GetWindowLong(this->GetTreeCtrl().m_hWnd,GWL_STYLE);
lStyle|=TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT|TVS_EDITLABELS;
SetWindowLong(this->GetTreeCtrl().m_hWnd,GWL_STYLE,lStyle);
给CtreeView添加几个节点,位置:OnInitialUpdate()
HTREEITEM hroot=this->GetTreeCtrl().InsertItem(_T("根目录"),0,0);
//一级目录信息
HTREEITEM level1=this->GetTreeCtrl().InsertItem(_T("一级目录"),0,0,hroot);
this->GetTreeCtrl().SetItemData(level1,(DWORD_PTR)&m_tip1);
//二级目录信息
HTREEITEM level2=this->GetTreeCtrl().InsertItem(_T("二级目录"),0,0,level1);
this->GetTreeCtrl().SetItemData(level2,(DWORD_PTR)&m_tip2);
大家注意到了,根目录节点并没有添加提示信息,但是他能不能提示呢?是的,没有添加提示信息的节点也能显示提示功能,提示的内容是节点本身信息,当节点文本很长而又显示不完整的时候很有用处。
//确定一个点是否位于指定工具的边界矩形之中并获
//得工具的信息
INT_PTR CTreeViewTippView::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
// TODO: Add your specialized code here and/or call the base class
RECT rect;
UINT nFlags;
HTREEITEM hitem = this->GetTreeCtrl().HitTest( point, &nFlags );
//判断若在某个项的文本上面
if( hitem&&(nFlags & TVHT_ONITEMLABEL) )
{
this->GetTreeCtrl().GetItemRect( hitem, &rect, TRUE );
pTI->hwnd = m_hWnd;
pTI->uId = (UINT_PTR)hitem;
pTI->lpszText = LPSTR_TEXTCALLBACK;
pTI->rect = rect;
return pTI->uId;
}
return -1;
//return CTreeView::OnToolHitTest(point, pTI);
}
在VC2005英文环境下,对CtreeViewTippView类的消息进行查找,居然没有找到TTN_NEEDTEXT,算了手动添加吧,记住:一共有三个地方需要改动:
第一:函数声明
在TreeViewTippView.h中添加代码
public:
BOOL OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult );
第二:消息映射
在TreeViewTippView.cpp中找到
BEGIN_MESSAGE_MAP(CTreeViewTippView, CTreeView)
END_MESSAGE_MAP()
修改为:
BEGIN_MESSAGE_MAP(CTreeViewTippView, CTreeView)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
第三:函数实现
在TreeViewTippView.cpp最后添加代码:
//在运行时改变提示
//Tooltip窗口在弹出之前,它给的父窗口发送通知消息TTN_NEEDTEXT,
//请求得到要显示的文本。
BOOL CTreeViewTippView::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 = (UINT)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(); // get mouse pos
ASSERT ( pMessage );
pt = pMessage->pt;
ScreenToClient( &pt );
UINT nFlags;
HTREEITEM hitem = this->GetTreeCtrl().HitTest( pt, &nFlags ); //Get item pointed by mouse
strTipText.Format(_T("%s") , this->GetTreeCtrl().GetItemText( (HTREEITEM ) nID)); //get item text
DWORD dw = (DWORD)this->GetTreeCtrl().GetItemData((HTREEITEM ) nID); //get item data
CString* ItemData = (CString*)dw; //CAST item data
if (ItemData!=NULL)
{
//CString s = ItemData; //pure virtual function
strTipText=CString(_T(" ")) + *ItemData; //add node text to node data text
}
#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
}
说明:稍加修改也适合CTreeCtrl控件,当然也适合CListCtrl和CListBox控件
别忘了给顶一下