|
-
Feb 21st, 2002, 10:17 PM
#1
Took a little while, but figured it out.
You can do it by subclassing the Listview and intercepting the
HDN_BEGINTRACK Header Notification Message.
In this example, I've set it up so that any column with a width of 0 (Zero) is deemed not sizable.
In a Standard Module:
VB Code:
Option Explicit
' GetWindowsLong Constants
Private Const GWL_WNDPROC = (-4)
' Windows Message Constants
Private Const WM_NOTIFY = &H4E
Private Const WM_DESTROY = &H2
' Column Header Notification Meassage Constants
Private Const HDN_FIRST = -300&
Private Const HDN_BEGINTRACK = (HDN_FIRST - 6)
' Column Header Item Info Message Constants
Private Const HDI_WIDTH = &H1
' Notify Message Header Type
Private Type NMHDR
hWndFrom As Long
idFrom As Long
code As Long
End Type
' Notify Message Header for Listview
Private Type NMHEADER
hdr As NMHDR
iItem As Long
iButton As Long
lPtrHDItem As Long ' HDITEM FAR* pItem
End Type
' Header Item Type
Private Type HDITEM
mask As Long
cxy As Long
pszText As Long
hbm As Long
cchTextMax As Long
fmt As Long
lParam As Long
iImage As Long
iOrder As Long
End Type
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private 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
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private mlPrevWndProc As Long
Private Function WindowProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim tNMH As NMHDR
Dim tNMHEADER As NMHEADER
Dim tITEM As HDITEM
Select Case Msg
Case WM_NOTIFY
' Copy the Notify Message Header to a Header Structure
CopyMemory tNMH, ByVal lParam, Len(tNMH)
Select Case tNMH.code
Case HDN_BEGINTRACK
' If the user is trying to Size a Column Header...
' Extract Information about the Header being Sized
CopyMemory tNMHEADER, ByVal lParam, Len(tNMHEADER)
' Get Item Info. about the header (i.e. Width)
CopyMemory tITEM, ByVal tNMHEADER.lPtrHDItem, Len(tITEM)
' Don't allow Zero Width Columns to be Sized.
If (tITEM.mask And HDI_WIDTH) = HDI_WIDTH And tITEM.cxy = 0 Then
WindowProc = 1
Exit Function
End If
End Select
Case WM_DESTROY
' Remove Subclassing when Listview is Destroyed (Form unloaded.)
WindowProc = CallWindowProc(mlPrevWndProc, hWnd, Msg, wParam, lParam)
Call SetWindowLong(hWnd, GWL_WNDPROC, mlPrevWndProc)
Exit Function
End Select
' Call Default Window Handler
WindowProc = CallWindowProc(mlPrevWndProc, hWnd, Msg, wParam, lParam)
End Function
Public Sub SubClassHwnd(ByVal hWnd As Long)
mlPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
In Form with ListView:
VB Code:
Option Explicit
Private Sub Form_Load()
Dim lIndex As Long
SubClassHwnd ListView1.hWnd
With ListView1
.View = lvwReport
For lIndex = 1 To 5
.ColumnHeaders.Add , "COL" & lIndex, "Column " & lIndex, IIf(lIndex = 3, 0, (.Width - 200) / 4)
Next
End With
End Sub
-
Feb 21st, 2002, 10:21 PM
#2
Holy crap that's cool!
Thanks a lot Aaron.
Laugh, and the world laughs with you. Cry, and you just water down your vodka.
Take credit, not responsibility
-
May 2nd, 2002, 11:03 PM
#3
PowerPoster
Nice one!
:thumbsup:
-----------------------------------------
-RJ
[email protected]
-----------------------------------------
-
Nov 4th, 2002, 04:37 PM
#4
Amen to the above compliments. Can the code be modified so that the cursor doesn't change to the double-bar form?
-
Nov 4th, 2002, 04:38 PM
#5
I would imagine that catching WM_SETCURSOR, or something similar, would accomplish that. Never really looked into it though.
Laugh, and the world laughs with you. Cry, and you just water down your vodka.
Take credit, not responsibility
-
Jun 9th, 2004, 04:08 PM
#6
Can this be modified to prevent resize of non zero width columns? Like some other fixed value...
-
Jun 9th, 2004, 04:10 PM
#7
So Unbanned
Nice code, I can already see uses for it in one appliacation of mine.
One thing, shouldn't those len()'s be LenB()'s, just to be safe.
-
Jun 9th, 2004, 04:25 PM
#8
Originally posted by baja_yu
Can this be modified to prevent resize of non zero width columns? Like some other fixed value...
Yes
VB Code:
' Don't allow Zero Width Columns to be Sized.
If (tITEM.mask And HDI_WIDTH) = HDI_WIDTH And tITEM.cxy = 0 Then
Change that from 0 to whatever you want.
Laugh, and the world laughs with you. Cry, and you just water down your vodka.
Take credit, not responsibility
-
Jun 10th, 2004, 01:56 PM
#9
Originally posted by crptcblade
Yes
VB Code:
' Don't allow Zero Width Columns to be Sized.
If (tITEM.mask And HDI_WIDTH) = HDI_WIDTH And tITEM.cxy = 0 Then
Change that from 0 to whatever you want.
No....that didnt work... The first column is 350...so I tried that... nothing.....then I noticed that it made it's size 349.79....tried that...nothing..... then I made a messagebox write the width....and it said 349.7953...... tried that and nothing...
-
Jun 10th, 2004, 03:17 PM
#10
How about < 350 instead of = 0?
-
Jun 10th, 2004, 03:23 PM
#11
Tired that too.... then all columns get locked for resizing and I cant resize any of them....
And I dont understand this because all of them, except the first one, are way wider than 350....
-
Jun 10th, 2004, 03:29 PM
#12
I don't have the code in front of me so it's hard to tell from here waht's going on but when you try to resize the column, does this line execute?
If (tITEM.mask And HDI_WIDTH) = HDI_WIDTH And tITEM.cxy = 0 Then
If so then set a breakpoint on that line and see what each of the variables contain and let me know.
-
Jun 10th, 2004, 03:37 PM
#13
Martin, I followed your idea and found that
tITEM.mask = 1
HDI_WIDTH = 1
but
tITEM.cxy = 23
even if the width is 350 .... so I set the limit to 23...
and now it works like I want it to...
But the readings are kinda odd... maybe it is in twips and not in pixels..
-
Jun 10th, 2004, 05:32 PM
#14
I was surprised to see this old thread back on top.
Here is Aaron's code that I had modified a while ago to prevent
the resizing of certain columns and prevents the double-click auto-
resize column width when the user tries to position the mouse
between column headers for a resize.
Also, I added code to keep certain columns a certain fixed width.
The "tITEM.cxy = 60" is a different measurement unit - twips I believe.
If you were to double-click a column with aarons code on a zero
width column, you would be able to open it up if it had anything
in it.
VB Code:
Private Function WindowProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim tNMH As NMHDR
Dim tNMHEADER As NMHEADER
Dim tITEM As HDITEM
Select Case Msg
Case WM_NOTIFY
' COPY THE NOTIFY MESSAGE HEADER TO A HEADER STRUCTURE
CopyMemory tNMH, ByVal lParam, Len(tNMH)
Select Case tNMH.code
Case HDN_DIVIDERDBLCLICKA
'IF THE USER IS TRYING TO DOUBLECLICK A COLUMN HEADER...
'EXTRACT INFORMATION ABOUT THE HEADER BEING SIZED
CopyMemory tNMHEADER, ByVal lParam, Len(tNMHEADER)
'GET THE INFO ABOUT THE HEADER (IE. INDEX#)
'DONT ALLOW COLUMNS 1 OR 2 TO BE DOUBLECLICKED
If (tNMHEADER.iItem < 3) = True Then
WindowProc = 1
Exit Function
ElseIf (tNMHEADER.iItem = 5) = True Then 'DURATION
WindowProc = 1
Exit Function
End If
Case HDN_BEGINTRACK
'IF THE USER IS TRYING TO SIZE A COLUMN HEADER...
'EXTRACT INFORMATION ABOUT THE HEADER BEING SIZED
CopyMemory tNMHEADER, ByVal lParam, Len(tNMHEADER)
'GET THE INFO ABOUT THE HEADER (IE. WIDTH)
CopyMemory tITEM, ByVal tNMHEADER.lPtrHDItem, Len(tITEM)
'DONT ALLOW ZERO OR COLUMNS 1 OR 2 TO BE SIZED
If (tNMHEADER.iItem < 3) = True Then 'TYPE & STATUS
WindowProc = 1
Exit Function
ElseIf (tNMHEADER.iItem = 5) = True Then 'DURATION
'If (tITEM.mask And HDI_WIDTH) = HDI_WIDTH And tITEM.cxy = 27 Then
WindowProc = 1
Exit Function
'End If
End If
End Select
Case WM_DESTROY
'REMOVE SUBCLASSING WHEN LISTVIEW IS DESTROYED (FORM UNLOADED)
WindowProc = CallWindowProc(mlPrevWndProc, hWnd, Msg, wParam, lParam)
Call SetWindowLong(hWnd, GWL_WNDPROC, mlPrevWndProc)
Exit Function
End Select
'CALL DEFAULT WINDOW HANDLER
WindowProc = CallWindowProc(mlPrevWndProc, hWnd, Msg, wParam, lParam)
End Function
Last edited by RobDog888; Jun 11th, 2004 at 12:22 PM.
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum. 
Microsoft MVP 2006-2011
Office Development FAQ (C#, VB.NET, VB 6, VBA)
Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
If a post has helped you then Please Rate it! 
• Reps & Rating Posts • VS.NET on Vista • Multiple .NET Framework Versions • Office Primary Interop Assemblies • VB/Office Guru™ Word SpellChecker™.NET • VB/Office Guru™ Word SpellChecker™ VB6 • VB.NET Attributes Ex. • Outlook Global Address List • API Viewer utility • .NET API Viewer Utility •
System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6 
-
Jun 11th, 2004, 02:06 AM
#15
I am getting a variable not defined for: HDN_DIVIDERDBLCLICKA
And I think same will happen for HDN_BEGINTRACK
Also, I am guessing these are constants... what are their values?
Last edited by baja_yu; Jun 11th, 2004 at 02:50 AM.
-
Jun 11th, 2004, 10:14 AM
#16
I had only posted the change to the procedure from Aaron's
code. You will need all his code from above and replace his
WindowProc with mine. Also, here is the declaration for the const.
VB Code:
Private Const HDN_DIVIDERDBLCLICKA As Long = (HDN_FIRST-5)
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum. 
Microsoft MVP 2006-2011
Office Development FAQ (C#, VB.NET, VB 6, VBA)
Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
If a post has helped you then Please Rate it! 
• Reps & Rating Posts • VS.NET on Vista • Multiple .NET Framework Versions • Office Primary Interop Assemblies • VB/Office Guru™ Word SpellChecker™.NET • VB/Office Guru™ Word SpellChecker™ VB6 • VB.NET Attributes Ex. • Outlook Global Address List • API Viewer utility • .NET API Viewer Utility •
System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6 
-
Jun 11th, 2004, 11:56 AM
#17
Yeah, I know. And I still got the error...
Anyway, I added the definition, and it does prevent doubleclikc, but it also prevents resizing of all columns, not just the one I set the widt to 23 (I am using that width)...
Aarons code works, but I can do the doubleclick...
-
Jun 11th, 2004, 12:00 PM
#18
Thats because you needed to modify it for whatever columns you
want to prevent the resize for. My example works and it works
for columns 1,2, & 5. Not by width only column index number -
base 1.
This could be part of the issue. I forgot to take it out from testing.
Comment like I have it.
VB Code:
'If (tITEM.mask And HDI_WIDTH) = HDI_WIDTH And tITEM.cxy = 27 Then
WindowProc = 1
Exit Function
'End If
Post your procedure so I can see whats wrong.
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum. 
Microsoft MVP 2006-2011
Office Development FAQ (C#, VB.NET, VB 6, VBA)
Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
If a post has helped you then Please Rate it! 
• Reps & Rating Posts • VS.NET on Vista • Multiple .NET Framework Versions • Office Primary Interop Assemblies • VB/Office Guru™ Word SpellChecker™.NET • VB/Office Guru™ Word SpellChecker™ VB6 • VB.NET Attributes Ex. • Outlook Global Address List • API Viewer utility • .NET API Viewer Utility •
System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6 
-
Jun 11th, 2004, 12:21 PM
#19
-
Jun 11th, 2004, 12:24 PM
#20
Glad to hear its working for you now.
I commented my code on my original post with the fix too.
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum. 
Microsoft MVP 2006-2011
Office Development FAQ (C#, VB.NET, VB 6, VBA)
Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
If a post has helped you then Please Rate it! 
• Reps & Rating Posts • VS.NET on Vista • Multiple .NET Framework Versions • Office Primary Interop Assemblies • VB/Office Guru™ Word SpellChecker™.NET • VB/Office Guru™ Word SpellChecker™ VB6 • VB.NET Attributes Ex. • Outlook Global Address List • API Viewer utility • .NET API Viewer Utility •
System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6 
-
Nov 12th, 2004, 12:04 PM
#21
Fanatic Member
Now all we need is a VB.Net version.
-
Jan 4th, 2006, 06:04 PM
#22
Hyperactive Member
Re: Preventing certain Listview columns from sizing...
Hey, how do we make this code "IDE-friendly"? So IDE doesn't crash every time one exits the program..
Signed, Rodik ([email protected])
Programmer,usesVB6ED
===========================
Copyright©RodikCo,2002.
Dont mind this signature ;] Its old
-
Jan 4th, 2006, 06:09 PM
#23
Re: Preventing certain Listview columns from sizing...
You need to close your app instead of stopping the code from the IDE.
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum. 
Microsoft MVP 2006-2011
Office Development FAQ (C#, VB.NET, VB 6, VBA)
Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
If a post has helped you then Please Rate it! 
• Reps & Rating Posts • VS.NET on Vista • Multiple .NET Framework Versions • Office Primary Interop Assemblies • VB/Office Guru™ Word SpellChecker™.NET • VB/Office Guru™ Word SpellChecker™ VB6 • VB.NET Attributes Ex. • Outlook Global Address List • API Viewer utility • .NET API Viewer Utility •
System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6 
-
Sep 20th, 2006, 08:22 AM
#24
Frenzied Member
Re: Preventing certain Listview columns from sizing...
I tried Aaron's code above and I get an error saying "Invalid use of AddressOf operator". Has anyone seen this before?
Thanks!
-
Sep 20th, 2006, 10:57 AM
#25
Re: Preventing certain Listview columns from sizing...
I believe that that code needs to be in a code module rather than a form. How are you using it?
-
Sep 20th, 2006, 10:58 AM
#26
Frenzied Member
Re: Preventing certain Listview columns from sizing...
Yes, I stuck it in my main form. I'll try it in a module instead and will reply back.
Thanks!
Warren
-
Apr 17th, 2008, 12:44 PM
#27
New Member
Re: Preventing certain Listview columns from sizing...
Hello to you all
A little late, I know, but I was just now looking for a way to prevent column on a listview from sizing. SO I found these messages. Thanks for it, but I noticed that it is still possible to resize the column after double-cllicking. Has anyone found this also and how did you fix that??
Thanks
Catharinus van der Werf
Leeuwarden, Holland
-
Apr 17th, 2008, 01:11 PM
#28
Re: Preventing certain Listview columns from sizing...
I can't reproduce that problem. Can you zip up and attach your project?
-
Apr 17th, 2008, 01:17 PM
#29
New Member
Re: Preventing certain Listview columns from sizing...
Hier is de code:
Zet onderstaande in een module:
' GetWindowsLong Constants
Private Const GWL_WNDPROC = (-4)
' Windows Message Constants
Private Const WM_NOTIFY = &H4E
Private Const WM_DESTROY = &H2
' Column Header Notification Meassage Constants
Private Const HDN_FIRST = -300&
Private Const HDN_BEGINTRACK = (HDN_FIRST - 6)
' Column Header Item Info Message Constants
Private Const HDI_WIDTH = &H1
' Notify Message Header Type
Private Type NMHDR
hWndFrom As Long
idFrom As Long
code As Long
End Type
' Notify Message Header for Listview
Private Type NMHEADER
hdr As NMHDR
iItem As Long
iButton As Long
lPtrHDItem As Long ' HDITEM FAR* pItem
End Type
' Header Item Type
Private Type HDITEM
mask As Long
cxy As Long
pszText As Long
hbm As Long
cchTextMax As Long
fmt As Long
lParam As Long
iImage As Long
iOrder As Long
End Type
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private 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
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private mlPrevWndProc As Long
Private Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim tNMH As NMHDR
Dim tNMHEADER As NMHEADER
Dim tITEM As HDITEM
Select Case Msg
Case WM_NOTIFY
' COPY THE NOTIFY MESSAGE HEADER TO A HEADER STRUCTURE
CopyMemory tNMH, ByVal lParam, Len(tNMH)
Select Case tNMH.code
Case HDN_DIVIDERDBLCLICKA
'IF THE USER IS TRYING TO DOUBLECLICK A COLUMN HEADER...
'EXTRACT INFORMATION ABOUT THE HEADER BEING SIZED
CopyMemory tNMHEADER, ByVal lParam, Len(tNMHEADER)
'GET THE INFO ABOUT THE HEADER (IE. INDEX#)
'DONT ALLOW COLUMNS 1 OR 2 TO BE DOUBLECLICKED
If (tNMHEADER.iItem < 9) = True Then '9 heb ik zelf ingevoerd als maximum kolom
WindowProc = 1
'Exit Function
'ElseIf (tNMHEADER.iItem = 5) = True Then 'DURATION
'WindowProc = 1
'Exit Function
End If
Case HDN_BEGINTRACK
'IF THE USER IS TRYING TO SIZE A COLUMN HEADER...
'EXTRACT INFORMATION ABOUT THE HEADER BEING SIZED
CopyMemory tNMHEADER, ByVal lParam, Len(tNMHEADER)
'GET THE INFO ABOUT THE HEADER (IE. WIDTH)
CopyMemory tITEM, ByVal tNMHEADER.lPtrHDItem, Len(tITEM)
'DONT ALLOW ZERO OR COLUMNS 1 OR 2 TO BE SIZED
If (tNMHEADER.iItem < 9) = True Then 'TYPE & STATUS'9 heb ik zelf ingevoerd als maximum kolom
WindowProc = 1
Exit Function
'ElseIf (tNMHEADER.iItem = 5) = True Then 'DURATION
''If (tITEM.mask And HDI_WIDTH) = HDI_WIDTH And tITEM.cxy = 27 Then
'WindowProc = 1
'Exit Function
'End If
End If
End Select
Case WM_DESTROY
'REMOVE SUBCLASSING WHEN LISTVIEW IS DESTROYED (FORM UNLOADED)
WindowProc = CallWindowProc(mlPrevWndProc, hwnd, Msg, wParam, lParam)
Call SetWindowLong(hwnd, GWL_WNDPROC, mlPrevWndProc)
Exit Function
End Select
'CALL DEFAULT WINDOW HANDLER
WindowProc = CallWindowProc(mlPrevWndProc, hwnd, Msg, wParam, lParam)
End Function
'-------------------------------------------------------------------------------
Public Sub SubClassHwnd(ByVal hwnd As Long)
mlPrevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
En zet onderstaande in de form_load:
SubClassHwnd ListView1.hwnd
-
Apr 17th, 2008, 03:35 PM
#30
New Member
Re: Preventing certain Listview columns from sizing...
I hope you can read/understand my dutch remarks, otherwise:
Put the first piece of code in the module
Put the second piece of code (SubClassHwnd ListView1.hwnd) in
the form_load of a form.
Catharinus van der Werf
[email protected]
Leeuwarden, The Netherlands
-
Apr 17th, 2008, 03:56 PM
#31
Re: Preventing certain Listview columns from sizing...
Please create a zip file from your project and attach it using the Manage Attachments function that you'll find below this window.
-
Mar 25th, 2010, 06:58 PM
#32
Re: Preventing certain Listview columns from sizing...
Here's my version of the code for locking the columnheaders. HDN_BEGINTRACK used in the examples above didn't work for me, so I had to change it to HDN_BEGINTRACKA (MSCC 6.0) and HDN_BEGINTRACKW (MSCC 5.0).
Unfortunately I still haven't found a way to hide the double-arrow cursor when moving over a locked column divider. WM_SETCURSOR doesn't 'fire' when the cursor is moved over a column divider.
::Edit::
An other 'problem' is that it's not possible to subclass more than one Listview at a time with the same code. You have to add multiple WindowProc with different names in order to do that. Although it's not a real problem, it would be easier to put the code in a Class and create a new instance for each Listview, but AddressOf only works for Modules and not Classes.
vb Code:
Option Explicit
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type HD_HITTESTINFO
PT As POINTAPI
flags As Long
iItem As Long
End Type
Private Const HHT_ONHEADER As Long = &H2
Private Const HHT_ONDIVIDER As Long = &H4
Private Const HDM_HITTEST As Long = &H1206
Private Const HDN_FIRST As Long = (-300)
Private Const HDN_BEGINTRACKW As Long = (HDN_FIRST - 26)
Private Const HDN_BEGINTRACKA As Long = (HDN_FIRST - 6)
Private Const HDN_DIVIDERDBLCLICKW As Long = (HDN_FIRST - 25)
Private Const HDN_DIVIDERDBLCLICKA As Long = (HDN_FIRST - 5)
' GetWindowsLong Constants
Private Const GWL_WNDPROC = (-4)
' Windows Message Constants
Private Const WM_NOTIFY = &H4E
Private Const WM_DESTROY = &H2
Private Const WM_SETCURSOR = &H20
' Notify Message Header Type
Private Type NMHDR
hWndFrom As Long
idFrom As Long
code As Long
End Type
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private 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
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function ScreenToClient Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private mlPrevWndProc As Long
Private Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim HitTestInfo As HD_HITTESTINFO
Dim PT As POINTAPI
Select Case Msg
Case WM_NOTIFY
Dim tNMH As NMHDR
' Copy the Notify Message Header to a Header Structure
CopyMemory tNMH, ByVal lParam, Len(tNMH)
Select Case tNMH.code
Case HDN_BEGINTRACKW, HDN_BEGINTRACKA, HDN_DIVIDERDBLCLICKW, HDN_DIVIDERDBLCLICKA
Call GetCursorPos(PT)
Call ScreenToClient(tNMH.hWndFrom, PT)
HitTestInfo.flags = HHT_ONHEADER Or HHT_ONDIVIDER
HitTestInfo.PT = PT
Call SendMessage(tNMH.hWndFrom, HDM_HITTEST, 0&, HitTestInfo)
' Lock column 1 (0) and column 2 (1)
If HitTestInfo.iItem = 0 Or HitTestInfo.iItem = 1 Then
Debug.Print "Sorry, I'm locked!"
WindowProc = 1
Exit Function
End If
Debug.Print "OK, you can move me."
End Select
Case WM_DESTROY
' Remove Subclassing when Listview is Destroyed (Form unloaded.)
WindowProc = CallWindowProc(mlPrevWndProc, hwnd, Msg, wParam, lParam)
Call SetWindowLong(hwnd, GWL_WNDPROC, mlPrevWndProc)
Exit Function
End Select
' Call Default Window Handler
WindowProc = CallWindowProc(mlPrevWndProc, hwnd, Msg, wParam, lParam)
End Function
Public Sub SubClassHwnd(ByVal hwnd As Long)
mlPrevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Last edited by Chris001; Mar 25th, 2010 at 07:17 PM.
-
May 11th, 2010, 07:04 AM
#33
Junior Member
Re: Preventing certain Listview columns from sizing...
there is a big problem with the column width version
if you resize a unlocked column to the specified size (0), it will become locked
i use a ParamArray to specify the column numbers so i can use it on all my forms
Code:
SubClassHwnd ListView1.hWnd, 7, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
Code:
Option Explicit
Option Base 0
' GetWindowsLong Constants
Private Const GWL_WNDPROC = (-4)
' Windows Message Constants
Private Const WM_NOTIFY = &H4E
Private Const WM_DESTROY = &H2
' Column Header Notification Meassage Constants
Private Const HDN_FIRST = -300&
Private Const HDN_DIVIDERDBLCLICKA = (HDN_FIRST - 5)
Private Const HDN_BEGINTRACK = (HDN_FIRST - 6)
' Column Header Item Info Message Constants
Private Const HDI_WIDTH = &H1
' Notify Message Header Type
Private Type NMHDR
hWndFrom As Long
idFrom As Long
code As Long
End Type
' Notify Message Header for Listview
Private Type NMHEADER
hdr As NMHDR
iItem As Long
iButton As Long
lPtrHDItem As Long ' HDITEM FAR* pItem
End Type
' Header Item Type
Private Type HDITEM
mask As Long
cxy As Long
pszText As Long
hbm As Long
cchTextMax As Long
fmt As Long
lParam As Long
iImage As Long
iOrder As Long
End Type
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private 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
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private mlPrevWndProc As Long, ColumnsBits As Long
Private Function WindowProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim tNMH As NMHDR
Dim tNMHEADER As NMHEADER
Dim tITEM As HDITEM
Select Case Msg
Case WM_NOTIFY
' Copy the Notify Message Header to a Header Structure
CopyMemory tNMH, ByVal lParam, Len(tNMH)
Select Case tNMH.code
Case HDN_DIVIDERDBLCLICKA
' If the user is trying to DOUBLECLICK a Column Header
' Extract Information about the Header being Sized
CopyMemory tNMHEADER, ByVal lParam, Len(tNMHEADER)
' Don't allow Columns to be Sized.
If (ColumnsBits And (2 ^ tNMHEADER.iItem)) = (2 ^ tNMHEADER.iItem) Then
WindowProc = 1
Exit Function
End If
Case HDN_BEGINTRACK
' If the user is trying to Size a Column Header
' Extract Information about the Header being Sized
CopyMemory tNMHEADER, ByVal lParam, Len(tNMHEADER)
' Don't allow Columns to be Sized.
If (ColumnsBits And (2 ^ tNMHEADER.iItem)) = (2 ^ tNMHEADER.iItem) Then
WindowProc = 1
Exit Function
End If
End Select
Case WM_DESTROY
' Remove Subclassing when Listview is Destroyed (Form unloaded)
WindowProc = CallWindowProc(mlPrevWndProc, hWnd, Msg, wParam, lParam)
Call SetWindowLong(hWnd, GWL_WNDPROC, mlPrevWndProc)
Exit Function
End Select
' Call Default Window Handler
WindowProc = CallWindowProc(mlPrevWndProc, hWnd, Msg, wParam, lParam)
End Function
Public Sub SubClassHwnd(ByVal hWnd As Long, ParamArray ColumnsNums())
Dim t As Integer
ColumnsBits = 0
For t = 0 To UBound(ColumnsNums)
ColumnsBits = ColumnsBits + (2 ^ (ColumnsNums(t) - 1))
Next t
mlPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
optionaly you can move all the hidden column to the left
Code:
ListView1.ColumnHeaders(7).Position = 1
Last edited by sergelac; May 11th, 2010 at 07:17 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|