现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

ToolTip用法及实例

2012-08-14 23:12 工业·编程 ⁄ 共 3898字 ⁄ 字号 暂无评论

我们经常在一些软件中看到类似的功能:鼠标移动到一个按钮(或其他控件)上的时候,自动弹出一些提示(不是弹出对话框),以提醒用户该控件的作用或注意事项。这种提示就是所说的Tooltip(如图1所示)。关于Tooltip,网上已经有很多资料了,我在这里只是给大家提供一些链接,让没有做过的朋友能在最短的时间内实现这个功能。

图1

Codeproject已经有许多现成的Tooltip类,并且有的功能非常之强,可以直接拿来用,这会为你节省许多时间!具体链接及说明如下:

(1)XSuperTooltip - Office 2007 Super Tooltip class 地址:http://www.codeproject.com/useritems/XSuperTooltip.asp

说明:这是一个功能相当强大的Tooltip类,它实现了Office 2007风格的Tooltip,当然,初次接触它的话,你肯定要花更多的时间去学习怎么用,我没有用过这个类,因为它所实现的效果远远超过了我软件中的需求,所以,这个类适合那些想让自己的软件Tooltip非常炫的朋友。

(2)CPPToolTip 地址:http://www.codeproject.com/miscctrl/pptooltip.asp

说明:这个类同样强大,你可以看一下上面链接中它的图例,我也没有去仔细看,因为它花哨的功能我也用不了这么多。

(3)CXInfoTip - Information Tooltip 地址:http://www.codeproject.com/miscctrl/xinfotip.asp

说明:这个类是本文介绍的重点,它实现了我的要求,上面的图1就是我用它做出来的效果。

说一下这个类的使用(非常简单):

以VC.NET 2003为例,新建一个基于对话框的MFC应用程序,在该工程中添加XInfoTip.cpp 及 XInfoTip.h 文件(这两个文件在上面的Codeproject链接中你可以找到)。然后在你需要实现Tooltip的对话框类中添加CXInfoTip成员变量(如果有多个Tooltip,请依次添加)m_tip1,然后在OnInitDialog()函数中(如果是子窗口,则需重载子对话框类的该函数,否则看不到这个函数——这是基础知识)添加以下两句代码:

     m_tip1.Create(this);

     m_tip1.AddTool(GetDlgItem(IDC_COMBO_COMPORT),
                 _T("串口未正确连接的话/n/n将导致系统不能运作!"),   //Tooltip的内容
                ::LoadIcon(NULL, IDI_WARNING)); //加载一个警告图标

AddTool()的第一个参数意思是:当鼠标移动到哪一个控件上的时候弹出Tooltip,这里用GetDlgItem来获取句柄就可以了,上面的代码写得非常明白,一看就懂吧?第二个参数是设置弹出的Tooltip中的内容,其中/n是换行符(地球人都知道)。关于第三个参数,可用LoadIcon()函数来加载一个图标显示在Tooltip中(如图1所示),可查MSDN,用法非常简单。

这样做之后,你就差最后一步就可以完成了,即:重载你用到Tooltip的对话框类的PreTranslateMessage()函数(别告诉我你不知道怎么重载哟~),然后将里面的代码改成如下所示:

{

      // TODO: 在此添加专用代码和/或调用基类

m_tip1.RelayEvent(pMsg);    //添加这一句

      return CDialog::PreTranslateMessage(pMsg);

}

好了,大功告成!编译一下试试看,再把鼠标移动到控件上,是不是弹出了很酷的Tooltip?

本文只涉及到了该类的很简单的功能使用,关于改变Tooltip中文字的字体、控制Tooltip显示时间等操作,请参阅Codeproject链接中作者的文章以及Demo。

还有几个类似的,在此一并给出链接:

(4)Message Balloons 地址:http://www.codeproject.com/dialog/message_balloons.asp

(5)A multiline extended tooltip control 地址:http://www.codeproject.com/miscctrl/tooltipex.asp

(6)Display ToolTip in any place on the screen 地址:http://www.codeproject.com/miscctrl/tooltipzen.asp

=============================

方法2:

http://blog.csdn.net/twater2000/archive/2004/08/05/65501.aspx

