CToolTipCtrl是用来显示单行文本的弹出框,可以给继承自CFrameWnd(提供了一个缺省的TTN_NEEDTEXT消息处理函数)的Windows控件添加一些提示信息。要使用它,包含3个步骤:
也就是说,第一步需要先打开这个功能(Tool Tips)。第二步需要处理TTN_NEEDTEXT消息,并不是必须的。第三步是利用TOOLTIPTEXT结构体提供的信息,设置提示内容。打开工具提示消息功能,使用函数EnableToolTips。其原型是:
BOOL EnableToolTips( BOOL bEnable );
bEnable为TRUE时打开功能,为FALSE时关闭工具提示功能。
处理TTN_NEEDTEXT需要一个消息映射ON_NOTIFY_EX( TTN_NEEDTEXT, 0, memberFxn )。其中的的memberFxn 是消息处理函数。memberFxn 的原型为:
afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result );
NMHDR是一个结构体,包含了对应控件的句柄、ID和消息代码。此参数可以由NMHDR为其一个成员的结构体替换使用,比如后面提到两种结构体NMTTDISPINFO、TOOLTIPTEXT。
typedef struct tagNMHDR { HWND hwndFrom; UINT idFrom; UINT code; } NMHDR;
消息处理函数的参数是NMHDR类型的指针,它实际上指向的是一个 NMTTDISPINFO结构体。
typedef struct tagNMTTDISPINFO { NMHDR hdr; LPTSTR lpszText; char szText[80]; HINSTANCE hinst; UINT uFlags; #if (_WIN32_IE >= 0x0300) LPARAM lParam; #endif } NMTTDISPINFO, FAR *LPNMTTDISPINFO; #define TOOLTIPTEXT NMTTDISPINFO
使用时常使用TOOLTIPTEXT结构体。
typedef struct { NMHDR hdr; // required for all WM_NOTIFY messages LPTSTR lpszText; // see below WCHAR szText[80]; // buffer for tool tip text HINSTANCE hinst; // see below UINT uflags; // flag indicating how to interpret the // idFrom member of the NMHDR structure // that is included in the structure } TOOLTIPTEXT, FAR *LPTOOLTIPTEXT;
可以看出其基本结构是一致的。前者只是后者的一个替代而已。各个成员代码已经做了解释,不再解释。
我们看看MSDN提供的示例:
BOOL CMyFormView::OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult ); { TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR; UINT nID =pNMHDR->idFrom; if (pTTT->uFlags & TTF_IDISHWND) { // idFrom is actually the HWND of the tool nID = ::GetDlgCtrlID((HWND)nID); if(nID) { pTTT->lpszText = MAKEINTRESOURCE(nID); pTTT->hinst = AfxGetResourceHandle(); return(TRUE); } } return(FALSE); } void CTestView::OnInitialUpdate() { CMyFormView::OnInitialUpdate(); EnableToolTips(TRUE); }
TOOLTIPTEXT的uFlags成员就是用来指示NMHDR的idForm的解释方式。如果指示它是一个窗口句柄,它就指示了鼠标当前停靠的控件,显示lpszText或者szText的提示信息。
成功了吗?还差一点,需要将鼠标产生的消息传递给Tool Tip。这就需要使用CToolTipCtrl提供的一个成员函数RelayEvent。
现在开始自己动手吧。
1、创建一个CToolTipCtrl成员。
CToolTipCtrl m_Ttc;
2、添加消息映射。在消息映射宏BEGIN_MESSAGE_MAP(CRDlg, CDialog)和END_MESSAGE_MAP()之间添加如下内容。
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, SetTipText )
3、声明消息处理函数
BOOL SetTipText(UINT id, NMHDR * pTTTStruct, LRESULT * pRes) ;
4、打开工具消息提示功能。调用CToolTipCtrl的BOOL Create( CWnd* pParentWnd, DWORD dwStyle = 0 )函数创建一个CToolTipCtrl。添加在OnInitDialog()函数中。
EnableToolTips(TRUE); m_Ttc.Create(this);
5、注册一个工具。如果只是给一个控件添加提示消息,可以直接将LPSTR_TEXTCALLBACK改为提示消息,不需要消息映射及消息处理函数,但只能给一个控件添加。
m_Ttc.AddTool(GetDlgItem(IDC_RESET), LPSTR_TEXTCALLBACK); m_Ttc.AddTool(GetDlgItem(IDC_SHUFFLE), LPSTR_TEXTCALLBACK);
6、实现消息处理函数。
BOOL CRubiksCubeDlg::SetTipText(UINT id, NMHDR * pTTTStruct, LRESULT * pRes) { TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pTTTStruct; UINT nID =pTTTStruct->idFrom; if (pTTT->uFlags & TTF_IDISHWND) { nID = ::GetDlgCtrlID((HWND)nID); switch(nID) { case(IDC_SHUFFLE): { strcpy(pTTT->lpszText,"随机"); return TRUE; break; } case(IDC_RESET): { strcpy(pTTT->lpszText,"重置。"); return TRUE; break; } } } return FALSE; }
7、在PreTranslateMessage中传递消息。
BOOL CRubiksCubeDlg::PreTranslateMessage(MSG* pMsg) { m_Ttc.RelayEvent(pMsg); return CDialog::PreTranslateMessage(pMsg); }
OK。大功告成。