zoukankan      html  css  js  c++  java
  • CSDN上关于ToolTip的知识

    我用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为该线程的所有窗口服务吗?难道是一种节约资源的表现.这点还需要研究.如果哪位朋友知道答案,还希望能不吝赐教.谢谢.

    ------------------------------------------------2----------------------------

    ToolTip是Win32中一个通用控件,MFC中为其生成了一个类CToolTipCtrl,总的说来其使用方法是较简单的,下面讲一下它的一般用法和高级用法。

    一般用法步骤:

    添加CToolTipCtrl成员变量 m_tt。

    在父窗口中调用EnableToolTips(TRUE);

    在窗口的OnCreate(或者其他适当的位置)中向ToolTip中添加需要显示Tip的子窗口,并同时指定相应的显示字串CToolTipCtrl::AddTool(pWnd,"string to display")。

    重载父窗口的 BOOL PreTranslateMessage(MSG* pMsg) ,在函数中调用 m_tt.RelayEvent(pMsg)。

    下面假设在窗口CWndYour中使用CToolTipCtrl

    在类定义中添加变量说明:
    class CWndYour:xxx
    {
    CToolTipCtrl m_tt;
    }
    在OnCreate中添加需要显示Tip的子窗口
    CWndYour::OnCreate(....)
    {
    EnableToolTips(TRUE);
    m_tt.Create(this);
    m_tt.Activate(TRUE);

    CWnd* pW=GetDlgItem(IDC_CHECK1);//得到窗口指针
    m_tooltip.AddTool(pW,"Check1");//添加
    ........
    }
    在BOOL PreTranslateMessage(MSG* pMsg)中添加代码
    BOOL CWndYour::PreTranslateMessage(MSG* pMsg)
    {
    {
    m_tt.RelayEvent(pMsg);
    }
    return CParentClass::PreTranslateMessage(pMsg);
    }

    这样当鼠标移动到相应的子窗口上时会显示出相应的ToolTip。

    动态改变ToolTip的显示内容的方法及步骤:

    上面所讲的1、2、4步骤。

    在增加ToolTip时不指定显示的字串,而是使用LPSTR_TEXTCALLBACK。

    在窗口中增加消息映射 ON_NOTIFY_EX( TTN_NEEDTEXT, 0, SetTipText )。

    在窗口中增加一个函数用于动态提供显示内容,其原型为 BOOL SetTipText( UINT id, NMHDR * pTTTStruct, LRESULT * pResult ),下面的代码可以根据传入的参数判定应该显示的内容。

    BOOL CWndYour::SetTipText( UINT id, NMHDR * pTTTStruct, LRESULT * pResult )
    {
    TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pTTTStruct;
    UINT nID =pTTTStruct->idFrom; //得到相应窗口ID,有可能是HWND
    if (pTTT->uFlags & TTF_IDISHWND) //表明nID是否为HWND
    {
    nID = ::GetDlgCtrlID((HWND)nID);//从HWND得到ID值,当然你也可以通过HWND值来判断
    switch(nID)
    case(IDC_YOUR_CONTROL1)
    strcpy(pTTT->lpszText,your_string1);//设置
    return TRUE;
    break;
    case(IDC_YOUR_CONTROL2)
    //设置相应的显示字串
    return TRUE;
    break;
    }
    return(FALSE);
    }  
    ToolTip是Win32中一个通用控件,MFC中为其生成了一个类CToolTipCtrl,总的说来其使用方法是较简单的,下面讲一下它的一般用法和高级用法。

    一般用法步骤:

    添加CToolTipCtrl成员变量 m_tt。

    在父窗口中调用EnableToolTips(TRUE);

    在窗口的OnCreate(或者其他适当的位置)中向ToolTip中添加需要显示Tip的子窗口,并同时指定相应的显示字串CToolTipCtrl::AddTool(pWnd,"string to display")。

    重载父窗口的 BOOL PreTranslateMessage(MSG* pMsg) ,在函数中调用 m_tt.RelayEvent(pMsg)。

    下面假设在窗口CWndYour中使用CToolTipCtrl

    在类定义中添加变量说明:
    class CWndYour:xxx
    {
    CToolTipCtrl m_tt;
    }
    在OnCreate中添加需要显示Tip的子窗口
    CWndYour::OnCreate(....)
    {
    EnableToolTips(TRUE);
    m_tt.Create(this);
    m_tt.Activate(TRUE);

    CWnd* pW=GetDlgItem(IDC_CHECK1);//得到窗口指针
    m_tooltip.AddTool(pW,"Check1");//添加
    ........
    }
    在BOOL PreTranslateMessage(MSG* pMsg)中添加代码
    BOOL CWndYour::PreTranslateMessage(MSG* pMsg)
    {
    {
    m_tt.RelayEvent(pMsg);
    }
    return CParentClass::PreTranslateMessage(pMsg);
    }

    这样当鼠标移动到相应的子窗口上时会显示出相应的ToolTip。

    动态改变ToolTip的显示内容的方法及步骤:

    上面所讲的1、2、4步骤。

    在增加ToolTip时不指定显示的字串,而是使用LPSTR_TEXTCALLBACK。

    在窗口中增加消息映射 ON_NOTIFY_EX( TTN_NEEDTEXT, 0, SetTipText )。

    在窗口中增加一个函数用于动态提供显示内容,其原型为 BOOL SetTipText( UINT id, NMHDR * pTTTStruct, LRESULT * pResult ),下面的代码可以根据传入的参数判定应该显示的内容。

    BOOL CWndYour::SetTipText( UINT id, NMHDR * pTTTStruct, LRESULT * pResult )
    {
    TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pTTTStruct;
    UINT nID =pTTTStruct->idFrom; //得到相应窗口ID,有可能是HWND
    if (pTTT->uFlags & TTF_IDISHWND) //表明nID是否为HWND
    {
    nID = ::GetDlgCtrlID((HWND)nID);//从HWND得到ID值,当然你也可以通过HWND值来判断
    switch(nID)
    case(IDC_YOUR_CONTROL1)
    strcpy(pTTT->lpszText,your_string1);//设置
    return TRUE;
    break;
    case(IDC_YOUR_CONTROL2)
    //设置相应的显示字串
    return TRUE;
    break;
    }
    return(FALSE);
    }  

  • 相关阅读:
    利用Python来远程控制肉鸡自由操作,下一个黑客大佬就是你
    利用Python来远程控制肉鸡自由操作,下一个黑客大佬就是你
    职场效率及注意点,数据领域职业选择有哪些
    职场效率及注意点,数据领域职业选择有哪些
    大数据的挑战:数据质量和历史偏见
    IP地址格式转换(htonl、ntohl;inet_addr、inet_ntoa)
    ubuntu 查看软件安装目录以及安装版本
    C++11 POD类型
    C++11 static_assert
    localtime 和 localtime_r
  • 原文地址:https://www.cnblogs.com/lidabo/p/2630392.html
Copyright © 2011-2022 走看看