Things it supports:
- adding progress bar gadgets to list icon gadget columns
- multiple list icon gadgets at once
- multiple columns per list icon gadget at once
- dynamical managment of progress bar gadget count to save ressources for not displayed progress bar gadgets
- adding and removing columns, if you do so progress bars will end up on wrong column
- sorting rows, if you do so progress bars will not be sorted and end up on wrong row
- adding a single progress bar, only full columns are supported
Procedures:
Add(ListIcon.i, Column.i, Min.i, Max.i, Flags.i)
Adds progress bars to a list icon gadget column.
ListIcon = PB gadget number
Column = column index starting at 0
Min = minimum value for progress bars
Max = maximum value for progress bars
Flags = PB progress bar flags
Remove(ListIcon.i, Column.i)
Removes progress bars that was been added with this module.
You need to do this befor closing the window or freeing the list icon gadget to prevent memory leak!
ListIcon = PB gadget number
Column = column index starting at 0
SetValue(ListIcon.i, Column.i, Row.i, Value.i)
Sets the value of a progress bar added with this module.
ListIcon = PB gadget number
Column = column index starting at 0
Row = row index starting at 0
Value = number within the bounds of min and max
GetValue(ListIcon.i, Column.i, Row.i)
Returns the value of a progress bar added with this module.
ListIcon = PB gadget number
Column = column index starting at 0
Row = row index starting at 0
Example screen shots:


