分享
 
 
 

VC中给树形控件的图标加上工具提示

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

VC中给树形控件的图标加上工具提示

我从没有在任何一个应用程序中看到过图标的工具提示。有时候查遍了整个帮助

文档也没有明白某个图标是什么意思。如果能在自己的程序中为图标加上工具提

示,一定会使界面的友好性大大增加。本文中以树形控件为例,详细介绍了在VC

中使用MFC提供的机制来实现图标工具提示的方法。

---- 第一步:使控件可以显示工具提示

---- 调用EnableToolTips(TRUE)使一个窗口可以显示工具提示。在什么地方插入

这条代码最好呢?在类的PreSubclassWindow()中。因为不管一个控件如何被创建

,MFC都会调用此函数。而其他的函数则不一定会被调用。以OnCreate()为例,如

果调用Create()或CreateEx()创建一个控件,OnCreate()会被调用,而如果一个

控件是从对话框资源创建,OnCreate()就不会被调用。

实现代码如下:

void CTreeCtrlX::PreSubclassWindow()

{

CTreeCtrl::PreSubclassWindow();

EnableToolTips(TRUE);

}

---- 第二步:重载虚函数OnToolHitTest()

---- MFC调用函数来确定在某个点是否应该显示工具提示。MSDN建议如果鼠标落

在应该显示工具提示的点上,返回值1。这并不完全正确。这个函数应该返回不同

的值来区分窗口中不同的应该显示提示的区域。

---- 在这个函数中,本文只处理鼠标落在节点图标或节点状态图标上的情况。读

者可以按照自己的情况向树的其他元素上添加工具提示。在两种情况下,都要计

算图标的区域,并且把TOOLINFO的uID设为鼠标所在点的树节点的句柄。注意,尽

管对于节点图标和节点状态图标,使用了相同的id,但返回值并不相同。不同的

返回值迫使MFC更新工具提示。

---- 虽然我们可以在此函数中给出工具提示,但因为鼠标的每次移动都会调用此

函数,太多的处理并不是一个好注意,所以我们在其他的函数中处理应该显示什

么提示的问题。

类声明中的代码如下所示:

// Overrides

// ClassWizard generated

virtual function overrides

//{{AFX_VIRTUAL(CTreeCtrlX)

protected:

virtual int OnToolHitTest

( CPoint point, TOOLINFO* pTI ) const;

//}}AFX_VIRTUAL

实现代码如下所示:

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 pTI- >uId*2;

}

return -1;

}

---- 第三步:处理TTN_NEEDTEXT消息;

---- 加入一个函数处理TTN_NEEDTEXT消息通知。当工具处理控制需要知道应该显

示什么信息时,这条消息被发出。由于上一步中我们给TOOLINFO的lpszText赋值

为LPSTR_TEXTCALLBACK,所以我们要处理这个消息VC的ClassWizard并不支持这条

消息被映射,所以只有我们自己加入这条消息的映射机制加入到MESSAGE_MAP中去

。我们不得不处理这个消息的两个版本,TTN_NEEDTEXTA和TTN_NEEDTEXTA。消息

映射的代码如下所示:

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()

---- 现在讨论这个函数本身的实现。为了适应不同的语言字符集,ANSI字符集和

UNICODE字符集都必须被处理,处理过程会有些不同。此处对树形控件的本身产生

的ToolTip消息不予处理,过滤掉上述消息的原则是树形控件本身产生的消息的ID

是树形控件窗口的句柄,并且有TTF_IDISHWND标志。根据鼠标位置可以确定应该

给出节点图标还是状态图标的工具提示。本文根据笔者画的图显示了一些无关紧

要的提示,读者做这一步时应该加入一些有意义的提示。当然,本文假定控件包

含节点图标和状态图标。如不包含,计算鼠标位置时要注意 不要计算错误。

BOOL CTreeCtrlX::OnToolTipText

( UINT id, NMHDR * pNMHDR, LRESULT * pResult )

{

// 需要处理ANSI和UNICODE两种格式

TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;

TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;

CString strTipText;

UINT nID = pNMHDR- >idFrom;

// 不必处理树自己发出的ToolTip消息

if( nID == (UINT)m_hWnd &&

(( pNMHDR- >code == TTN_NEEDTEXTA &&

pTTTA- >uFlags & TTF_IDISHWND ) ||

( pNMHDR- >code == TTN_NEEDTEXTW &&

pTTTW- >uFlags & TTF_IDISHWND ) ) )

return FALSE;

// 得到鼠标位置

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 );

switch(nImage)

{

case 0:

strTipText = "叉";

break;

case 1:

strTipText = "加号";

break;

case 2:

strTipText = "菱形";

break;

}

}

else

{

if( (GetItemState( (HTREEITEM ) nID,

TVIS_STATEIMAGEMASK ) > >12 ) == 2 )

strTipText.Format( "此节点被选中" );

else

strTipText.Format( "此节点未被选中" );

}

#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; // 消息处理完毕

}

---- 本文程序在Win9x,VC6.0下调试通过。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有