ToolTip一般用法和高级用法

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



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



用VC实现TOOL TIP2008-03-17 13:57按照下面的步骤去做:
1、先为static设置一个ID,如ID_TIP;
2、在CDialogBar的头文件中的AFX_MSG内加入一行申明
afx_msg BOOL OnToolTip(UINT id,NMHDR * pNMHDR,LRESULT * pResult);
3、在CDialogBar的CPP文件中的AFX_MSG_MAP内加入一行
ON_NOTIFY_EX(TTN_NEEDTEXT,0,OnToolTip)
4、在CDialogBar的CPP文件中的OnInitDialog()函数内加入
EnableToolTips(TRUE);
5、在CDialogBar的CPP文件中添加OnToolTip函数
BOOL CDialogBar::OnToolTip(UINT id,NMHDR * pNMHDR,LRESULT * pResult)
{
TOOLTIPTEXT * pTTT=(TOOLTIPTEXT *)pNMHDR;
UINT uID = pNMHDR->idFrom;
if(pTTT->uFlags & TTF_IDISHWND)
uID = ::GetDlgCtrlID((HWND)uID);
if(uID == NULL) return FALSE;
switch(uID)
{
case IDC_TIP:
pTTT->lpszText="添加你的提示内容";
break;
}
return TRUE;
}
这样就可以了。
其实,上面的方法可以为任何控件添加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为该线程的所有窗口服务吗?难道是一种节约资源的表现.这点还需要研究.如果哪位朋友知道答案,还希望能不吝赐教.谢谢


//头文件加入
CToolTipCtrl m_tooltip;
//主窗口初始化时加入
m_tooltip.Create(this);
m_tooltip.Activate(TRUE);
m_tooltip.AddTool(GetDlgItem(IDC_>name<), ">text<");
//IDC_>name<为你控件的ID,>text<为显示的内容

利用ClassWizard建立PreTranslateMessage
BOOL CTest5Dlg::PreTranslateMessage(MSG* pMsg)
{
m_tooltip.RelayEvent(pMsg); //你加入的代码
return CDialog::PreTranslateMessage(pMsg);
}


如何用VC++实现在对话框的控件上显示ToolTip 并在状态条上显示控件的信息
湖南省邮电五二六厂
肖天鹏
---- 利用 VC++ 的 AppWizard,可以很容易地实现工具条和菜单项的 ToolTip 或在状态条上显 示帮助信息,但要在对话框的控件上显示 ToolTip 并在状态条上显示控件信息并不是那么容易, 其实,利用 VC++ 中的 WM_SETCURSOR 与 TTN_NEEDTEXT 消息就可达到目的。具体操作如下:

---- 一

---- 利用 VC++ 的 MFC AppWizard 生成一个 SDI 或 MDI 的应用程序

---- 二

---- 编辑对话框控件的字符串资源

---- 例如:

---- IDC_DBBUTTON1 = "this is 肖天鹏的第一自制按钮\n天 鹏", 其中字符串"this is 肖天鹏的第一自制按钮"将在鼠标移到控件上时显示在状态条上,字符串"天 鹏"将作为 ToolTip 显示。

---- 三

---- 建立消息映射。

---- 在对话框的头文件 (*.H) 中加入以下代码:

protected:
    void SetStatusText(UINT nID=0);
    //{{AFX_MSG(CFileOp1)
    afx_msg void OnDestroy();
    afx_msg BOOL OnSetCursor(CWnd* pWnd,
    UINT nHitTest, UINT message);
    //}}AFX_MSG
    afx_msg BOOL OnTipNotify( UINT id, NMHDR *
     pNMHDR, LRESULT * pResult );
    DECLARE_MESSAGE_MAP()
---- 在对话框的实现文件 (*.CPP) 中加入以下代码:

BEGIN_MESSAGE_MAP(CFileOp1, CDialog)
    //{{AFX_MSG_MAP(CFileOp1)
    ON_WM_DESTROY()
    ON_WM_SETCURSOR()
    //}}AFX_MSG_MAP
    ON_NOTIFY_EX(TTN_NEEDTEXT,0,OnTipNotify)
END_MESSAGE_MAP()
---- 四

---- 编辑消息处理函数。

BOOL CFileOp1::OnSetCursor
(CWnd* pWnd, UINT nHitTest, UINT message)
{
// TODO: Add your message handler
 code here and/or call default
    if(pWnd==this)
        SetStatusText();
    else
    {
        TOOLTIPTEXT m_psttt;
        m_psttt.hdr.hwndFrom=m_hWnd;
        m_psttt.hdr.idFrom=pWnd- >GetDlgCtrlID();
        m_psttt.hdr.code=TTN_NEEDTEXT;
        m_psttt.uFlags= TTF_IDISHWND;
        SetStatusText(pWnd- >GetDlgCtrlID());
        this- >SendMessage(WM_NOTIFY,
        m_psttt.hdr.idFrom,(LPARAM)&m_psttt);
    }
return CDialog::OnSetCursor
 (pWnd, nHitTest, message);
}

void CFileOp1::OnDestroy()
{
    SetStatusText();
    CDialog::OnDestroy();
}

void CFileOp1::SetStatusText(UINT nID)
{
    if(nID==0)
        nID=AFX_IDS_IDLEMESSAGE;
    CWnd *pWnd=AfxGetMainWnd()- >GetDescendantWindow
    (AFX_IDW_STATUS_BAR);
    if(pWnd)
    {
        AfxGetMainWnd()- >SendMessage
        (WM_SETMESSAGESTRING ,nID);
        pWnd- >SendMessage(WM_IDLEUPDATECMDUI);
        pWnd- >UpdateWindow();
    }
}

BOOL CFileOp1::OnTipNotify( UINT id, NMHDR *
 pNMHDR, LRESULT * pResult )
{
    TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
    UINT nID =pNMHDR- >idFrom;
    if (pTTT- >uFlags & TTF_IDISHWND)
    {
        nID = ::GetDlgCtrlID((HWND)nID);
        if(nID)
        {
        TCHAR szFullText[256];
        CString StrTipText;
        AfxLoadString(nID,szFullText);
        AfxExtractSubString(StrTipText,
        szFullText,1,'\n');
        if(!StrTipText.IsEmpty())
            strcpy(pTTT-  >lpszText,StrTipText);
            pTTT-  >hinst = AfxGetResourceHandle();
            return(TRUE);
        }
    }
    return(FALSE);
}
---- 五

---- 在 Stdafx.h 文件中加入以下指令:

    #include 〈 afxpriv.h>
    #include 〈 afxres.h>
---- 六

---- 将该对话框作为一个 SDI 或 MDI 应用程序的主框架的子窗口,生成这样一个对话框后,当你把鼠标移到某个控件 ( 必须有相应的字符串资源 )上时,就会出现该控件的 ToolTip 和状态条信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值