Hi Roel. You can subclass the ListView and look for several of the Header Control
Notification Messages. You'll probably be primarily interested in the HDN_ENDTRACK
(user has finished dragging a divider), HDN_DIVIDERDBLCLICK (user double-clicked the
divider area of the control), and HDN_ENDDRAG (re-ordered drag operation has ended).
I've provided some sample code below (tested on VB6). For definitions of the Header
messages, see the following link:
Header Control Notification Messages
http://msdn.microsoft.com/library/sdkdoc/shellcc/commctls/Header/Noti...
cations.htm
The following article may be of some assistance as well:
How to Determine Re-Ordered Column Positions in a ListView
http://mvps.org/vbnet/code/comctl/lvcolumnpos.htm
'=============================
'Begin Module Code
Option Explicit
Public Const WM_NOTIFY = &H4E
Public Const GWL_WNDPROC = -4
Public lpPrevWndProc As Long
Public gHW As Long
Public Declare Function CallWindowProc Lib "user32" Alias _
"CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function SetWindowLong Lib _
"user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Public Declare Sub MoveMemory Lib _
"kernel32" Alias "RtlMoveMemory" _
(pDest As Any, pSource As Any, _
ByVal dwLength As Long)
'The NMHDR structure contains information
'about a notification message.
'The pointer to this structure is specified as
'the lParam member of the WM_NOTIFY message.
Private Type NMHDR
hwndFrom As Long ' Window handle of control sending message
idFrom As Long ' Identifier of control sending message
code As Long ' Specifies the notification code
End Type
Private Type NMHEADER
hdr As NMHDR
iItem As Long
iButton As Long
lPtrHDItem As Long ' HDITEM FAR* pItem
End Type
'Header Notifications
'HDN_BEGINDRAG Drag operation has begun
'HDN_BEGINTRACK User began dragging a divider
'HDN_DIVIDERDBLCLICK User double clicked the divider area
'HDN_ENDDRAG Drag operation has ended
'HDN_ENDTRACK User finished dragging a divider
'HDN_GETDISPINFO Item information request
'HDN_ITEMCHANGED An item has changed
'HDN_ITEMCHANGING An item is changing
'HDN_ITEMCLICK User clicked the control
'HDN_ITEMDBLCLICK User double-clicked the control
'HDN_TRACK User is dragging a divider
'NM_CUSTOMDRAW Custom draw request notification
'NM_RCLICK User clicked right mouse button in control
'NM_RELEASEDCAPTURE Control is releasing mouse capture
Public Enum HD_Notifications
HDN_FIRST = -300&
HDN_LAST = -399&
HDN_GETDISPINFO = (HDN_FIRST - 9)
HDN_BEGINDRAG = (HDN_FIRST - 10)
HDN_ENDDRAG = (HDN_FIRST - 11)
HDN_ITEMCLICK = (HDN_FIRST - 2)
HDN_ITEMDBLCLICK = (HDN_FIRST - 3)
HDN_DIVIDERDBLCLICK = (HDN_FIRST - 5)
HDN_ITEMCHANGING = (HDN_FIRST - 0)
HDN_ITEMCHANGED = (HDN_FIRST - 1)
HDN_BEGINTRACK = (HDN_FIRST - 6)
HDN_ENDTRACK = (HDN_FIRST - 7)
HDN_TRACK = (HDN_FIRST - 8)
NM_FIRST = -0& ' (0U- 0U)
NM_CUSTOMDRAW = (NM_FIRST - 12)
NM_RCLICK = (NM_FIRST - 5)
NM_RELEASEDCAPTURE = (NM_FIRST - 16)
End Enum
Public Sub Hook()
'Establish a hook to capture messages to this window
lpPrevWndProc = SetWindowLong(gHW, _
GWL_WNDPROC, _
AddressOf WindowProc)
End Sub
Public Sub Unhook()
Dim temp As Long
'Reset the message handler for this window
temp = SetWindowLong(gHW, _
GWL_WNDPROC, lpPrevWndProc)
End Sub
Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Dim nmh As NMHDR
Dim nmhd As NMHEADER
Select Case uMsg
Case WM_NOTIFY
' Fill the NMHDR struct from the lParam pointer.
' (for any WM_NOTIFY msg, lParam always points to a struct which is
' either the NMHDR struct, or whose 1st member is the NMHDR struct)
Call MoveMemory(nmh, ByVal lParam, Len(nmh))
' Fill the NMHEADER struct from the lParam pointer.
Call MoveMemory(nmhd, ByVal lParam, Len(nmhd))
Select Case nmh.code
Case HDN_BEGINTRACK 'User began dragging a divider
' nmhd.iItem will tell you which divider is being dragged
' 0 based
Debug.Print "HDN_BEGINTRACK: " & nmhd.iItem
Case HDN_TRACK 'User is dragging a divider
' nmhd.iItem will tell you which divider is being dragged
' 0 based
Debug.Print "HDN_TRACK: " & nmhd.iItem
Case HDN_ENDTRACK 'User finished dragging a divider
' nmhd.iItem will tell you which divider is finished being dragged
' 0 based
Debug.Print "HDN_ENDTRACK: " & nmhd.iItem
Case HDN_DIVIDERDBLCLICK 'User double clicked the divider area
' nmhd.iItem will tell you which divider is being double clicked
' 0 based
Debug.Print "HDN_DIVIDERDBLCLICK: " & nmhd.iItem
Case HDN_BEGINDRAG 'Drag operation has begun
' nmhd.iItem will tell you which divider is being dragged
(re-ordered)
' 0 based
Debug.Print "HDN_BEGINDRAG: " & nmhd.iItem
Case HDN_ENDDRAG 'Drag operation has ended
' nmhd.iItem will tell you which divider is finished being dragged
(re-ordered)
' 0 based
Debug.Print "HDN_ENDDRAG: " & nmhd.iItem
End Select
End Select
'Pass message on to the original window message handler
WindowProc = CallWindowProc(lpPrevWndProc, hwnd, _
uMsg, wParam, lParam)
End Function
'End Module Code
'=============================
'Begin Form Code
Private Sub Form_Load()
'Store handle
gHW = ListView1.hwnd
Hook
End Sub
Private Sub Form_Unload(Cancel As Integer)
'Pressing the End button or selecting End from _
the Run menu without unhooking causes _
an Invalid Page Fault and closes Microsoft Visual Basic.
'Call procedure to stop intercepting
'the messages for this window
Unhook
End Sub
End Form Code
'=============================
'-------
galen
: My application uses the ListView control and allows users to drag column
: headers and change their width. Of course the user wants these changes saved
: so every time I show a different list (with different column headers) I save
: the width and order of all columns.
:
: Most users will drag the columns just a few times and will then leave them
: alone. So 99 of a 100 times I'm saving the information for nothing.
:
: Does anybody know how to detect changes in columnheader position and width
: so I can save them only when needed?
:
: Roel de Regt
:
:
: