CToolTipListCtrl - 一个 CListCtrl 派生类,提供每个子项的工具提示






4.58/5 (17投票s)
2001 年 11 月 8 日
3分钟阅读

262887

3558
一个 CListCtrl 派生类,提供每个子项的工具提示,改编自 Nate Maynard 的 CToolTipTreeCtrl
引言
很久以前,我需要使用 CListCtrl 来显示(显然是多列多行)数学矩阵,其中大部分都有明确的、具有物理现实意义的单个单元格元素。这意味着要么我需要在已经混乱的表单视图中寻找额外的空间来容纳更明确但冗余的数据显示,要么尝试寻找一个巧妙的替代方案。
如何用工具/信息提示注释每个单元格/子项? 我立刻想起了 **Matt Weagle** 的精彩文章“Using the ListCtrl”,其中提到了使用 LVS_EX_INFOTIP
来使用信息提示。不幸的是,正如 MSDN 文档所述,没有办法比用信息提示注释项更精细地做到这一点。然后我想到在 CodeProject 上搜索工具提示实现,并祈祷能找到一些关于 ListCtrl 的实现。虽然我没有找到我想要的东西,但我确实发现了一篇由 **Nate Maynard** 撰写的精彩文章(谢谢!我欠你一个人情!:)),该文章是关于一个提供每个项工具提示支持的 CTreeCtrl
派生类,我想:“为什么不为 CodeProject 做出我第一次微薄的贡献呢?”
好吧,这就是它。我的类大部分都使用了 Nate Maynard 文章中的思想,为了避免冗余(好吧:我承认!为了避免浪费太多时间…… :)),我将在本文中仅讨论 CListCtrl
特定的内容。关于更深入的通用问题见解,请参考 Maynard 先生的文章。
工作原理(特别是针对 CListCtrl)
在规划我的 CToolTipListCtrl
时,我面临的两个主要问题是 CListCtrl
特有的问题
1. CListCtrl
子项没有句柄,所以我无法使用 CMap
来映射工具提示字符串。
2. 用于命中测试子项的正确的 CListCtrl
成员是 SubItemHitTest
,由于 OnToolHitTest
是 const
,因此在该特定重载中需要重新评估其使用…
至于第一个问题,我通过使用 CMapStringToString
来解决它,其 CString
键由一个简单的算法生成:(项 * 100 + 子项)。不是很优雅,但它解决了每个项少于 100 个子项的列表控件的问题(我希望不是你的情况…… :))
第二个问题稍微棘手一些(或者至少一开始是这样),但后来我偶然发现了 MSDN 中的 ListView_SubItemHitTest
宏,它解决了我的问题。
你必须注意的唯一另一件事是,CListCtrl
的掩码与 CTreeCtrl
的前缀不同,后者必须是 LVHT_
。
函数
我没有像 Nate Maynard 那样多的时间来重载和覆盖基类成员,但我希望我所做的(至少对我来说是这样)能够完成工作。它们是
virtual BOOL DeleteAllItems( )
virtual BOOL DeleteItem( int nItem )
所有其他添加的函数与其 CToolTipTreeCtrl
对等函数执行相同的功能,当然参数和返回值也经过了相应的调整。它们是
WORD SetToolTipHitMask(WORD wHitMask)
virtual BOOL DeleteItem( int nItem )
virtual void DeleteAllToolTips()
virtual BOOL SetItemToolTipText( int nItem, int nSubItem, LPCTSTR lpszToolTipText )
virtual CString GetItemToolTipText( int nItem, int nSubItem )
最后一点:我在类的析构函数中添加了一个 DeleteAllToolTips
语句,以避免内存泄漏(因为没有清理)。
结论
好了,就是这样,它奏效了!但这就是全部了吗?
我认为不是。你看,还有一些未解答的问题。例如,请查看我留在这个代码片段中的注释
//Deal with UNICODE #ifndef _UNICODE if (pNMHDR->code == TTN_NEEDTEXTA) lstrcpyn(pTTTA->szText, strTipText, 80); else _mbstowcsz(pTTTW->szText, strTipText, 80); #else if (pNMHDR->code == TTN_NEEDTEXTA) _wcstombsz(pTTTA->szText, strTipText, 80); else lstrcpyn(pTTTW->szText, strTipText, 80); #endif return FALSE; //We found a tool tip, //tell the framework this message has been handled //////////////////////////////////////////////////////////////////////////////// // ****** Special note ***** // // Still don't understand why the function must return FALSE for CListCtrl // so as not to cause flickering, as opposed to Nate Maynard's derivation // from CTreeCtrl. // I have experimented with disabling Tooltips for the control // and found out that a "ghost" tooltip appears for a fraction of a second... // // I am completely at a loss... // Seems to work, though... // //////////////////////////////////////////////////////////////////////////////// } } return FALSE; //We didn't handle the message, //let the framework continue propagating the message
为什么我在 OnToolTipText
重载中被迫返回 FALSE
,即使该函数找到了字符串?我将不胜感激任何指点。
一如既往,“如果您有任何建议,发现错误,或者只是觉得它有用,请随时给我写信”。