我用VC做TOOL TIP很多次了,但每次都要再研究一遍.虽然说学而时习,应该的,但主要还是由于自己懒.今天一定要记下来.以后再用的时候,就是参考.也请阅读此文的朋友记下来,将来查阅用.

用VC实现TOOL TIP.比较复杂,其实也简单,但MFC帮助一些窗口实现,而另一些窗口又不实现,倒搞得复杂了.最开始我用WM_MOUSEMOVE消息,然后用CToolTipCtrl::Pop,这个方法太笨.不建议用.除非需要自定义.

MFC对TOOL TIP的支持不错的.缺省情况CFrameWnd支持很好.然后是CWnd.主要体现在TTN_NEEDTEXT消息的支持和OnToolHitTest的支持.TTN_NEEDTEXT是在CFrameWnd中支持的.OnToolHitTest是在CWnd中支持的.有了这些支持,可以在框架窗口中很好实现ToolBar的TIP.和在一个对话框中很好实现一个控件的TOOL TIP.

举例.在对话框中实现TOOL TIP.

1.EnableToolTips( TRUE )是不可少的.建议在:CDialog::OnInitDialog 调用吧.

2.ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnNeedText ).OnNeedText实现了TOOL TIP的文字.传入的参数idFrom是控件的ID,根据控件ID得到相应的TIP文字

就这么简单的两步,就实现了对话框中的TOOL TIP.其实不只对话框,任何窗口都可以用上面的方法实现自己的子窗口控件的TIP.但前提是必须是CWnd的派生类.

这就看出了MFC对TOOL TIP的支持很厉害

但这一切都是MFC实现的我们简单描述一下它的实现原理,这样看得更清楚

CWnd本身就带有一个CToolTipCtrl对象,是放在pThreadState中的这个不说了,知道CWnd有就行了

CWnd负责创建它,然后在PreTranslateMessage中调用了FilterToolTipMessage,这个函数的作用是处理WM_MOUSEMOVE,WM_NCMOUSEMOVE等消息,给CToolTipCtrl一个机会,判断鼠标是否在需要显示TIP的窗口上,如果是,就显示.FilterToolTipMessage先从CWnd::OnToolHitTest得到TOOLINFO:中的数据,比如哪个控件需要TIP等信息,然后利用ADDTOOL消息把这个需要TIP的控制加入到CToolTipCtrl的TOOL列表中,然后将鼠标移动的消息转给CToolTipCtrl处理.如果这个TIP的文字需要用回调函数来获得,就用WM_NOTIFY的TTN_NEEDTEXT从CToolTipCtrl的父窗口获取.这个过程就是CToolTipCtrl判断是否要显示TIP,到获得文字并显示TIP的全过程

这样一分析,就知道原来CWnd帮助实现了控件子窗口的TIP其实就是实现了OnToolHitTest这个函数,然后在PreTranslateMessage中转发消息,帮助CToolTipCtrl正确显示TIP.

而CFrameWnd是实现了TTN_NEEDTEXT的响应,帮助子窗口实现TIP.

其实我们也可以不要这些缺省实现,自己用CToolTipCtrl搞定,做法一样:

1.CToolTipCtrl::Create创建Tool Tip

2.AddTool增加一个TOOL,这里的TOOL就是需要显示TIP的一个区域或一个子窗口.如果对AddTool使用有不清楚的地方,建议查看源程序.可能会觉得直接使用TTM_ADDTOOL更方便.

3.在PreTranslateMessage中调用CToolTipCtrl::RelayMessage

4.如果在AddTool中,文字是用回调函数实现,那就要处理TTN_NEEDTEXT消息.

其实自己创建CToolTipCtrl和MFC做的一样.只是不需要在OnToolHitTest中给出需要显示TIP的窗口或者区域.

如果给子窗口用TIP.就用MFC最简单.如果给自己呢?

设置TOOLINFO中的uFlags = TTF_IDISHWND,然后设置uId为窗口句柄,hWnd为窗口句柄就可以了.

写了这么多,有不对的地方还请和我联系一下,帮助我改正错误.

只是有个问题还没搞明白.就是为什么MFC把CToolTipCtrl放在了pThreadState中.难道是为了用一个TOOL TIP为该线程的所有窗口服务吗?难道是一种节约资源的表现.这点还需要研究.如果哪位朋友知道答案,还希望能不吝赐教.谢谢.

给我留言

留言无头像?