Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

LV_Group() - ListView Groups or "show in groups"


  • Please log in to reply
42 replies to this topic
gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
hey all, simple function here to enable grouping in ListViews... i didn't want (or have the ability to) wrap all the features of LVM_'s, but here's one:

LV_Group() v0.04 updated 2012/02/18

notes: should be stdlib compliant, only tested in _Basic, and unicode surely won't work as-is, may add features as i use it (header click re-grouping comes to mind), won't handle multiple LV's as is but will be fixed

Posted Image

Simple Example (run in a folder with some files around):
#SingleInstance, Force
#NoEnv
SetWorkingDir, %A_ScriptDir%
 Gui Add, ListView, w400 r30 gLVAction,Filename|Ext|Size [mb]
 LV_ModifyCol(1,250)
 LV_ModifyCol(2,60)
 LV_ModifyCol(3,"60 Integer")
 Loop, *.*
 {
  SplitPath A_LoopFileName,,,,NameWithoutExt
  Row:=LV_Add(""" " . DefaultCheck . " """,NameWithoutExt,A_LoopFileExt,Round(A_LoopFileSize/1024/1024))
  LV_Group(Row,A_LoopFileExt)
 }
 Gui Show,,Group View Test
Return

LVAction:
If (A_GuiEvent = "ColClick")
{
 LV_Group("Delete")
 Loop, % LV_GetCount()
 {
  LV_GetText(_,A_Index,A_EventInfo) ;get text of clicked column as group to put it in
  LV_Group(A_Index,_) ;row, group, and hwnd of list view
 }
}
Return ; a little buggy on the size column for some reason

GuiClose:
GuiEscape:
ExitApp
Function:
;——————————————————————————————————————————————————————
;————————      LV_Group() 0.04 by gwarble 2012 ————————
;—————                                            —————
;———      listview groups, or "show in groups"      ———
;——    https://ahknet.autohotkey.com/~gwarble/LV_Group/  ——
;——————————————————————————————————————————————————————
;
; LV_Group([RowOrCommand, GroupName, ListViewHWnd])
;
; RowOrCommand  Row number to add to group, or 0 or "" to just add a group
;               or Command to:
;                   "Enable"  enable Group viewing
;                             (rows not assigned to groups will be hidden)
;                   "Disable" turn grouping off and revert to Report view
;                   "Toggle"  toggle above options
;                   "Delete"  turn off group view and delete all groups
;                   not yet implemented: delete groups, lots of LVM_'s, sortable by header, etc
;
; GroupName     Name of group in which to add row
;               or adds a group name without assigning a row if above=0 or ""
;               in that case, multiple groups can be added as "Group1|Group2|..."
;           
; ListViewHwnd  hWnd of ListView control to work on... (listview option hwndListViewHwnd)
;               will be remembered, so only needs to be used once if only using one LV
;               not yet implemented: work on default LV when ""
;
; Return        not sure what would be most useful
;               0 on error
;               Group Number on success? group name?
;——————————————————————————————————————————————————————