Code: Select all
;/------------------\
;| ListIconProgress |
;| |
;| v0.02 |
;| by Thorium |
;| PureBaic 5.20 |
;\------------------/
;change log
;--------------------
;v0.02
;-fixed: if last row was displayed only partially it was not redrawn on progress change
;--------------------
;v0.01
;-initial release
EnableExplicit
DeclareModule ListIconProgress
Declare Add(ListIcon.i, Column.i, Min.i, Max.i, Flags.i)
Declare Remove(ListIcon.i, Column.i)
Declare SetValue(ListIcon.i, Column.i, Row.i, Value.i)
Declare.i GetValue(ListIcon.i, Column.i, Row.i)
EndDeclareModule
Module ListIconProgress
;holds information about the added progress bars
Structure ProgressGadgetInfo
ProgressBarNum.i
ProgressBarId.i
Item.i
SubItem.i
EndStructure
Structure ProgressInfo
Column.i
Min.i
Max.i
Flags.i
List Values.i()
Array ProgressGadgets.ProgressGadgetInfo(0)
EndStructure
;holds information about all list icon gadgets progress bars was been added to
Structure ListIconInfo
ListIconNum.i
ListIconId.i
OldListIconProc.i
RowCnt.i
VisibleRows.i
List ProgressColumns.ProgressInfo()
EndStructure
Global NewList ListIcons.ListIconInfo()
;finds the list icon gadget information for the specified list icon gadget
;returns #True if found and sets the found element to the current list element
;returns #False if not found
Procedure.i FindListIcon(ListIcon.i)
ForEach ListIcons()
If ListIcons()\ListIconNum = ListIcon
ProcedureReturn #True
EndIf
Next
ProcedureReturn #False
EndProcedure
;finds the list icon gadget information for the specified list icon gadget by it's hWnd
;returns #True if found and sets the found element to the current list element
;returns #False if not found
Procedure.i FindListIconByHandle(hWnd.i)
ForEach ListIcons()
If ListIcons()\ListIconId = hWnd
ProcedureReturn #True
EndIf
Next
ProcedureReturn #False
EndProcedure
;findes the column information for the specified list icon gadget column
;searches in the current element of ListIcons()
;returns #True if found and sets the found element to the current list element
;returns #False if not found
Procedure.i FindProgressColumn(Column.i)
ForEach ListIcons()\ProgressColumns()
If ListIcons()\ProgressColumns()\Column = Column
ProcedureReturn #True
EndIf
Next
ProcedureReturn #False
EndProcedure
;finds the progress bar gadget information for the specified list icon gadget row
;searches the current element of ListIcons()\ProgressColumns()
;returns the array index of ListIcons()\ProgressColumns()\ProgressGadgets
;returns #False if not found
Procedure.i FindProgressGadget(Row.i)
Protected i.i
For i = 1 To ListIcons()\VisibleRows
If ListIcons()\ProgressColumns()\ProgressGadgets(i)\Item = Row
ProcedureReturn i
EndIf
Next
ProcedureReturn #False
EndProcedure
;checks if a row of the current list view gadget is visible
Procedure.i IsRowVisible(Row.i)
Protected FirstVisibleRow.i
Protected VisibleRowCnt.i
;get visible rows
FirstVisibleRow = SendMessage_(ListIcons()\ListIconId, #LVM_GETTOPINDEX, 0, 0)
VisibleRowCnt = SendMessage_(ListIcons()\ListIconId, #LVM_GETCOUNTPERPAGE, 0, 0) + 1
;check if row is within visible range
If (Row >= FirstVisibleRow) And (Row < (FirstVisibleRow + VisibleRowCnt))
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
;creates the progress bars for a list icon column
;uses the current element of ListIcons()\ProgressColumns()
Procedure CreateProgressBars()
Protected i.i
Protected VisibleRowCnt.i
VisibleRowCnt = SendMessage_(ListIcons()\ListIconId, #LVM_GETCOUNTPERPAGE, 0, 0) + 1
ReDim ListIcons()\ProgressColumns()\ProgressGadgets.ProgressGadgetInfo(VisibleRowCnt)
For i = 1 To VisibleRowCnt
ListIcons()\ProgressColumns()\ProgressGadgets(i)\ProgressBarNum = ProgressBarGadget(#PB_Any, 0, 0, 10, 10, ListIcons()\ProgressColumns()\Min, ListIcons()\ProgressColumns()\Max, ListIcons()\ProgressColumns()\Flags)
ListIcons()\ProgressColumns()\ProgressGadgets(i)\ProgressBarId = GadgetID(ListIcons()\ProgressColumns()\ProgressGadgets(i)\ProgressBarNum)
SetParent_(ListIcons()\ProgressColumns()\ProgressGadgets(i)\ProgressBarId, ListIcons()\ListIconId)
Next
ListIcons()\VisibleRows = VisibleRowCnt
EndProcedure
;creates or frees progress bar gadgets if count of visible rows in list icon gadget changed
Procedure ManageProgressBars()
Protected i.i
Protected VisibleRowCnt.i
VisibleRowCnt = SendMessage_(ListIcons()\ListIconId, #LVM_GETCOUNTPERPAGE, 0, 0) + 1
If VisibleRowCnt > ListIcons()\VisibleRows
ForEach ListIcons()\ProgressColumns()
ReDim ListIcons()\ProgressColumns()\ProgressGadgets.ProgressGadgetInfo(VisibleRowCnt)
For i = ListIcons()\VisibleRows + 1 To VisibleRowCnt
ListIcons()\ProgressColumns()\ProgressGadgets(i)\ProgressBarNum = ProgressBarGadget(#PB_Any, 0, 0, 10, 10, ListIcons()\ProgressColumns()\Min, ListIcons()\ProgressColumns()\Max, ListIcons()\ProgressColumns()\Flags)
ListIcons()\ProgressColumns()\ProgressGadgets(i)\ProgressBarId = GadgetID(ListIcons()\ProgressColumns()\ProgressGadgets(i)\ProgressBarNum)
SetParent_(ListIcons()\ProgressColumns()\ProgressGadgets(i)\ProgressBarId, ListIcons()\ListIconId)
Next
Next
ElseIf VisibleRowCnt < ListIcons()\VisibleRows
ForEach ListIcons()\ProgressColumns()
For i = ListIcons()\VisibleRows To VisibleRowCnt + 1 Step -1
FreeGadget(ListIcons()\ProgressColumns()\ProgressGadgets(i)\ProgressBarNum)
Next
ReDim ListIcons()\ProgressColumns()\ProgressGadgets.ProgressGadgetInfo(VisibleRowCnt)
Next
EndIf
ListIcons()\VisibleRows = VisibleRowCnt
EndProcedure
;updates the position, size and value of the progress bar gadgets
Procedure UpdateProgressBars()
Protected i.i
Protected FirstVisibleRow.i
Protected SubItemRect.RECT
FirstVisibleRow = SendMessage_(ListIcons()\ListIconId, #LVM_GETTOPINDEX, 0, 0)
ForEach ListIcons()\ProgressColumns()
For i = 0 To ListIcons()\VisibleRows - 1
If i+FirstVisibleRow > ListIcons()\RowCnt-1
;row is in visible range but has no item so we need to hide the progress bar gadget
ListIcons()\ProgressColumns()\ProgressGadgets(i+1)\Item = -1
ListIcons()\ProgressColumns()\ProgressGadgets(i+1)\SubItem = ListIcons()\ProgressColumns()\Column
HideGadget(ListIcons()\ProgressColumns()\ProgressGadgets(i+1)\ProgressBarNum, #True)
Else
;store information about the progress bar gadget
ListIcons()\ProgressColumns()\ProgressGadgets(i+1)\Item = i + FirstVisibleRow
ListIcons()\ProgressColumns()\ProgressGadgets(i+1)\SubItem = ListIcons()\ProgressColumns()\Column
;get position and size of sub item for progress bar
SubItemRect\top = ListIcons()\ProgressColumns()\Column
SubItemRect\left = #LVIR_LABEL
SendMessage_(ListIcons()\ListIconId, #LVM_GETSUBITEMRECT, FirstVisibleRow + i, @SubItemRect)
;update position and size of progress bar gadget
ResizeGadget(ListIcons()\ProgressColumns()\ProgressGadgets(i + 1)\ProgressBarNum, SubItemRect\left+1, SubItemRect\top+1, SubItemRect\right - SubItemRect\left - 2, SubItemRect\bottom - SubItemRect\top - 2)
;update value of progress bar gadget
SelectElement(ListIcons()\ProgressColumns()\Values(), i + FirstVisibleRow)
SetGadgetState(ListIcons()\ProgressColumns()\ProgressGadgets(i + 1)\ProgressBarNum, ListIcons()\ProgressColumns()\Values())
HideGadget(ListIcons()\ProgressColumns()\ProgressGadgets(i + 1)\ProgressBarNum, #False)
EndIf
Next
Next
RedrawWindow_(ListIcons()\ListIconId, 0, 0, #RDW_INVALIDATE)
EndProcedure
;hook procedure for the subclassing of the list icon gadgets
;all messages going to the list icon gadget windows will go to this procedure first
;needed to handle resize, move, item add, item delete, etc.
Procedure.i WindowProcHook(hwnd.i, msg.i, wparam.i, lparam.i)
Protected Result.i
Protected *HeaderNotification.NMHDR
;check if we actualy got this window hooked
If FindListIconByHandle(hwnd) = #False
ProcedureReturn #False
EndIf
;call the original window proc and save the return value
Result = CallWindowProc_(ListIcons()\OldListIconProc, hwnd, msg, wparam, lparam)
;if the message processing failed we dont need to do any actions
If Result = -1
ProcedureReturn -1
EndIf
;check if we got a message which needs us to update the progress bar gadgets
Select msg
Case #WM_NOTIFY
*HeaderNotification = lparam
If *HeaderNotification\code = #HDN_ITEMCHANGED
;a column header has been changed
ManageProgressBars()
UpdateProgressBars()
EndIf
Case #WM_VSCROLL, #WM_HSCROLL, #WM_SIZE, #LVM_SCROLL, #LVM_SETCOLUMNWIDTH
;list icon gadget was been scrolled or changed in size or a column changed in size
ManageProgressBars()
UpdateProgressBars()
Case #LVM_DELETEALLITEMS
;all items have been deleted
ListIcons()\RowCnt = 0
ForEach ListIcons()\ProgressColumns()
ClearList(ListIcons()\ProgressColumns()\Values())
Next
UpdateProgressBars()
Case #LVM_DELETEITEM
;a item has been deleted
ForEach ListIcons()\ProgressColumns()
SelectElement(ListIcons()\ProgressColumns()\Values(), wparam)
DeleteElement(ListIcons()\ProgressColumns()\Values())
Next
ListIcons()\RowCnt = ListIcons()\RowCnt - 1
UpdateProgressBars()
Case #LVM_INSERTITEM
;a item has been inserted
ForEach ListIcons()\ProgressColumns()
If Result = 0
FirstElement(ListIcons()\ProgressColumns()\Values())
InsertElement(ListIcons()\ProgressColumns()\Values())
Else
SelectElement(ListIcons()\ProgressColumns()\Values(), Result - 1)
AddElement(ListIcons()\ProgressColumns()\Values())
EndIf
Next
ListIcons()\RowCnt = ListIcons()\RowCnt + 1
UpdateProgressBars()
EndSelect
ProcedureReturn Result
EndProcedure
;adds a progress bar to a list icon gadget column
Procedure Add(ListIcon.i, Column.i, Min.i, Max.i, Flags.i)
Protected i.i
;get list icon gadget information entry
If FindListIcon(ListIcon) = #False
;it's a new list icon gadget
AddElement(ListIcons())
;get informations about the new list icon gadget
ListIcons()\ListIconNum = ListIcon.i
ListIcons()\ListIconId = GadgetID(ListIcon)
ListIcons()\RowCnt = CountGadgetItems(ListIcons()\ListIconNum)
;install window hook on the list icon gadget for subclassing
ListIcons()\OldListIconProc = GetWindowLongPtr_(ListIcons()\ListIconId, #GWLP_WNDPROC)
SetWindowLongPtr_(ListIcons()\ListIconId, #GWLP_WNDPROC, @WindowProcHook())
EndIf
;store informations about the progress column
AddElement(ListIcons()\ProgressColumns())
ListIcons()\ProgressColumns()\Column = Column
ListIcons()\ProgressColumns()\Min = Min
ListIcons()\ProgressColumns()\Max = Max
ListIcons()\ProgressColumns()\Flags = Flags
;create list of progress values
For i = 1 To ListIcons()\RowCnt
AddElement(ListIcons()\ProgressColumns()\Values())
Next
;manages count of progress bars
CreateProgressBars()
;update position, size and value of the progress bar gadgets
UpdateProgressBars()
EndProcedure
;removes a progress bar from a list icon gadget column
Procedure Remove(ListIcon.i, Column.i)
Protected i.i
If FindListIcon(ListIcon) = #True
If FindProgressColumn(Column) = #True
;free all progress bar gadgets associated with the list view gadget column
For i = 1 To ListIcons()\VisibleRows
FreeGadget(ListIcons()\ProgressColumns()\ProgressGadgets(i)\ProgressBarNum)
Next
;remove stored informations about the list icon gadget column
DeleteElement(ListIcons()\ProgressColumns())
;if the column was the last remaining progress column of the list icon remove the list icon from stored information
If ListSize(ListIcons()\ProgressColumns()) = 0
;uninstall window hook
SetWindowLongPtr_(ListIcons()\ListIconId, #GWLP_WNDPROC, ListIcons()\OldListIconProc)
;remove stored informations about the list icon gadget
DeleteElement(ListIcons())
EndIf
EndIf
EndIf
EndProcedure
;sets the value of a progress bar of a list icon gadget
Procedure SetValue(ListIcon.i, Column.i, Row.i, Value.i)
If FindListIcon(ListIcon) = #True
If FindProgressColumn(Column) = #True
SelectElement(ListIcons()\ProgressColumns()\Values(), Row)
ListIcons()\ProgressColumns()\Values() = Value
If IsRowVisible(Row) = #True
SetGadgetState(ListIcons()\ProgressColumns()\ProgressGadgets(FindProgressGadget(Row))\ProgressBarNum, Value)
EndIf
EndIf
EndIf
EndProcedure
;gets the value of a progress bar of a list icon gadget
Procedure.i GetValue(ListIcon.i, Column.i, Row.i)
If FindListIcon(ListIcon) = #True
If FindProgressColumn(Column) = #True
SelectElement(ListIcons()\ProgressColumns()\Values(), Row)
ProcedureReturn ListIcons()\ProgressColumns()\Values()
EndIf
EndIf
ProcedureReturn #False
EndProcedure
EndModule