如何为CCheckListBox添加内容截断时的内联工具提示?
实现CCheckListBox截断项的悬停提示功能
要给MFC的CCheckListBox实现内容截断时显示完整文本提示的功能,需要通过派生自定义类+工具提示控件来实现,具体步骤如下:
1. 派生自定义CCheckListBox类
标准CCheckListBox没有自带悬停提示功能,我们需要创建一个继承自它的自定义类,比如CMyCheckListBox,用来扩展功能。
2. 集成CToolTipCtrl工具提示
在自定义类中添加CToolTipCtrl成员变量,负责显示提示文本;同时添加变量记录上一次悬停的项,避免重复更新提示。
3. 处理鼠标移动消息
通过WM_MOUSEMOVE消息检测鼠标位置,判断当前指向的列表项:
- 获取项的文本内容
- 计算文本的显示宽度,和列表框的可用宽度对比
- 如果文本宽度超过列表框宽度,说明内容被截断,触发工具提示显示完整文本;否则隐藏提示
4. 实现提示文本的更新逻辑
通过TTN_NEEDTEXT通知消息,配合工具提示控件完成文本的更新和显示。
完整代码示例
自定义类头文件(MyCheckListBox.h)
#pragma once #include <afxwin.h> class CMyCheckListBox : public CCheckListBox { DECLARE_DYNAMIC(CMyCheckListBox) public: CMyCheckListBox(); virtual ~CMyCheckListBox(); protected: CToolTipCtrl m_toolTip; int m_lastHoverItem; // 记录上一次悬停的项索引 DECLARE_MESSAGE_MAP() afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg BOOL OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult); virtual void PreSubclassWindow(); };
自定义类实现文件(MyCheckListBox.cpp)
#include "MyCheckListBox.h" IMPLEMENT_DYNAMIC(CMyCheckListBox, CCheckListBox) CMyCheckListBox::CMyCheckListBox() : m_lastHoverItem(-1) { } CMyCheckListBox::~CMyCheckListBox() { } BEGIN_MESSAGE_MAP(CMyCheckListBox, CCheckListBox) ON_WM_MOUSEMOVE() ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &CMyCheckListBox::OnToolTipNotify) END_MESSAGE_MAP() void CMyCheckListBox::PreSubclassWindow() { CCheckListBox::PreSubclassWindow(); // 初始化工具提示:设置延迟时间并激活 m_toolTip.Create(this); m_toolTip.SetDelayTime(TTDT_INITIAL, 500); // 悬停500ms后显示提示 m_toolTip.SetDelayTime(TTDT_AUTOPOP, 5000); // 提示显示5秒后自动消失 m_toolTip.Activate(TRUE); } void CMyCheckListBox::OnMouseMove(UINT nFlags, CPoint point) { CCheckListBox::OnMouseMove(nFlags, point); // 获取鼠标所在的列表项索引 int itemIndex = ItemFromPoint(point, FALSE); if (itemIndex == LB_ERR || itemIndex == m_lastHoverItem) return; m_lastHoverItem = itemIndex; // 获取当前项的文本 CString itemText; GetText(itemIndex, itemText); if (itemText.IsEmpty()) { m_toolTip.Hide(); return; } // 计算文本的实际显示宽度 CDC* pDC = GetDC(); CFont* pOldFont = pDC->SelectObject(GetFont()); CSize textSize = pDC->GetTextExtent(itemText); pDC->SelectObject(pOldFont); ReleaseDC(pDC); // 获取列表框的可用显示宽度(减去滚动条宽度) CRect clientRect; GetClientRect(clientRect); int listWidth = clientRect.Width(); if (GetHorizontalExtent() > listWidth) listWidth -= GetSystemMetrics(SM_CXVSCROLL); // 判断文本是否超出显示范围,更新提示 if (textSize.cx > listWidth) { m_toolTip.UpdateTipText(itemText, this, ID_TOOLTIP); m_toolTip.Pop(); m_toolTip.Activate(TRUE); } else { m_toolTip.Hide(); } } BOOL CMyCheckListBox::OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult) { TOOLTIPTEXT* pTTT = (TOOLTIPTEXT*)pNMHDR; if (pTTT->uFlags & TTF_IDISHWND) { UINT nID = ::GetDlgCtrlID((HWND)pNMHDR->idFrom); if (nID == ID_TOOLTIP) { *pResult = 0; return TRUE; } } return FALSE; }
使用方法
在对话框中,将原CCheckListBox控件的关联变量类型改为CMyCheckListBox;如果是动态创建控件,直接实例化CMyCheckListBox类即可。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

