Introduction
Once
upon a time, I felt the need to use CListCtrls to display (obviously
multi-column-line) mathematical matrices, most of which turned out to have
explicitly as individual cell elements entities with physical real-world
significance. This either meant that I should scorch for extra-space in my
already cluttered form view to accommodate the more explicit, although redundant,
data display, or try to find an ingenious alternative.
How
about commenting each cell/SubItem with tool/info tips? I immediately
remembered Matt Weagle's great article “Using
the ListCtrl”
that referred to the matter of using info tips through LVS_EX_INFOTIP
. Unfortunately,
as stated by the MSDN documentation, there is no way of doing this method with
more granularity than to comment Items with info tips. I then thought about
searching CodeProject for tool tip implementations and prayed to find something
done on ListCtrl. Well, although I didn't find exactly what I was looking for,
I did discover a great article by Nate Maynard
(thanks! I owe you one! :) )
about a CTreeCtrl
derived class providing per item tool tip support and thought “why not make my
first humble contribution to CodeProject?”.
Well,
here it is. Most of my class uses the ideas from Nate Maynard's article, so as to
avoid redundancy (ok: I confess! To avoid losing to much time… :) )
I will only address the CListCtrl
specifics in this article. Please refer to Mr Maynard's article for further insights
on the general issue.
How
it works (specifically for CListCtrls)
The
two major problems I had to deal with when planning my CToolTipListCtrl
were the CListCtrl
specific issues:
1. There are no handles for CListCtrl
SubItems, so I couldn't use CMap
to map the ToolTip strings.
2. The right CListCtrl
member
to use for hit-testing the SubItems would be SubItemHitTest
, which, due to OnToolHitTest
being const
,
would had to have its use be re-evaluated in that particular override…
As
for the first problem, I addressed it using CMapStringToString
with its CString
keys being formed by a
simple algorithm: (Item * 100 + SubItem). Not very elegant, but it does solve
the problem for list controls with less than 100 SubItems per Item (I hope that's
not your case… :) )
The
second was a little trickier (or at least it seemed so at first) but then I
stumbled through the ListView_SubItemHitTest
macro in MSDN which solved my problem.
The
only other thing you must be aware of is that the CListCtrl
masks differ from the CTreeCtrl
‘s on the prefix,
which in the earlier must be LVHT_
.
The
functions
I didn't have much time to override and overload as many base class members as
Nate Maynard, but the one's I did I hope (at least for me they did) will do the
job. They were
virtual BOOL
DeleteAllItems( )
virtual BOOL DeleteItem( int nItem )
All
the other added functions do the same things as their CToolTipTreeCtrl
counterparts,
of course having their own adapted arguments and returns. They were
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 )
One
last remark: I have added a DeleteAllToolTips
statement in the class' destructor so as to avoid memory leakages by not
cleaning up.
Conclusion
There
you have it, and it works! But is this the end of it?
I
think not. You see, there are some unanswered questions. For example, check the
note I left on this code-snippet:
#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;
return FALSE;
Why
was I forced to return FALSE
on the OnToolTipText
override, even when the function did find the string? I would appreciate some
enlightening, anyone…
As
usual, “if you have any suggestions, find errors, or if you just find it
useful, please feel free to drop me a line”.