-
1 Attachment(s)
[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)
-
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
-
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.
-
Re: [VB6, Vista+] Undocumented ListView feature: Subsetted Groups (simple, no TLB)
I attached a zip file of the control.
-
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
-
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.
-
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
-
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!...:cool:
-
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.
-
Re: [VB6, Vista+] Undocumented ListView feature: Subsetted Groups (simple, no TLB)
Thanks, fafalone,
:confused: - 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!...:bigyello:
-
1 Attachment(s)
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.
-
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.
-
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.
-
Re: [VB6, Vista+] Undocumented ListView feature: Subsetted Groups (simple, no TLB)
faf,
Quote:
Originally Posted by
fafalone
...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 :bigyello:
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
-
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?
-
2 Attachment(s)
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
:confused:
-
Re: [VB6, Vista+] Undocumented ListView feature: Subsetted Groups (simple, no TLB)
Are those the fabled subitem controls? Or just inserting them manually?
-
Re: [VB6, Vista+] Undocumented ListView feature: Subsetted Groups (simple, no TLB)
Quote:
Originally Posted by
fafalone
Are those the fabled subitem controls? Or just inserting them manually?
No, :( drawn
LucasMKG