Results 1 to 18 of 18

Thread: [VB6, Vista+] Undocumented ListView feature: Subsetted Groups (simple, no TLB)

Threaded View

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,667

    [VB6, Vista+] Undocumented ListView feature: Subsetted Groups (simple, no TLB)




    Compatibility: Like other modern features, this should work with API-created ListView's including krools, as well as the 5.0 Common Controls ListView in an IDE and/or compiled EXE manifested for the latest comctl32.dll version; and will almost certainly not work with the VB "Common Controls 6.0" ocx. Works with Windows Vista and higher.

    Subsetted groups allow you to show only a limited number of rows, and have a link at the bottom to show the hidden items. Works in any view where group view is supported (e.g. large icon and details, not list, etc). Not only is all the info needed to do it undocumented, but MSDN provides some of the constants then explicitly says it can't be done. Not sure what their deal is... I mean yeah there's some issues (see warning) but no reason they couldn't have fixed it between Vista and 10).
    So I had been converting this project to VB, and after I had already implemented the full IListView class, I went back and decided to try LVM_SETGROUPSUBSETCOUNT anyway, having originally thought the project author had tried that first since it was mentioned where he got the idea from. Lo and behold, it worked. So now you can subsetted groups with just a couple lines, and no TLB, no subclassing, nothing.


    Code:
    Public Const LVM_FIRST = &H1000
    Public Const LVM_SETGROUPSUBSETCOUNT = (LVM_FIRST + 190)
    Public Const LVM_GETGROUPSUBSETCOUNT = (LVM_FIRST + 191)
    
     'is included in standard group def despite MSDN saying not supported:
         LVGF_SUBSET = &H8000
         LVGS_SUBSETED = &H40
         LVGS_SUBSETLINKFOCUSED = &H80
    Now that you have your constants, when you're adding a group you want to be subsetted, add LVGF_SUBSET to .mask, and LVGS_SUBSETED to .State and .StateMask.
    Next add the subset link text,
    .pszSubsetTitle = StrPtr(sSubSetText)
    .cchSubsetTitle = Len(sSubSetText) + 1 'MSDN says this needs its own flag, but this combo of flags and properties works for both me and the codeproject sample

    Then, after the group has been added, to set the number of rows simply use:
    Call SendMessage(hLVS, LVM_SETGROUPSUBSETCOUNT, 0, ByVal 2&)
    where 2 can be anything, it's the number of rows you want. Note that in VB programs, all groups will have the link if one does, even without the style set. The link doesn't seem to go away, although in the c++ sample is does, so it might vary.

    And that's all it takes!

    WARNING:
    Note that this is an undocumented message, and as such has SERIOUS issues: MSDN explicitly says subset text cannot be set. They lied, but changing the variable holding it after running your program without restarting the IDE can cause damage your project, leading to crashes and having to re-enter control settings. If Group View is not enabled, or no groups are added, or no groups are marked as subsetted, the ListView window will lock up and nothing can be drawn to that area of the screen until the program is ended.


    Alternative Method: IListView
    This method was originally discovered by looking at the undocumented IListView interface. The LVM_SETGROUPSUBSETCOUNT message came later. So at first, this method was done in the following matter:
    Code:
    Public Const LVM_QUERYINTERFACE = (LVM_FIRST + 189)
    '-----
    
    Dim pILV As IListView
    
    Call SendMessage(hLVS, LVM_QUERYINTERFACE, VarPtr(IID_IListView), pILV)
    If (pILV Is Nothing) Then
        Debug.Print "Failed to get IListView interface"
        Exit Sub
    End If
    pILV.SetGroupSubsetCount nNumOfRows&
    And on Windows 7 and higher:
    Code:
    Public Function IID_IListView() As UUID
    '{E5B16AF2-3990-4681-A609-1F060CD14269}
    Static iid As UUID
     If (iid.Data1 = 0) Then Call DEFINE_UUID(iid, &HE5B16AF2, CInt(&H3990), CInt(&H4681), &HA6, &H9, &H1F, &H6, &HC, &HD1, &H42, &H69)
     IID_IListView = iid
    End Function
    On Windows Vista:
    Code:
    Public Function IID_IListView() As UUID
    '{2FFE2979-5928-4386-9CDB-8E1F15B72FB4}
    Static iid As UUID
     If (iid.Data1 = 0) Then Call DEFINE_UUID(iid, &H2FFE2979, CInt(&H5928), CInt(&H4386), &H9C, &HDB, &H8E, &H1F, &H15, &HB7, &H2F, &HB4)
     IID_IListView = iid
    End Function
    (this alternative method requires lvundoc.tlb; but the original method doesn't)
    Last edited by fafalone; Jun 26th, 2025 at 05:57 PM. Reason: Added link to Part 5

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