LV_Group(Row, Group="`n", hWnd="")
{
 static hWnd_, GroupCount, UnicodeHeader, Grouped
 static GroupList := "`n"

 hWnd_ := hWnd<>"" ? hWnd : hWnd_<>"" ? hWnd_ : "Default"

 If (hWnd_ = "Default")
 { ; PreviousLFWhwnd := WinExist() ; store for restoring after this
  Gui,+LastFound  ; use default gui if no hwnd specified
  ControlGet,hWnd_,hWnd,,SysListView321 ; and save the hwnd so we don't have to find it again
 } ; IfWinExist, ahk_id %PreviousLFWhwnd% ; save and restore LastFound window? 

 If (Row = "Enable")
 {
  SendMessage 0x109d,1,0,,ahk_id %hWnd_% ; LVM_ENABLEGROUPVIEW = 0x109d, l=1 to enable
  Grouped=1
 }
 Else If (Row = "Disable")
 {
  SendMessage 0x109d,0,0,,ahk_id %hWnd_% ; LVM_ENABLEGROUPVIEW = 0x109d, l=0 to disable
  Grouped=
 }
 Else If (Row = "Return")
 { ;return a variables contents via: LV_Group("Return","GroupList") returns `n delimited list
  Return % %Group%
 }
 Else If (Row="Toggle")
 {
  If Grouped
   SendMessage 0x109d,0,0,,ahk_id %hWnd_% ; LVM_ENABLEGROUPVIEW = 0x109d, l=0 to disable
  Else
   SendMessage 0x109d,1,0,,ahk_id %hWnd_% ; LVM_ENABLEGROUPVIEW = 0x109d, l=1 to enable
  Grouped := !Grouped
 }
 Else If (Row="Delete") ; still need support to delete a group or unassign a row
 {
  SendMessage 0x10A0,0,0,,ahk_id %hWnd_% ; LVM_REMOVEALLGROUPS = 0x10A0
  SendMessage 0x109d,0,0,,ahk_id %hWnd_% ; LVM_ENABLEGROUPVIEW = 0x109d, l=0 to disable
  Grouped:=GroupCount:="", GroupList:="`n" ; hwnd is still saved
 }
; Else If (Group="`n") AND (hWnd="")
;  hWnd_ := hWnd := Row
 Else ; assuming an actual call and not a Command...
 {
  If !InStr(GroupList, "`n" Group "`n")
  {
   GroupList .= Group "`n"
   GroupCount++
   If UnicodeHeader =
    VarSetCapacity(UnicodeHeader,100)
   Group%GroupCount%_:=Group
   VarSetCapacity(          Group%GroupCount%, 96, 0)
   NumPut(96,              &Group%GroupCount%, 0,"Int")            ; LVGROUP_CbSize    = 0
   NumPut(0x11,            &Group%GroupCount%, 4,"Int")            ; LVGROUP_Mask      = 4 ; LVGF_HEADER (flag 0x1) + LVGF_GROUPID (flag 0x10)??
   DllCall("MultiByteToWideChar","UINT",0,"UINT",0,"UINT",&Group%GroupCount%_,"INT",-1,"UINT",&UnicodeHeader,"INT",strlen(Group%GroupCount%_)+1)
   NumPut(&UnicodeHeader,  &Group%GroupCount%, 8,"Int")            ; LVGROUP_PszHeader = 8
   NumPut(GroupCount-1,    &Group%GroupCount%, 24,"Int")           ; LVGROUP_IGroupId  = 24
   SendMessage 0x1091, -1, &Group%GroupCount%,, ahk_id %hWnd_%     ; LVM_INSERTGROUP = 0x1091
  }
  If Row < 1 ;is not integer for LV_Group(0,"Group") to add group without assigning??
   Return 1 ; successfully added group... not assigning any rows though

  StringTrimLeft, GroupList_, GroupList, 1
  StringTrimRight, GroupList_, GroupList_, 1
  StringSplit, Groups, GroupList_, `n

  Loop, %Groups0%
   If (Groups%A_Index% = Group)
    GroupNum:=A_Index
  VarSetCapacity(          Group%Row%, 64,   0  )
  NumPut(0x100,           &Group%Row%, 0,  "Int")                  ; LVIF_GROUPID (flag 0x100)
  NumPut(Row-1,           &Group%Row%, 4,  "Int")                  ; LVITEM_iItem        = 4
  NumPut(GroupNum-1,      &Group%Row%, 40, "Int")                  ; LVITEM_iGroupId     = 40???
  SendMessage 0x1006, -1, &Group%Row%, , ahk_id %hWnd_%            ; LVM_SETITEM         = 0x1006 ; 0x104C unicode?
  SendMessage 0x109d,1,0,,ahk_id %hWnd_%                           ; LVM_ENABLEGROUPVIEW = 0x109d maybe this shouldnt be default, only with enable?
  Grouped=1
 }
Return 1 ; not sure whats useful yet to return, group number? name?
}
Help:

RowOrCommand Row number to add to group, or 0 or "" to just add a group
or Command to:
"Enable" enable Group viewing
(rows not assigned to groups will be hidden)
"Disable" turn grouping off and revert to Report view
"Toggle" toggle above options
"Delete" turn off group view and delete all groups

GroupName Name of group to add to LV, and group in which to add row
or adds a group name without assigning a row if above=0 or ""
in that case, multiple groups can be added as "Group1|Group2|..."

ListViewHwnd hWnd of ListView control to work on... (listview option hwndListViewHwnd)
will be remembered, so only needs to be used once if only using one LV


feedback welcome, i haven't seen much use of this listview ability on here but some may find a use for it... and hopefully some unicode/_L/64-bit gurus can help out with a modern version

- gwarble

thanks: <!-- m -->http://www.autohotke...pic.php?t=52485<!-- m -->

edit: v.04 update, see latest posts

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
Posted Image

jballi
  • Members
  • 1029 posts
  • Last active:
  • Joined: 01 Oct 2005
Looks cool. :) I've always wondered what those LVM Group messages were for. I tried your example on AutoHotkey Basic and AutoHotkey L. Seems to work OK on both versions.

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
awesome, thanks for the feedback and testing...

good way to use:
LV_Group(LV_Add("", Cust, Desc, Stat ),Stat,JobsLV) ; LV_Add() returns row number


gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
ah beautimous... column clicking to regroup, like my computer when in "show in groups" mode... i'll add this ability to the function as well probably but try this in your ListView's g-Label:
If (A_GuiEvent = "ColClick")	; sorting
{
 Gui, 1:Default ; or however for ahk LV_ functions
 Loop, % LV_GetCount()
 {
  LV_GetText(Group,A_Index,A_EventInfo) ;get text of clicked column as group to put it in
  LV_Group(A_Index,Group,JobsLV) ;row, group, and hwnd of list view
 }
}

edit: example from first post with this ability:
#SingleInstance, Force
#NoEnv
SetWorkingDir, %A_ScriptDir%
 Gui Add, ListView, w400 r30 HwndLV vLV gLV,Filename|Ext|Size [mb]
 LV_ModifyCol(1,250)
 LV_ModifyCol(2,60)
 LV_ModifyCol(3,"60 Integer")
 Loop, *.*
 {
  SplitPath A_LoopFileName,,,,NameWithoutExt
  Row:=LV_Add(""" " . DefaultCheck . " """,NameWithoutExt,A_LoopFileExt,Round(A_LoopFileSize/1024/1024))
  LV_Group(Row,A_LoopFileExt,LV)
 }
 Gui Show,,Group View Test
Return

LV:
If (A_GuiEvent = "ColClick")
{
 LV_Group("Delete")
 Loop, % LV_GetCount()
 {
  LV_GetText(_,A_Index,A_EventInfo) ;get text of clicked column as group to put it in
  LV_Group(A_Index,_,LV) ;row, group, and hwnd of list view
 }
}
Return ; a little buggy on the size column for some reason

GuiClose:
GuiEscape:
ExitApp


Delusion
  • Members
  • 272 posts
  • Last active: Jul 13 2014 09:04 PM
  • Joined: 16 Jul 2008
this looks great but im still having some trouble figuring out how it works
how can i make this to group the list by Genre lets say or by Year

#SingleInstance, Force
#NoEnv
SetWorkingDir, %A_ScriptDir%
 Gui Add, ListView, w1400 r30 HwndLV vLV gLV,Title :|Path :|IMDb Link :|Genre :|Year :|Quality :|Keywords :|Seen? :|PMDb ID :
  
  LV_ModifyCol(1, "490 NoSort"), LV_ModifyCol(2, "390 NoSort"), LV_ModifyCol(3, "210 NoSort"), LV_ModifyCol(4, "210 NoSort")
  LV_ModifyCol(5, "50 NoSort"), LV_ModifyCol(6, "100 NoSort"), LV_ModifyCol(7, "100 NoSort"), LV_ModifyCol(8, "90 NoSort"), LV_ModifyCol(9, "70 NoSort")

  Loop Read, lists\Movielist_1.mdb
    {
      Loop Parse, A_LoopReadLine, `;
        Col%A_Index% := % A_LoopField
      LV_Add("", Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9)
    }
 Gui Show,w1520 h570,Group View Test
Return

LV:
If (A_GuiEvent = "ColClick")
{
 LV_Group("Delete")
 Loop, % LV_GetCount()
 {
  LV_GetText(_,A_Index,A_EventInfo) ;get text of clicked column as group to put it in
  LV_Group(A_Index,_,LV) ;row, group, and hwnd of list view
 }
}
Return ; a little buggy on the size column for some reason

GuiClose:
GuiEscape:
ExitApp

QuickSubs | Popcorn Movie Catalog
All my scripts are just in AutoHotkey v1.0.48.05

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
i'll fix this, but for now i think just remove your LV_Group("Delete") from the LV: subroutine since you aren't starting with groups...

otherwise you can do:
Loop Read, lists\Movielist_1.mdb
    {
      Loop Parse, A_LoopReadLine, `;
        Col%A_Index% := % A_LoopField
      Row:=LV_Add("", Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9)
      LV_Group(Row,Col4,LV)
    }
to start out grouped, then the LV: works as is (or "delete" can still be removed i think... buggy cuz i don't fully understand the LVM_'s)

thanks for trying

tested with a lists\Movielist_1.mdb like:

Movie1;Test2;Test3;Horror;1999;Test6;Test7;Test8;Test9
Movie2;Test2;Test3;Comedy;1999;Test6;Test7;Test8;Test9
Movie3;Test2;Test3;Horror;2002;Test6;Test7;Test8;Test9
Movie4;Test2;Test3;Comedy;2002;Test6;Test7;Test8;Test9
Movie5;Test2;Test3;Horror;1999;Test6;Test7;Test8;Test9



Delusion
  • Members
  • 272 posts
  • Last active: Jul 13 2014 09:04 PM
  • Joined: 16 Jul 2008
yeah that seems to work!
now i understand also a little bit better!

thank you very much for your work.im trying to implement it my movie database so i will have an eye on it for future versions :)
QuickSubs | Popcorn Movie Catalog
All my scripts are just in AutoHotkey v1.0.48.05

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
Great, let me know what features you'd want, i'm adding it to my app too so stuff will become apparent

  • Guests
  • Last active:
  • Joined: --
Nice work gwarble, I always wondered how grouped listview works.
I think your function is not final yet as I see from your post, so will wait before start using it :D
Also how about icons, colors and checkboxes?

Delusion
  • Members
  • 272 posts
  • Last active: Jul 13 2014 09:04 PM
  • Joined: 16 Jul 2008

Great, let me know what features you'd want, i'm adding it to my app too so stuff will become apparent


all i need it to is to be able to group my movies by genre and year

Also how about icons, colors and checkboxes?


there is many posts about those things already...iv tried already with colours and stuff but all of those libraries are not very stable
just make a search on the forum and im sure you will find what you need
QuickSubs | Popcorn Movie Catalog
All my scripts are just in AutoHotkey v1.0.48.05

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
Theres lots of options for coloring (but not for coloring groups, something i'll look into) just search around, lvx i think is what i use and its stable enough if you handle the wm_ cleanly

Checkboxes and icons are natively supported, and i think i saw a library for images in any column

Grouping doesnt rely on monitoring any windows messages so it should be stable enough to try at this point, but yes there are many improvements to come, its just a proof of concept from one night after bedtime at this point

Edit: i also hope there's a way to adjust the padding (space below a groups items before the next group name mainly) so i'll be looking into what options are available

Edit: here are prelim results of LVX_() for coloring (been using without LV_Group() for a while with good stable results) as you can see grouping changes the spacing by a pixel for some reason, and all the spacing around the group name:
Posted Image

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
If you're planning to use this be prepared for syntax changes...
with hwnd still static third param, call like
LV_Group(LV_hWnd)
just initializes the hwnd and returns

The reason the above failed for you without first grouping was LV_G("Delete") was called first, without hwnd

Ill try to make it act on gui default syslist123 or whatever if no hwnd

Also will be changing "Delete" to allow second param to delete a single group, no second param or "all" to remove all

And adding aux commands or functions like
LV_GroupCol(ColumnNumber,[FirstCharOnly]) or LV_Group("Col",...
for grouping by a column, or optionally by letter only
LV_GroupSort(?) or LV_Group("Sort",...)
once i figure out how

EDIT: since the native LV_ commands work on the default gui, i'd like this function to do the same when no hWnd is specified... anyone have a good way to accomplish this (without changing the LastFoundWindow)?
thanks

  • Guests
  • Last active:
  • Joined: --
Very nice function gwarble, but it doesn't work on Ahk_l

gwarble
  • Members
  • 624 posts
  • Last active: Aug 12 2016 07:49 PM
  • Joined: 23 May 2009
The problem surely comes from the way unicode is saved for the group name, i'll fix it once i understand it, but a poster above said it worked in _L, i assume ansi