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
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.
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.
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'
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).
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.
Last edited by fafalone; Jul 9th, 2015 at 09:05 AM.
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.
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
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?
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
Last edited by LucasMKG; Feb 6th, 2022 at 09:45 AM.