Results 1 to 18 of 18

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

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,652

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

    Name:  lvsubset.jpg
Views: 503
Size:  25.7 KB

    Undocumented ListView Features : Part 2 - Subsetted Groups
    See Also: Part 1 - Footer Items | Part 3 - Groups With Virtual Mode | Part 4 - Column Backcolor | Part 5 - Explorer-style selection



    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; Jan 25th, 2022 at 01:21 AM. Reason: Added link to Part 5

  2. #2
    Hyperactive Member LucasMKG's Avatar
    Join Date
    Jun 2015
    Location
    South Africa (ZAR)
    Posts
    338

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

    Hi fafalone,

    Cool stuff

    I want to integrate that feature in vhGrid, since its listview based. I will appreciate your help in that regard.

    In ZAR and still VB6 all the way.
    LucasMKG

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,652

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

    Not too familiar with the control... but what exactly does "listview based" mean?

    If it's built on top of a real listview control, then you should be able to get the ListView's hWnd. If it's not... I would seriously doubt it would have the same undocumented features built in, especially something added in Vista.

    Edit: The only place I see to DL it is planet source code, which seems to be down. Can you send me an alternate link, or the control itself?

    Also be aware, this is for Group View only. It doesn't work in standard views. So actually, if you've already got groups working I'd imagine this would be supported too.
    Last edited by fafalone; Jun 19th, 2015 at 01:43 PM.

  4. #4
    Hyperactive Member LucasMKG's Avatar
    Join Date
    Jun 2015
    Location
    South Africa (ZAR)
    Posts
    338

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

    I attached a zip file of the control.

  5. #5
    Hyperactive Member LucasMKG's Avatar
    Join Date
    Jun 2015
    Location
    South Africa (ZAR)
    Posts
    338

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

    Hi fafalone,

    I'm not sure if this message and attachment will go through. In case it goes through, pls receive the vhGrid control Im referring to.

    LucasMKG
    still on vb6...still rolling

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,652

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

    Wow that's an insanely complex control.. but no it doesn't support subsetting groups, because it doesn't use group view in any of its modes (the LVM_ messages and LVGROUP structure aren't even declared). Not to mention it looks like absolutely everything is owner-drawn. If you wanted to do it, it would have to be completely from scratch. Even if you added group view support, a challenge on its own, I don't know that the owner-draw code wouldn't override subsetting.
    If you really think its worthwhile, read up on ListView Group API, look at existing group view code. Minus the owner-draw issue, the listview is API-created and the ucVHGrid.hWnd is the ListView hWnd that you would send the messages to (LVM_INSERTGROUP, LVM_ENABLEGROUPVIEW, LVM_SETGROUPSUBSETCOUNT, etc).
    -Enable group view
    -add groups
    -when items are inserted their groupid must be set
    -set subset count


    Edit: Sorry, the situation is far worse than I thought. It doesn't even use items. The "items" aren't even listitems, the exist entirely as manually-drawn custom objects. Regular ListView items are LVITEM structures added through LVM_INSERTITEM; neither of those exist in this control. So the only practical way to add subsetting would be manually drawing the text and link after adding a given number of items, then adding the rest on click. But there's absolutely nothing that would handle that even partially for you, it would have to be drawn from scratch with APIs like DrawText.
    Last edited by fafalone; Jun 22nd, 2015 at 05:20 PM.

  7. #7
    Hyperactive Member LucasMKG's Avatar
    Join Date
    Jun 2015
    Location
    South Africa (ZAR)
    Posts
    338

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

    fafalone,

    Thanks for the reply.

    The control is complex i agree, but the only feature i was hoping to add was grouping/or node_to_cell (multicolumn treeview) then it will be complete. I was working on importing the vbAccelerator ListView Control [group feature] but its complex coding...but i won't give-up.

    I twiked LynxGrid and added many features including node_to_cell (sourced from flexcell grid), but it was too rigid...i wasn't happy with its limitations...so i abandoned it for vhGrid

    I respect you work(coding)...If I was fluent with VB as you are, I would be extremely happy'

    LucasMKG
    still on vb6...still pushing hard

  8. #8
    Hyperactive Member LucasMKG's Avatar
    Join Date
    Jun 2015
    Location
    South Africa (ZAR)
    Posts
    338

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

    fafalone,

    I managed to add Groups feature (incl. lvitem) to vhGrid but somehow it doesn't work. pls check and advice of where I went wrong.

    I based the Groups feature on <ucListViewEx_V2.5_ori.zip> as mention in the vhGrid thread I started.

    The form that should initiate the groups on <vhGrid is frmUnicode.frm>

    LucasMKG
    Still loving VB6...Yeah!...

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,652

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

    The issue that jumps out first is that the listview is created with LVS_OWNERDATA (full virtual mode), that can't easily be used with group mode.

  10. #10
    Hyperactive Member LucasMKG's Avatar
    Join Date
    Jun 2015
    Location
    South Africa (ZAR)
    Posts
    338

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

    Thanks, fafalone,

    - What is required for LVS_OWNERDATA to use groups?

    I really need Groups feature or MultiColumn_Treeview...either one will do. I struggling to incorporate into vhGrid - vbAccelerator's MultiColumn_Treeview (or find a simplified version thereof).

    LucasMKG
    VB6 lives on!...

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,652

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

    I'll take a look at multi column TreeView later on, but there's almost certainly an easier way than vbAccelerators.

    How many list items do you plan on having? Unless it's in the 100,000 or more range you could manage without virtual mode, which is by far the easier route - just remove the style, add the item with its data like normal, and remove code responding to LVM_GETDISPINFO (might not be there if it's owner drawn).
    If you want group mode with virtual mode, you have to implement IOwnerDataCallback, then use LVM_SETOWNERDATACALLBACK (untested) or LVM_QUERYINTERFACE for IListView.SetOwnerDataCallback (untested in VB). All undocumented stuff here.

    If you did want to go down that road, I have written VB-compatible interfaces for IListView and IOwnerDataCallback. Attached below is the current progress of my complete undocumented ListView set, it's released yet because it's not complete, but contains what you'd need for this.
    Attached Files Attached Files
    Last edited by fafalone; Jul 9th, 2015 at 09:05 AM.

  12. #12
    Hyperactive Member LucasMKG's Avatar
    Join Date
    Jun 2015
    Location
    South Africa (ZAR)
    Posts
    338

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

    fafalone,

    Thanks, but I'm unable to view your attachments...(which program should I use to view such files).

    I'll be waiting for your input on the integration of Multi-Column_Treeview into vhGrid...since lvGroups with LVS_OWNERDATA is getting too complicated for me.

    I appreciate your effort.

    LucasMKG
    VB6...my language.

  13. #13

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,652

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

    You add the .tlb as a reference in VB. The other files are just the source code, and are plain text viewable in any text editor.

  14. #14
    Hyperactive Member LucasMKG's Avatar
    Join Date
    Jun 2015
    Location
    South Africa (ZAR)
    Posts
    338

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

    faf,

    Quote Originally Posted by fafalone View Post
    ...The link doesn't seem to go away, although in the c++ sample is does, so it might vary.
    It doesn't matter, we could toggle between "show all entries" and "minimize again"

    WARNING: solution untidy but somehow works

    In the Subclass_WndProc:
    Code:
        Case WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_MOUSEMOVE
            iBtn = GetMouseButtonState(uMsg)                                            'Seal.added.native ©John Underhill(Steppenwolfe) : vhGrid-clsTreeView : ButtonState - changed to GetMouseButtonState
            iShift = ShiftState()                                                       'Seal.added.based on ©UniListView (Dana Seaman - www.cyberactivex.com)
            GetClientCursorPos m_lHGHwnd, lXPos, lYPos                                  'Seal.added.native ©John Underhill(Steppenwolfe) : vhGrid-clsTreeView
            Select Case uMsg
    
    
                Case WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP
                    Select Case uMsg
                        Case WM_LBUTTONUP       '/* release transition mask
                            If (lHwnd = m_lParentHwnd) Then
                                If m_bHasTreeView Then
                                    If TreeViewDividerHitTest Then
                                        m_cTreeView.Refresh True
                                        If Not (m_eGridMode = eVhGrid Or m_eGridMode = eVhGrid_TreeGrid) Then DrawSizer UserControl.hdc                      'Seal.modified
                                    End If
                                End If
                            Else
    'Nowbuffer
                                If m_bColumnSizingVertical Then ColumnSizingVertical = False        'Seal.added : [If m_bColumnSizingVertical Then]
                                ColumnHeaderDragStop
                                If m_bTransitionMask Then
                                    DestroyTransitionMask
                                End If
                            End If
    
    'GroupView ...................
                        'Seal.added: based on © 2016 ©VBForums (Jonney) - Thread '[RESOLVED] LVN_LINKCLICK inhibited by WM_LBUTTONDOWN'
                        If GroupView Then
            
                            GetCursorPos tPnt
                            ScreenToClient m_lHGHwnd, tPnt
                            
                            With uLVHI
                                .pt.x = tPnt.x
                                .pt.y = tPnt.y
                
                                Call SendMessage(m_lHGHwnd, LVM_HITTEST, -1, VarPtr(uLVHI))
        
                                Select Case .flags
                                  '/  Case LVHT_EX_GROUP_HEADER
                                  '/      bHandled = False   '/* Bypass default behavior
                                  '/      MsgBox "LVHT_EX_GROUP_HEADER"
                                    Case LVHT_EX_GROUP_FOOTER                            '.works
                                        MsgBox "LVHT_EX_GROUP_FOOTER "
                                    Case LVHT_EX_GROUP_COLLAPSE
                                        MsgBox "LVHT_EX_GROUP_COLLAPSE "
                                    Case LVHT_EX_GROUP_BACKGROUND
                                        MsgBox "LVHT_EX_GROUP_BACKGROUND "
                                    Case LVHT_EX_GROUP_STATEICON                            '.works
                                        MsgBox "LVHT_EX_GROUP_STATEICON "
                                  '/  Case LVHT_EX_GROUP_SUBTITLE
                                  '/      MsgBox "LVHT_EX_GROUP_SUBTITLE "
                                    Case LVHT_EX_GROUP_SUBSETLINK                            '.works
                                    'Seal.added: SubsetLink | toggle "Show all entries" & "minimise again..."
                                        Dim bGroupSubseted As Boolean
                                        
                                        bGroupSubseted = FGroupSubseted(.iGroup)
                                        mFGroupSubseted .iGroup, bGroupSubseted
                                        
                                    Case LVHT_EX_GROUP
                                        MsgBox "LVHT_EX_GROUP "
                                    Case LVHT_EX_ONCONTENTS                    'On item AND not on the background
                                        MsgBox "LVHT_EX_ONCONTENTS "
                                    Case LVHT_EX_FOOTER                            '.works
                                        MsgBox "LVHT_EX_FOOTER "
                                    Case LVHT_EX_GROUP
                                        MsgBox "LVHT_EX_GROUP "
                                    Case Else
                                  '/      MsgBox "Case Else: " & .flags
                                End Select
                            End With
                        End If
    'GroupView ...................
    
                            'Seal.added :: to set SubItem FocusRect
                            If (m_eGridMode = eLVS_Report) And CellInFocus > 0 Then SubItemSelected
                            RaiseEvent MouseUp(iBtn, iShift, CSng(lXPos), CSng(lYPos))     'Seal.added.native ©John Underhill(Steppenwolfe) : vhGrid-clsTreeView
    'Debug.Print "WM_LBUTTONUP"
                        Case WM_MBUTTONUP
                            RaiseEvent MouseUp(iBtn, iShift, CSng(lXPos), CSng(lYPos))     'Seal.added.native ©John Underhill(Steppenwolfe) : vhGrid-clsTreeView
    'Debug.Print "WM_MBUTTONUP"
                        Case WM_RBUTTONUP
                            RaiseEvent MouseUp(iBtn, iShift, CSng(lXPos), CSng(lYPos))     'Seal.added.native ©John Underhill(Steppenwolfe) : vhGrid-clsTreeView
    'Debug.Print "WM_RBUTTONUP"
                    End Select
                    If bIsClick = True Then
                        bIsClick = False
                        If (lXPos >= 0 And lXPos <= UserControl.Width) _
                        And (lYPos >= 0 And lYPos <= UserControl.Height) Then _
                            RaiseEvent Click
                    End If

    Code:
    Function mFGroupSubseted(ByVal iGrpId As Long, ByVal bSubseted As Boolean)
        If Not (m_lHGHwnd = 0) Then
            Dim sSubsetLink As String
            Dim LVG As LVGROUP
    
            With LVG
                '*/ returns or sets the subsettitle link of the group
                If bSubseted Then
                    sSubsetLink = "minimise again..."
                Else
                    sSubsetLink = "Show all entries "
                End If
    
                .cbSize = LenB(LVG)
                .stateMask = .stateMask Or LVGS_SUBSETED
                .Mask = .Mask Or LVGF_STATE Or LVGF_SUBSET
                .pszSubsetTitle = StrPtr(sSubsetLink)
                .cchSubsetTitle = LenB(sSubsetLink)
    
                .State = IIf(bSubseted = False, LVGS_SUBSETED, LVGS_NORMAL)
                '*/ when TRUE the group displays only a portion of its items _
                 A value of 0 indicates that all list items are displayed, which means no subset. _
                 Requires comctl32.dll version 6.1 or higher."
    
                SendMessage m_lHGHwnd, LVM_SETGROUPINFO, iGrpId, VarPtr(LVG)
            End With
        End If
    
    End Function

    ommited
    Code:
    'Seal.added.based on ©Krool : CommonControls (Replacement of the MS common controls)
    Property Get FGroupSubseted(ByVal iGrpId As Long) As Boolean
    'If ListViewHandle <> 0 And ComCtlsSupportLevel() >= 2 Then
    '    If IsGroupAvailable(ID) = True Then
    'FGroupSubseted = CBool(SendMessage(m_lHGHwnd, LVM_GETGROUPSTATE, iGrpId, ByVal LVGS_SUBSETED) <> 0)
    FGroupSubseted = CBool(SendMessage(m_lHGHwnd, LVM_GETGROUPSTATE, iGrpId, ByVal LVGS_SUBSETED) <> 0)
    'End If
    End Property
    LucasMKG
    trying to make a comeback...revising
    Last edited by LucasMKG; Feb 21st, 2022 at 03:38 AM.

  15. #15

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,652

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

    Does LVHT_EX_GROUP_SUBSETLINK not respond to clicks on the task link? That doesn't seem to have a separate LVHT_ item. It's the only thing that generates an LVN_LINKCLICK.

    And applying the style again re-subsets the group? Does the link still permanently disappear on the 2nd expansion?

  16. #16
    Hyperactive Member LucasMKG's Avatar
    Join Date
    Jun 2015
    Location
    South Africa (ZAR)
    Posts
    338

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

    a) LVHT_EX_GROUP_SUBSETLINK respond to clicks

    b) "...That doesn't seem to have a separate LVHT_ item", not sure i understand the second question, but
    Call SendMessage(m_lHGHwnd, LVM_HITTEST, -1, VarPtr(uLVHI))
    provides .iItem

    c) "...applying the style again re-subsets the group?"
    YES

    d) "...Does the link still permanently disappear on the 2nd expansion?"
    the link appearance is constant - only toggles from 'show all'[while list is contracted] and 'minimize' [appears while list is expanded]

    LucasMKG
    Attached Images Attached Images   
    Last edited by LucasMKG; Feb 6th, 2022 at 09:45 AM.

  17. #17

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,652

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

    Are those the fabled subitem controls? Or just inserting them manually?

  18. #18
    Hyperactive Member LucasMKG's Avatar
    Join Date
    Jun 2015
    Location
    South Africa (ZAR)
    Posts
    338

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

    Quote Originally Posted by fafalone View Post
    Are those the fabled subitem controls? Or just inserting them manually?
    No, drawn

    LucasMKG

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