Results 1 to 33 of 33

Thread: Preventing certain Listview columns from sizing...

  1. #1

    Thread Starter
    Guru Aaron Young's Avatar
    Join Date
    Jun 1999
    Location
    Red Wing, MN, USA
    Posts
    2,177
    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:
    1. Option Explicit
    2.  
    3. ' GetWindowsLong Constants
    4. Private Const GWL_WNDPROC = (-4)
    5.  
    6. ' Windows Message Constants
    7. Private Const WM_NOTIFY = &H4E
    8. Private Const WM_DESTROY = &H2
    9.  
    10. ' Column Header Notification Meassage Constants
    11. Private Const HDN_FIRST = -300&
    12. Private Const HDN_BEGINTRACK = (HDN_FIRST - 6)
    13.  
    14. ' Column Header Item Info Message Constants
    15. Private Const HDI_WIDTH = &H1
    16.  
    17. ' Notify Message Header Type
    18. Private Type NMHDR
    19.    hWndFrom As Long
    20.    idFrom As Long
    21.    code As Long
    22. End Type
    23.  
    24. ' Notify Message Header for Listview
    25. Private Type NMHEADER
    26.      hdr As NMHDR
    27.      iItem As Long
    28.      iButton As Long
    29.      lPtrHDItem As Long ' HDITEM FAR* pItem
    30. End Type
    31.  
    32. ' Header Item Type
    33. Private Type HDITEM
    34.     mask As Long
    35.     cxy As Long
    36.     pszText As Long
    37.     hbm As Long
    38.     cchTextMax As Long
    39.     fmt As Long
    40.     lParam As Long
    41.     iImage As Long
    42.     iOrder As Long
    43. End Type
    44.  
    45. Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    46. 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
    47. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    48.  
    49. Private mlPrevWndProc As Long
    50.  
    51. Private Function WindowProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    52.     Dim tNMH As NMHDR
    53.     Dim tNMHEADER As NMHEADER
    54.     Dim tITEM As HDITEM
    55.    
    56.     Select Case Msg
    57.     Case WM_NOTIFY
    58.         ' Copy the Notify Message Header to a Header Structure
    59.         CopyMemory tNMH, ByVal lParam, Len(tNMH)
    60.        
    61.         Select Case tNMH.code
    62.         Case HDN_BEGINTRACK
    63.             ' If the user is trying to Size a Column Header...
    64.            
    65.             ' Extract Information about the Header being Sized
    66.             CopyMemory tNMHEADER, ByVal lParam, Len(tNMHEADER)
    67.            
    68.             ' Get Item Info. about the header (i.e. Width)
    69.             CopyMemory tITEM, ByVal tNMHEADER.lPtrHDItem, Len(tITEM)
    70.            
    71.             ' Don't allow Zero Width Columns to be Sized.
    72.             If (tITEM.mask And HDI_WIDTH) = HDI_WIDTH And tITEM.cxy = 0 Then
    73.                 WindowProc = 1
    74.                 Exit Function
    75.             End If
    76.         End Select
    77.        
    78.     Case WM_DESTROY
    79.         ' Remove Subclassing when Listview is Destroyed (Form unloaded.)
    80.         WindowProc = CallWindowProc(mlPrevWndProc, hWnd, Msg, wParam, lParam)
    81.         Call SetWindowLong(hWnd, GWL_WNDPROC, mlPrevWndProc)
    82.         Exit Function
    83.          
    84.     End Select
    85.  
    86.     ' Call Default Window Handler
    87.     WindowProc = CallWindowProc(mlPrevWndProc, hWnd, Msg, wParam, lParam)
    88. End Function
    89.  
    90. Public Sub SubClassHwnd(ByVal hWnd As Long)
    91.     mlPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
    92. End Sub
    In Form with ListView:
    VB Code:
    1. Option Explicit
    2.  
    3. Private Sub Form_Load()
    4.     Dim lIndex As Long
    5.    
    6.     SubClassHwnd ListView1.hWnd
    7.    
    8.     With ListView1
    9.         .View = lvwReport
    10.         For lIndex = 1 To 5
    11.             .ColumnHeaders.Add , "COL" & lIndex, "Column " & lIndex, IIf(lIndex = 3, 0, (.Width - 200) / 4)
    12.         Next
    13.     End With
    14.  
    15. End Sub

  2. #2
    The Devil crptcblade's Avatar
    Join Date
    Aug 2000
    Location
    Quetzalshacatenango
    Posts
    9,091
    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

  3. #3
    PowerPoster rjlohan's Avatar
    Join Date
    Sep 2001
    Location
    Sydney, Australia
    Posts
    3,205
    Nice one!
    :thumbsup:

    -----------------------------------------
    -RJ
    [email protected]
    -----------------------------------------

  4. #4

  5. #5
    The Devil crptcblade's Avatar
    Join Date
    Aug 2000
    Location
    Quetzalshacatenango
    Posts
    9,091
    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

  6. #6
    Next Of Kin baja_yu's Avatar
    Join Date
    Aug 2002
    Location
    /dev/root
    Posts
    5,989
    Can this be modified to prevent resize of non zero width columns? Like some other fixed value...

  7. #7
    So Unbanned DiGiTaIErRoR's Avatar
    Join Date
    Apr 1999
    Location
    /dev/null
    Posts
    4,111
    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.

  8. #8
    The Devil crptcblade's Avatar
    Join Date
    Aug 2000
    Location
    Quetzalshacatenango
    Posts
    9,091
    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:
    1. ' Don't allow Zero Width Columns to be Sized.
    2.             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

  9. #9
    Next Of Kin baja_yu's Avatar
    Join Date
    Aug 2002
    Location
    /dev/root
    Posts
    5,989
    Originally posted by crptcblade
    Yes
    VB Code:
    1. ' Don't allow Zero Width Columns to be Sized.
    2.             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...

  10. #10

  11. #11
    Next Of Kin baja_yu's Avatar
    Join Date
    Aug 2002
    Location
    /dev/root
    Posts
    5,989
    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....

  12. #12
    Former Admin/Moderator MartinLiss's Avatar
    Join Date
    Sep 1999
    Location
    San Jose, CA
    Posts
    33,431
    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.

  13. #13
    Next Of Kin baja_yu's Avatar
    Join Date
    Aug 2002
    Location
    /dev/root
    Posts
    5,989
    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..

  14. #14
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,709
    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:
    1. Private Function WindowProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    2.    
    3.     Dim tNMH As NMHDR
    4.     Dim tNMHEADER As NMHEADER
    5.     Dim tITEM As HDITEM
    6.    
    7.     Select Case Msg
    8.         Case WM_NOTIFY
    9.             ' COPY THE NOTIFY MESSAGE HEADER TO A HEADER STRUCTURE
    10.             CopyMemory tNMH, ByVal lParam, Len(tNMH)
    11.             Select Case tNMH.code
    12.                 Case HDN_DIVIDERDBLCLICKA
    13.                     'IF THE USER IS TRYING TO DOUBLECLICK A COLUMN HEADER...
    14.                     'EXTRACT INFORMATION ABOUT THE HEADER BEING SIZED
    15.                     CopyMemory tNMHEADER, ByVal lParam, Len(tNMHEADER)
    16.                     'GET THE INFO ABOUT THE HEADER (IE. INDEX#)
    17.                     'DONT ALLOW COLUMNS 1 OR 2 TO BE DOUBLECLICKED
    18.                     If (tNMHEADER.iItem < 3) = True Then
    19.                         WindowProc = 1
    20.                         Exit Function
    21.                     ElseIf (tNMHEADER.iItem = 5) = True Then 'DURATION
    22.                         WindowProc = 1
    23.                         Exit Function
    24.                     End If
    25.                 Case HDN_BEGINTRACK
    26.                     'IF THE USER IS TRYING TO SIZE A COLUMN HEADER...
    27.                     'EXTRACT INFORMATION ABOUT THE HEADER BEING SIZED
    28.                     CopyMemory tNMHEADER, ByVal lParam, Len(tNMHEADER)
    29.                     'GET THE INFO ABOUT THE HEADER (IE. WIDTH)
    30.                     CopyMemory tITEM, ByVal tNMHEADER.lPtrHDItem, Len(tITEM)
    31.                     'DONT ALLOW ZERO OR COLUMNS 1 OR 2 TO BE SIZED
    32.                     If (tNMHEADER.iItem < 3) = True Then 'TYPE & STATUS
    33.                         WindowProc = 1
    34.                         Exit Function
    35.                     ElseIf (tNMHEADER.iItem = 5) = True Then 'DURATION
    36.                         'If (tITEM.mask And HDI_WIDTH) = HDI_WIDTH And tITEM.cxy = 27 Then
    37.                             WindowProc = 1
    38.                             Exit Function
    39.                         'End If
    40.                     End If
    41.             End Select
    42.         Case WM_DESTROY
    43.             'REMOVE SUBCLASSING WHEN LISTVIEW IS DESTROYED (FORM UNLOADED)
    44.             WindowProc = CallWindowProc(mlPrevWndProc, hWnd, Msg, wParam, lParam)
    45.             Call SetWindowLong(hWnd, GWL_WNDPROC, mlPrevWndProc)
    46.             Exit Function
    47.     End Select
    48.     'CALL DEFAULT WINDOW HANDLER
    49.     WindowProc = CallWindowProc(mlPrevWndProc, hWnd, Msg, wParam, lParam)
    50.    
    51. 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 PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI 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

  15. #15
    Next Of Kin baja_yu's Avatar
    Join Date
    Aug 2002
    Location
    /dev/root
    Posts
    5,989
    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.

  16. #16
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,709
    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:
    1. 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 PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI 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

  17. #17
    Next Of Kin baja_yu's Avatar
    Join Date
    Aug 2002
    Location
    /dev/root
    Posts
    5,989
    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...

  18. #18
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,709
    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:
    1. 'If (tITEM.mask And HDI_WIDTH) = HDI_WIDTH And tITEM.cxy = 27 Then
    2.     WindowProc = 1
    3.     Exit Function
    4. '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 PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI 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

  19. #19
    Next Of Kin baja_yu's Avatar
    Join Date
    Aug 2002
    Location
    /dev/root
    Posts
    5,989
    Didn't see that, sorry

    Anyway, it works more than great. Thumbs up to all

    Thanks for the help.

  20. #20
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,709
    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 PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI 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

  21. #21
    Fanatic Member InvisibleDuncan's Avatar
    Join Date
    May 2001
    Location
    Eating jam.
    Posts
    819
    Now all we need is a VB.Net version.
    Indecisiveness is the key to flexibility.

    www.mangojacks.com

  22. #22
    Hyperactive Member
    Join Date
    Dec 1999
    Posts
    321

    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

  23. #23
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,709

    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 PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI 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

  24. #24
    Frenzied Member
    Join Date
    Oct 2000
    Posts
    1,463

    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!

  25. #25

  26. #26
    Frenzied Member
    Join Date
    Oct 2000
    Posts
    1,463

    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

  27. #27
    New Member
    Join Date
    Jul 2006
    Posts
    12

    Red face 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

  28. #28

  29. #29
    New Member
    Join Date
    Jul 2006
    Posts
    12

    Wink 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

  30. #30
    New Member
    Join Date
    Jul 2006
    Posts
    12

    Smile 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

  31. #31

  32. #32
    Frenzied Member
    Join Date
    Nov 2005
    Posts
    1,834

    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:
    1. Option Explicit
    2.  
    3. Private Type POINTAPI
    4.   x             As Long
    5.   y             As Long
    6. End Type
    7.  
    8. Private Type HD_HITTESTINFO
    9.   PT            As POINTAPI
    10.   flags         As Long
    11.   iItem         As Long
    12. End Type
    13.  
    14. Private Const HHT_ONHEADER          As Long = &H2
    15. Private Const HHT_ONDIVIDER         As Long = &H4
    16. Private Const HDM_HITTEST           As Long = &H1206
    17.  
    18. Private Const HDN_FIRST             As Long = (-300)
    19. Private Const HDN_BEGINTRACKW       As Long = (HDN_FIRST - 26)
    20. Private Const HDN_BEGINTRACKA       As Long = (HDN_FIRST - 6)
    21. Private Const HDN_DIVIDERDBLCLICKW  As Long = (HDN_FIRST - 25)
    22. Private Const HDN_DIVIDERDBLCLICKA  As Long = (HDN_FIRST - 5)
    23.  
    24. ' GetWindowsLong Constants
    25. Private Const GWL_WNDPROC = (-4)
    26.  
    27. ' Windows Message Constants
    28. Private Const WM_NOTIFY = &H4E
    29. Private Const WM_DESTROY = &H2
    30. Private Const WM_SETCURSOR = &H20
    31.  
    32. ' Notify Message Header Type
    33. Private Type NMHDR
    34.    hWndFrom As Long
    35.    idFrom As Long
    36.    code As Long
    37. End Type
    38.  
    39. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    40. 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
    41. Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    42. 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
    43. Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    44. Private Declare Function ScreenToClient Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
    45.  
    46. Private mlPrevWndProc As Long
    47.  
    48. Private Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    49.     Dim HitTestInfo     As HD_HITTESTINFO
    50.     Dim PT              As POINTAPI
    51.    
    52.     Select Case Msg
    53.     Case WM_NOTIFY
    54.         Dim tNMH As NMHDR
    55.        
    56.         ' Copy the Notify Message Header to a Header Structure
    57.         CopyMemory tNMH, ByVal lParam, Len(tNMH)
    58.        
    59.         Select Case tNMH.code
    60.         Case HDN_BEGINTRACKW, HDN_BEGINTRACKA, HDN_DIVIDERDBLCLICKW, HDN_DIVIDERDBLCLICKA
    61.            
    62.             Call GetCursorPos(PT)
    63.             Call ScreenToClient(tNMH.hWndFrom, PT)
    64.            
    65.             HitTestInfo.flags = HHT_ONHEADER Or HHT_ONDIVIDER
    66.             HitTestInfo.PT = PT
    67.  
    68.             Call SendMessage(tNMH.hWndFrom, HDM_HITTEST, 0&, HitTestInfo)
    69.  
    70.             ' Lock column 1 (0) and column 2 (1)
    71.             If HitTestInfo.iItem = 0 Or HitTestInfo.iItem = 1 Then
    72.                 Debug.Print "Sorry, I'm locked!"
    73.                 WindowProc = 1
    74.                 Exit Function
    75.             End If
    76.            
    77.             Debug.Print "OK, you can move me."
    78.         End Select
    79.        
    80.     Case WM_DESTROY
    81.         ' Remove Subclassing when Listview is Destroyed (Form unloaded.)
    82.         WindowProc = CallWindowProc(mlPrevWndProc, hwnd, Msg, wParam, lParam)
    83.         Call SetWindowLong(hwnd, GWL_WNDPROC, mlPrevWndProc)
    84.         Exit Function
    85.          
    86.     End Select
    87.  
    88.     ' Call Default Window Handler
    89.     WindowProc = CallWindowProc(mlPrevWndProc, hwnd, Msg, wParam, lParam)
    90. End Function
    91.  
    92. Public Sub SubClassHwnd(ByVal hwnd As Long)
    93.     mlPrevWndProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
    94. End Sub
    Last edited by Chris001; Mar 25th, 2010 at 07:17 PM.

  33. #33
    Junior Member
    Join Date
    Jun 2005
    Posts
    18

    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
  •  



Click Here to Expand Forum to Full Width