|
An InfoTip is the name Microsoft give to a tooltip which has multiple lines. If you run IE4.01 or
higher, or have Win98 or 2000 then you will see InfoTips in effect whenever you point your mouse
at 'My Computer' or 'Internet Explorer' on the desktop.
You can add this facility to a Microsoft ListView control by setting an extended style and then
subclassing to respond to LVN_GETINFOTIP notifications passed via the WM_NOTIFY message.
The Endlessly Flexible WM_NOTIFY Message
Most Common Controls use the WM_NOTIFY message to notify the container window of a condition
the application might want to respond to.
MS have designed an interface for the WM_NOTIFY message so it can cover large numbers of
different notifications. The first part of this scheme is that whenever you receive a WM_NOTIFY
message, the lParam of the message is a long pointer to an area of memory, and this area of
memory will always contain at least an NMHDR
structure:
Private Const WM_NOTIFY = &H4E
Private Type NMHDR
hWndFrom As Long
idFrom As Long
code As Long
End Type
This structure allows the control to identify itself to the container window using the
hWndFrom and idFrom members, and also allows a huge number of submessages
to be packed in by setting different values for the code member.
In the commmon control's header file, Microsoft have indicated that ListViews use
code values between -100 and -199, although currently a limited number of these are
actually used.
The extensibility of the WM_NOTIFY message to handling any sort of notification
is achieved by creating structures which contain the mandatory NMHDR structure
fields as the first three elements, but then contain further fields. Each notification
code defines its own unique structure.
In the case of a WM_NOTIFY message with the LVS_INFOTIP code value, the
required structure is as follows:
Private Type NMLVGETINFOTIP
hdr As NMHDR
dwFlags As Long
pszText As String
cchTextMax As Long
iItem As Long
iSubItem As Long
lParam As Long
End Type
InfoTips In Action
To enable InfoTips in a ListView, you just need to tell the ListView it should support
InfoTips. This is done by setting the LVS_EX_INFOTIP extended style:
Private Const LVM_FIRST = &H1000& '' ListView messages
Private Const LVN_FIRST = -100 '' listview
Private Const LVS_EX_INFOTIP = &H400 ' listview does InfoTips for you
Private Const LVM_SETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 54) ' optional wParam == mask
Private Const LVM_GETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 55)
pSetExStyle lvw.hWnd, 0, LVS_EX_INFOTIP
Private Sub pSetExStyle(ByVal hWnd As Long, ByVal lStyle As Long, ByVal lStyleNot As Long)
Dim lS As Long
lS = SendMessageLong(hWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0)
lS = lS And Not lStyleNot
lS = lS Or lStyle
SendMessageLong hWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, lS
End Sub
Once you have done this, the ListView will start sending WM_NOTIFY messages with the
LVN_GETINFOTIP code to the container window of the ListView control. You can
then subclass for the WM_NOTIFY message and return the string for the ListView to
show in the InfoTip using code like this:
Private Const LVN_GETINFOTIP = (LVN_FIRST - 57)
' Module level variable to ensure pointer is valid.
' String pointed to should be an ANSI string.
Private msInfoTipBuffer As String
m_hWnd = GetParent(lvw.hWnd)
AttachMessage Me, m_hWnd, WM_NOTIFY
Private Function ISubclass_WindowProc(ByVal hWnd As Long, ByVal iMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim tNMH As NMHDR
Select Case iMsg
Case WM_NOTIFY
CopyMemory tNMH, ByVal lParam, Len(tNMH)
Select Case tNMH.code
Case LVN_GETINFOTIP
Dim tLVIT As NMLVGETINFOTIP_NOSTRING
Dim sTip As String
CopyMemory tLVIT, ByVal lParam, Len(tLVIT)
sTip = m_lvw.ListItems(tLVIT.iItem + 1).Tag
If sTip <> "" Then
sTip = sTip & vbNullChar
tLVIT.cchTextMax = Len(sTip)
msInfoTipBuffer = StrConv(sTip, vbFromUnicode)
tLVIT.pszText = StrPtr(msInfoTipBuffer)
CopyMemory ByVal lParam, tLVIT, Len(tLVIT)
End If
End Select
End Select
End Function
Wrapping It Up
The sample code includes a class (cListViewInfoTip) which can be used to simply add
InfoTips support to a ListView. This class makes it particularly simple to use because
it simply refers to the ListItem's Tag property, which it uses as the InfoTip. If
you are already using the Tag property for something else, you will want to write
some more sophisticated code. (A good method for doing this would be to store an Object Pointer
in each of the Tags, and use the IUnknown AddRef and Release mechanism
described in the article
Store Objects against a Control's Tag or ItemData property.
To use the Class as is, just reference SSubTmr.DLL
(it appears in the Project->References list as "Subclassing and Timer Assistant (with Multi-Control
Support and Timer bug-fix)". Then add this code:
' Info tip support:
Private m_cLVTip As cListViewInfoTip
Set m_cLVTip = New cListViewInfoTip
m_cLVTip.Attach lvwFiles
Back to top
Back to Source Code
  |