Jump to content

ListView Flicker, and failing to DeleteAll.


Go to solution Solved by kurtykurtyboy,

Recommended Posts

Hi,  

I wanted a multi-column listview, with coloured cells, and I found @Melba23’s example here.  That works, but the listview has a flicker.  It redraws all the rows whenever you add one.  It’s not so obvious with the few lines in the original example, but becomes worse with more items and wider.

It’s the same whether you add the new items at the top, as in the example, or on the end.  I tried _GUICtrlListView_BeginUpdate and _GUICtrlListView_EndUpdate but that didn’t seem to make any difference.  I tried GUICtrlSetState($iGUI1_LV, $GUI_HIDE) before adding multiple items, and $GUI_SHOW after.  With this you only see one redraw for multiple items, but still a full redraw for adding a single item. I tried @jpm’s Lock/ResetLock but that seems the same as hide/show.

Not directly connected, I tried _GUICtrlListView_DeleteAllItems, that seemed to work, but when I added another item, all the deleted ones reappeared.

The code below adds some items, wait 2 seconds, and adds another, see full redraw.  After a few more seconds it deletes all the items, you can see them gone.  Then it adds a item, which appears at the top, but all the deleted ones reappear below.

AutoIt 3.3.14.5

Any help appreciated.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

#include "GUIListViewEx.au3"

$hGUI = GUICreate("Coloured ListView Example", 500, 300)

; Create ListView
$cLV = GUICtrlCreateListView("Column 0|Colourable|Column 2|Column 3", 10, 10, 480, 260, BitOR($LVS_SINGLESEL, $LVS_SHOWSELALWAYS))
For $i = 0 To 3
    _GUICtrlListView_SetColumnWidth($cLV, $i, 100)
Next

; Initiate ListView = user colours
$iLVIndex = _GUIListViewEx_Init($cLV, "", 0, 0, True, 32)

; Set default colours to use
Global $aDefCols[4] = ["0x000000", "0xFEFEFE", "0xFFFFFF", "0x0000FF"]
_GUIListViewEx_SetDefColours($iLVIndex, $aDefCols)

; If colours used then this function must be run BEFORE GUISetState
_GUIListViewEx_MsgRegister()

GUISetState()

; Create array and fill listview
Global $aLVArray[6][4]
;_GUICtrlListView_BeginUpdate($cLV)
For $i = 0 To 5
    $sData = "Item " & $i & "-0"
    $aLVArray[$i][0] = $sData
    For $j = 1 To 3
        $sData &= "|SubItem " & $i & "-" & $j
        $aLVArray[$i][$j] = "SubItem " & $i & "-" & $j
        Next

    _GUIListViewEx_InsertSpec($iLVIndex, 0, $sData)
    _GUIListViewEx_InsertSpec($iLVIndex, 0, $sData)
    ; Some simple conditions for colour
    $sColSet = ";0x00FF00"
    If Mod($i, 2) = 0 Then
        $sColSet = ";0xFFFF00"
    ElseIf Mod($i, 3) = 0 Then
        $sColSet = ";0xFF0000"
    EndIf
    ; Set item colour
    ;_GUIListViewEx_SetColour($iLVIndex, $sColSet, 0, 1)
Next
Sleep(2000)
_GUIListViewEx_InsertSpec($iLVIndex, 0, $sData)

;_GUICtrlListView_EndUpdate($cLV)

Local $iLoops = 0
While 1

    $iMsg = GUIGetMsg()
    Switch $iMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

    $vRet = _GUIListViewEx_EventMonitor()

        If $iLoops =  50 Then
            _GUICtrlListView_DeleteAllItems($cLV)
        EndIf

        If $iLoops = 100 Then
    _GUIListViewEx_InsertSpec($iLVIndex, 0, "More|Data")
        EndIf

        Sleep(100)
        $iLoops += 1
WEnd

 

Link to post
Share on other sites
  • Moderators

RichardL,

There will always be some flicker as using colour means hat the ListView is user-drawn and AutoIt takes a time to run through all of the elements to redraw them when the ListView is altered. But using the UDF function _GUIListViewEx_BlockReDraw helps when adding multiple items as I hope you can see in the example below.

As to the "DeleteAll" problem, did you read the the Guide that is part of the UDF download? If not then you missed this bit:

Quote

Closure and Reloading:

 <...>

If you wish to reload the ListView with new data, you will need to clear the current content using _GUICtrlListView_DeleteAllItems, close it within the UDF using _GUIListViewEx_Close, reload the ListView with the new data and then reinitialise it using _GUIListViewEx_Init. Otherwise the UDF will become confused about the current content and errors will certainly occur.

When you follow this procedure, the UDF no longer believes that the original content is there and does not show it at the next redraw.

Here is your script with the amendments:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

#include "GUIListViewEx.au3"

$hGUI = GUICreate("Coloured ListView Example", 500, 300)

; Create ListView
$cLV = GUICtrlCreateListView("Column 0|Colourable|Column 2|Column 3", 10, 10, 480, 260, BitOR($LVS_SINGLESEL, $LVS_SHOWSELALWAYS))
For $i = 0 To 3
    _GUICtrlListView_SetColumnWidth($cLV, $i, 100)
Next

; Initiate ListView = user colours
$iLVIndex = _GUIListViewEx_Init($cLV, "", 0, 0, True, 32)

; Set default colours to use
Global $aDefCols[4] = ["0x000000", "0xFEFEFE", "0xFFFFFF", "0x0000FF"]
_GUIListViewEx_SetDefColours($iLVIndex, $aDefCols)

; If colours used then this function must be run BEFORE GUISetState
_GUIListViewEx_MsgRegister()

GUISetState()

; Create array and fill listview
Global $aLVArray[6][4]

_GUIListViewEx_BlockReDraw($iLVIndex, True)

For $i = 0 To 5

    $sData = "Item " & $i & "-0"
    $aLVArray[$i][0] = $sData
    For $j = 1 To 3
        $sData &= "|SubItem " & $i & "-" & $j
        $aLVArray[$i][$j] = "SubItem " & $i & "-" & $j
    Next

    _GUIListViewEx_InsertSpec($iLVIndex, 0, $sData)
    _GUIListViewEx_InsertSpec($iLVIndex, 0, $sData)
    ; Some simple conditions for colour
    $sColSet = ";0x00FF00"
    If Mod($i, 2) = 0 Then
        $sColSet = ";0xFFFF00"
    ElseIf Mod($i, 3) = 0 Then
        $sColSet = ";0xFF0000"
    EndIf
    ; Set item colour
    _GUIListViewEx_SetColour($iLVIndex, $sColSet, 0, 1)

Next

_GUIListViewEx_BlockReDraw($iLVIndex, False)

Sleep(2000)

_GUIListViewEx_BlockReDraw($iLVIndex, True)

_GUIListViewEx_InsertSpec($iLVIndex, 0, $sData)

_GUIListViewEx_BlockReDraw($iLVIndex, False)

Local $iLoops = 0
While 1

    $iMsg = GUIGetMsg()
    Switch $iMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

    $vRet = _GUIListViewEx_EventMonitor()

    If $iLoops = 50 Then
        _GUICtrlListView_DeleteAllItems($cLV)
        _GUIListViewEx_Close($iLVIndex)
        $iLVIndex = _GUIListViewEx_Init($cLV, "", 0, 0, True, 32)
    EndIf

    If $iLoops = 100 Then
        _GUIListViewEx_InsertSpec($iLVIndex, 0, "More|Data")
    EndIf

    Sleep(100)
    $iLoops += 1
WEnd

Does that meet with your expectations?

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to post
Share on other sites

Hi @Melba23 Thanks.  The example program is working fine now.  I've copied the changes into the real program.  The update is looking smooth, but the DeleteAllItems is causing a crash when new items are added.  I'm puzzling what I've done different from the example.  Should the _GUIListViewEx_EventMonitor() be done just once? at the start?

 

Link to post
Share on other sites
  • Moderators

RichardL,

Delighted to hear it.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to post
Share on other sites

@Melba23, I have another listview with a flicker and I think you might be saying it can't be fixed.  "There will always be some flicker as using colour..."  With fewer than about 20 rows the flicker is very fast, almost unnoticible.  With 40 rows or more it's annoying.

The action is:
- if the LV is full, delete the top row.
- insert a new row at the end
- Update the text of one sub-item in the new row (possibly a few times)
- change the colour on that sub-item.

The delete and insert each make a flicker but combined into one with BlockRedraw.  The new row and the change sub-item each make a flicker.  

The colour change works very nicely, changes the colour without any flicker.

Is any improvement possible?

 

#include <GUIConstantsEx.au3>
#include <Date.au3>
#include <WindowsConstants.au3>

#include "GUIListViewEx.au3"

Opt("MustDeclareVars", 1)

Local $iGW = 700
Local $iGH = 600
Local $hGUI
Local $cLV

Local $iLVIndex
Local $vRet
Local $sData
Local $sColSet
Local $iMsg
Local $iColWid
$hGUI = GUICreate("Coloured ListView Example", $iGW, $iGH)


; Create ListView
$cLV = GUICtrlCreateListView("Column 0|Colourable|Column 2|Column 3|C4|C5", 10, 10, $iGW - 20, $iGH - 20, BitOR($LVS_SINGLESEL, $LVS_SHOWSELALWAYS))
For $i = 0 To 5
    $iColWid = 100
    If $i = 3 Then $iColWid = 160
    _GUICtrlListView_SetColumnWidth($cLV, $i, $iColWid)
Next

; Initiate ListView = user colours
$iLVIndex = _GUIListViewEx_Init($cLV, "", 0, 0, True, 32)

; Set default colours to use
;Global $aDefCols[4] = ["0x000000", "0xFEFEFE", "0xFFFFFF", "0x0000FF"]
;_GUIListViewEx_SetDefColours($iLVIndex, $aDefCols)

; If colours used then this function must be run BEFORE GUISetState
_GUIListViewEx_MsgRegister()

GUISetState()

; Create array and fill listview
Global $aLVArray[6][4]

_GUIListViewEx_BlockReDraw($iLVIndex, True)

For $i = 0 To 5

    $sData = "Item " & $i & "-0"
    $aLVArray[$i][0] = $sData
    For $j = 1 To 3
        $sData &= "|SubItem " & $i & "-" & $j
        $aLVArray[$i][$j] = "SubItem " & $i & "-" & $j
    Next

    _GUIListViewEx_InsertSpec($iLVIndex, 0, $sData)
    _GUIListViewEx_InsertSpec($iLVIndex, 0, $sData)
    ; Some simple conditions for colour
    $sColSet = ";0x00FF00"
    If Mod($i, 2) = 0 Then
        $sColSet = ";0xFFFF00"
    ElseIf Mod($i, 3) = 0 Then
        $sColSet = ";0xFF0000"
    EndIf
    ; Set item colour
    _GUIListViewEx_SetColour($iLVIndex, $sColSet, 0, 1)

Next
_GUIListViewEx_BlockReDraw($iLVIndex, False)


ConsoleWrite(StringFormat("Count %3d\n", _GUICtrlListView_GetItemCount($cLV)))
Sleep(1000)
; Try deleting an item.
;_GUICtrlListView_DeleteItem($cLV, 3)  !NO
_GUIListViewEx_DeleteSpec($iLVIndex, 3)
ConsoleWrite(StringFormat("Count %3d\n", _GUICtrlListView_GetItemCount($cLV)))
Sleep(1000)


Local $iNofRows
Local $iDly
; Insert more lines
For $iIx = 1 To 5000
    $iDly = 200
    _GUIListViewEx_BlockReDraw($iLVIndex, True)
    If $iIx > 20 Then $iDly = 400
    $iNofRows = _GUICtrlListView_GetItemCount($cLV)
    If $iNofRows > $iGH / 18 + 5 Then
        _GUIListViewEx_DeleteSpec($iLVIndex, 0)
    EndIf
    Sleep($iDly)
    $sData = StringFormat("Count %3d|Rows %3d|---------|------------|-----------|---------", $iIx, $iNofRows)
    ;_GUIListViewEx_BlockReDraw($iLVIndex, True)
    _GUIListViewEx_InsertSpec($iLVIndex, -1, $sData)
    _GUIListViewEx_BlockReDraw($iLVIndex, False)

    Local $iLVItmNo
    $iLVItmNo = _GUICtrlListView_GetItemCount($cLV) - 1
    ConsoleWrite(StringFormat("Count %3d\n", $iLVItmNo))
    Sleep($iDly)
    _GUIListViewEx_ChangeItem($iLVIndex, $iLVItmNo, 3, _Now())
    Sleep($iDly)
    _GUIListViewEx_SetColour($iLVIndex, ";0x00FF00", $iLVItmNo, 3)
Next

Local $iLoops = 0
While 1

    $iMsg = GUIGetMsg()
    Switch $iMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

    ;$vRet = _GUIListViewEx_EventMonitor()
        If 0 Then  ; Try delet all and add again.
            If $iLoops = 50 Then
                    _GUICtrlListView_DeleteAllItems($cLV)
                    _GUIListViewEx_Close($iLVIndex)
                    $iLVIndex = _GUIListViewEx_Init($cLV, "", 0, 0, True, 32)
            EndIf

            If $iLoops = 100 Then
                    _GUIListViewEx_InsertSpec($iLVIndex, 0, "More|Data")
                    _GUIListViewEx_InsertSpec($iLVIndex, 0, "More|Data")
            EndIf
        EndIf

    Sleep(100)
    $iLoops += 1
WEnd

 

Link to post
Share on other sites
  • Moderators

RichardL,

Alas, I do not think that the flicker can be reduced any further when there are a significant number of rows in the ListView. This thread shows the effort that went into getting the code as "fast" as it is now!

Something that does reduce the flicker a bit is setting the value that you subsequently change into the original data that you load into the new line - I realise this is an example script and your full version may not be able to do such a thing, but it might be worth taking a look to see if something along those lines is possible.

Taking another route, LarsJ has done a lot of work on "virtual ListViews" which are significantly faster that the "normal" ones when there are large numbers of rows in the control - and as I pinched used his colouring code in my UDF I am sure that he must have a coloured version on the forum somewhere. That might well be a solution.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to post
Share on other sites
  • Solution

@RichardL Try adding the $LVS_EX_DOUBLEBUFFER extended style. This eliminated all flickering for me.

$cLV = GUICtrlCreateListView("Column 0|Colourable|Column 2|Column 3|C4|C5", 10, 10, $iGW - 20, $iGH - 20, BitOR($LVS_SINGLESEL, $LVS_SHOWSELALWAYS))
_GUICtrlListView_SetExtendedListViewStyle($cLV, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER))

 

Link to post
Share on other sites

For what it's worth, here is a quick and dirty version of your last example using the LarsJ virtual listview plus colors. It's surprisingly easy to set up, you just need to take care of your data and color arrays.

#include <GUIConstantsEx.au3>
#include <Date.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <GuiListView.au3>
#include <ListViewConstants.au3>


Opt("MustDeclareVars", 1)

Local $iGW = 700
Local $iGH = 600
Local $hGUI
Global $cLV, $h_cLV

Local $iLVIndex
Local $vRet
Local $sData
Local $sColSet
Local $iMsg
Local $iColWid
Local $iNumberCols = 6
Global $tText = DllStructCreate("wchar[4096]")

$hGUI = GUICreate("Coloured ListView Example", $iGW, $iGH)


; Create ListView - set $LVS_OWNERDATA to indicate that we will keep track of our own data
$cLV = GUICtrlCreateListView("Column 0|Colourable|Column 2|Column 3|C4|C5", 10, 10, $iGW - 20, $iGH - 20, BitOR($LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_OWNERDATA))
_GUICtrlListView_SetExtendedListViewStyle($cLV, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER))
$h_cLV = GUICtrlGetHandle($cLV)
For $i = 0 To $iNumberCols - 1
    $iColWid = 100
    If $i = 3 Then $iColWid = 160
    _GUICtrlListView_SetColumnWidth($cLV, $i, $iColWid)
Next

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()

; Create array to hold listview data
Global $aLVArray[0][$iNumberCols]
; Create array to hold color data
Global $aLVColors[0][$iNumberCols]

Local $aData[1][$iNumberCols], $aColors[1][$iNumberCols]
_GUICtrlListView_BeginUpdate($cLV)
For $i = 0 To 5

    $sData = "Item " & $i & "-0"
    $aData[0][0] = $sData
    For $j = 1 To 3
        $aData[0][$j] = "SubItem " & $i & "-" & $j
    Next
    If UBound($aLVColors) = 0 Then
        _ArrayAdd($aLVArray, $aData)
    Else
        _ArrayInsert($aLVArray, 0, $aData)
    EndIf
    _ArrayInsert($aLVArray, 0, $aData)

    ; Some simple conditions for colour
    $aColors[0][0] = 0xFFFFFF
    $aColors[0][1] = 0xFFFFFF
    $aColors[0][2] = 0xFFFFFF
    $aColors[0][3] = 0xFFFFFF
    $aColors[0][4] = 0xFFFFFF
    $aColors[0][5] = 0xFFFFFF
    $sColSet = _WinAPI_SwitchColor(0x00FF00)
    If Mod($i, 2) = 0 Then
        $sColSet = _WinAPI_SwitchColor(0xFFFF00)
    ElseIf Mod($i, 3) = 0 Then
        $sColSet = _WinAPI_SwitchColor(0xFF0000)
    EndIf
    If UBound($aLVColors) = 0 Then
        _ArrayAdd($aLVColors, $aColors)
    Else
        _ArrayInsert($aLVColors, 0, $aColors)
    EndIf
    ; Set item colour
    $aColors[0][1] = $sColSet
    _ArrayInsert($aLVColors, 0, $aColors)

Next
_GUICtrlListView_EndUpdate($cLV)
;force the listview to update itself
GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)

ConsoleWrite(StringFormat("Count %3d\n", _GUICtrlListView_GetItemCount($cLV)))
Sleep(1000)

; Try deleting an item.
;~ _GUICtrlListView_DeleteItem($cLV, 3)
_ArrayDelete($aLVArray, 3)
_ArrayDelete($aLVColors, 3)
GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)

ConsoleWrite(StringFormat("Count %3d\n", _GUICtrlListView_GetItemCount($cLV)))
Sleep(1000)


Local $iNofRows
Local $iDly
; Insert more lines
For $iIx = 1 To 5000
    $iDly = 200

    If $iIx > 20 Then $iDly = 400
    $iNofRows = UBound($aLVArray)
    If $iNofRows > $iGH / 18 + 5 Then
        _ArrayDelete($aLVArray, 0)
        _ArrayDelete($aLVColors, 0)
    EndIf
    GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)

    Sleep($iDly)
    $sData = StringFormat("Count %3d|Rows %3d|---------|------------|-----------|---------", $iIx, $iNofRows)
    ;_GUIListViewEx_BlockReDraw($iLVIndex, True)
;~     _GUIListViewEx_InsertSpec($iLVIndex, -1, $sData)
;~     _GUIListViewEx_BlockReDraw($iLVIndex, False)
    $aData[0][0] = "Count " & $iIx
    $aData[0][1] = "Rows " & $iNofRows
    $aData[0][2] = "---------"
    $aData[0][3] = "---------"
    $aData[0][4] = "---------"
    $aData[0][5] = "---------"
    _ArrayAdd($aLVArray, $aData)

    $aColors[0][0] = 0xFFFFFF
    $aColors[0][1] = 0xFFFFFF
    $aColors[0][2] = 0xFFFFFF
    $aColors[0][3] = 0xFFFFFF
    $aColors[0][4] = 0xFFFFFF
    $aColors[0][5] = 0xFFFFFF
    _ArrayAdd($aLVColors, $aColors)

    GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)

    Local $iLVItmNo
    $iLVItmNo = UBound($aLVArray) - 1
    ConsoleWrite(StringFormat("Count %3d\n", $iLVItmNo))
    Sleep($iDly)
;~     _GUIListViewEx_ChangeItem($iLVIndex, $iLVItmNo, 3, _Now())
    $aLVArray[$iLVItmNo][3] = _Now()
;~  GUICtrlSendMsg($cLV, $LVM_REDRAWITEMS, $iLVItmNo, $iLVItmNo)
    GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)
    Sleep($iDly)
;~     _GUIListViewEx_SetColour($iLVIndex, ";0x00FF00", $iLVItmNo, 3)
    $aLVColors[$iLVItmNo][3] = 0x00FF00

    GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)
Next

;~ Local $iLoops = 0
;~ While 1

;~     $iMsg = GUIGetMsg()
;~     Switch $iMsg
;~         Case $GUI_EVENT_CLOSE
;~             Exit
;~     EndSwitch

;~     ;$vRet = _GUIListViewEx_EventMonitor()
;~         If 0 Then  ; Try delet all and add again.
;~             If $iLoops = 50 Then
;~                     _GUICtrlListView_DeleteAllItems($cLV)
;~                     _GUIListViewEx_Close($iLVIndex)
;~                     $iLVIndex = _GUIListViewEx_Init($cLV, "", 0, 0, True, 32)
;~             EndIf

;~             If $iLoops = 100 Then
;~                     _GUIListViewEx_InsertSpec($iLVIndex, 0, "More|Data")
;~                     _GUIListViewEx_InsertSpec($iLVIndex, 0, "More|Data")
;~             EndIf
;~         EndIf

;~     Sleep(100)
;~     $iLoops += 1
;~ WEnd


Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Local $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $h_cLV
            Switch $iCode
                    ;virtual listview and color change from larsj
                    ;https://www.autoitscript.com/forum/topic/168707-listview-item-subitem-background-colour/#comment-1234009
                Case $LVN_GETDISPINFOW
                    ; Fill virtual listview
                    Local $tNMLVDISPINFO = DllStructCreate($tagNMLVDISPINFO, $lParam)
                    If BitAND(DllStructGetData($tNMLVDISPINFO, "Mask"), $LVIF_TEXT) Then
                        Local $sItem = $aLVArray[DllStructGetData($tNMLVDISPINFO, "Item")][DllStructGetData($tNMLVDISPINFO, "SubItem")]
                        DllStructSetData($tText, 1, $sItem)
                        DllStructSetData($tNMLVDISPINFO, "TextMax", StringLen($sItem))
                        DllStructSetData($tNMLVDISPINFO, "Text", DllStructGetPtr($tText))
                    EndIf

                Case $NM_CUSTOMDRAW
                    Local $tNMLVCUSTOMDRAW = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
                    Local $dwDrawStage = DllStructGetData($tNMLVCUSTOMDRAW, "dwDrawStage")

                    Switch $dwDrawStage              ; Holds a value that specifies the drawing stage

                        Case $CDDS_PREPAINT
                            ; Before the paint cycle begins
                            Return $CDRF_NOTIFYITEMDRAW ; Notify the parent window of any item-related drawing operations

                        Case $CDDS_ITEMPREPAINT
                            ; Before painting an item
                            Return $CDRF_NOTIFYSUBITEMDRAW ; Notify the parent window of any subitem-related drawing operations

                        Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM)
                            ; Before painting a subitem
                            ;Local $iItem = DllStructGetData($tNMLVCUSTOMDRAW, "dwItemSpec")                ; Item index
                            ;Local $iSubItem = DllStructGetData($tNMLVCUSTOMDRAW, "iSubItem")               ; Subitem index
                            ;DllStructSetData( $tNMLVCUSTOMDRAW, "ClrTextBk", $aColors[$iItem][$iSubItem] ) ; Backcolor of item/subitem
                            DllStructSetData($tNMLVCUSTOMDRAW, "ClrTextBk", $aLVColors[DllStructGetData($tNMLVCUSTOMDRAW, "dwItemSpec")][DllStructGetData($tNMLVCUSTOMDRAW, "iSubItem")])
                            Return $CDRF_NEWFONT     ; $CDRF_NEWFONT must be returned after changing font or colors

                    EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
    #forceref $hWnd, $iMsg, $wParam
EndFunc   ;==>WM_NOTIFY

 

Link to post
Share on other sites
  • Moderators

kurtykurtyboy,

Very nice - thanks for the tip.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to post
Share on other sites

..just in case. Y' know, "make it until you brake it" is my motto.

Spoiler
#include <GUIConstantsEx.au3>
#include <Date.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <GuiListView.au3>
#include <ListViewConstants.au3>

;;; https://www.autoitscript.com/forum/topic/208868-listview-flicker-and-failing-to-deleteall/

Opt("MustDeclareVars", 1)
Opt("TrayAutoPause", 0)

Local $iGW = 700
Local $iGH = 600
Local $hGUI
Global $cLV, $h_cLV

Local $iLVIndex
Local $vRet
Local $sData
Local $sColSet
Local $iMsg
Local $iColWid
Local $iNumberCols = 6
Global $tText = DllStructCreate("wchar[4096]")

$hGUI = GUICreate("Coloured ListView Example", $iGW, $iGH)


; Create ListView - set $LVS_OWNERDATA to indicate that we will keep track of our own data
$cLV = GUICtrlCreateListView("Column 0|Colourable|Column 2|Column 3|C4|C5", 10, 10, $iGW - 20, $iGH - 20, BitOR($LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_OWNERDATA))
_GUICtrlListView_SetExtendedListViewStyle($cLV, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER))
$h_cLV = GUICtrlGetHandle($cLV)
For $i = 0 To $iNumberCols - 1
    $iColWid = 100
    If $i = 3 Then $iColWid = 160
    _GUICtrlListView_SetColumnWidth($cLV, $i, $iColWid)
Next

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()

; Create array to hold listview data
Global $aLVArray[0][$iNumberCols]
; Create array to hold color data
Global $aLVColors[0][$iNumberCols]

Local $aData[1][$iNumberCols], $aColors[1][$iNumberCols]
_GUICtrlListView_BeginUpdate($cLV)
For $i = 0 To 5

    $sData = "Item " & $i & "-0"
    $aData[0][0] = $sData
    For $j = 1 To 3
        $aData[0][$j] = "SubItem " & $i & "-" & $j
    Next
    If UBound($aLVColors) = 0 Then
        _ArrayAdd($aLVArray, $aData)
    Else
        _ArrayInsert($aLVArray, 0, $aData)
    EndIf
    _ArrayInsert($aLVArray, 0, $aData)

    ; Some simple conditions for colour
    $aColors[0][0] = 0xFFFFFF
    $aColors[0][1] = 0xFFFFFF
    $aColors[0][2] = 0xFFFFFF
    $aColors[0][3] = 0xFFFFFF
    $aColors[0][4] = 0xFFFFFF
    $aColors[0][5] = 0xFFFFFF

    $aColors[0][0] = 0
    $aColors[0][1] = 0
    $aColors[0][2] = 0
    $aColors[0][3] = 0
    $aColors[0][4] = 0
    $aColors[0][5] = 0

    $sColSet = _WinAPI_SwitchColor(0x009900)
    If Mod($i, 2) = 0 Then
        $sColSet = _WinAPI_SwitchColor(0x999900)
    ElseIf Mod($i, 3) = 0 Then
        $sColSet = _WinAPI_SwitchColor(0x990000)
    EndIf
    If UBound($aLVColors) = 0 Then
        _ArrayAdd($aLVColors, $aColors)
    Else
        _ArrayInsert($aLVColors, 0, $aColors)
    EndIf
    ; Set item colour
    $aColors[0][1] = $sColSet
    _ArrayInsert($aLVColors, 0, $aColors)

Next
_GUICtrlListView_EndUpdate($cLV)
;force the listview to update itself
GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)

ConsoleWrite(StringFormat("Count:  %3d\n", _GUICtrlListView_GetItemCount($cLV)))
;~ Sleep(1000)

; Try deleting an item.
;~ _GUICtrlListView_DeleteItem($cLV, 3)
_ArrayDelete($aLVArray, 3)
_ArrayDelete($aLVColors, 3)
GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)

ConsoleWrite(StringFormat("Count:: %3d\n", _GUICtrlListView_GetItemCount($cLV)))
;~ Sleep(1000)


Local $iNofRows
Local $iDly
; Insert more lines
For $iIx = 1 To 5000
    $iDly = 200

    If $iIx > 20 Then $iDly = 400
    $iNofRows = UBound($aLVArray)
    If $iNofRows > $iGH / 18 + 5 Then
        _ArrayDelete($aLVArray, 0)
        _ArrayDelete($aLVColors, 0)
    EndIf
    GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)

;~  Sleep($iDly) ; Scotty, full speed ahead, warp factor 10 ( https://www.youtube.com/watch?v=AzGVz9cTIpg )
    $sData = StringFormat("Count %3d|Rows %3d|---------|------------|-----------|---------", $iIx, $iNofRows)
    ;_GUIListViewEx_BlockReDraw($iLVIndex, True)
;~     _GUIListViewEx_InsertSpec($iLVIndex, -1, $sData)
;~     _GUIListViewEx_BlockReDraw($iLVIndex, False)
    $aData[0][0] = "Count " & $iIx
    $aData[0][1] = "Rows " & $iNofRows
    $aData[0][2] = "---------"
    $aData[0][3] = "---------"
    $aData[0][4] = "---------"
    $aData[0][5] = "---------"
    _ArrayAdd($aLVArray, $aData)

    $aColors[0][0] = 0xFFFFFF
    $aColors[0][1] = 0xFFFFFF
    $aColors[0][2] = 0xFFFFFF
    $aColors[0][3] = 0xFFFFFF
    $aColors[0][4] = 0xFFFFFF
    $aColors[0][5] = 0xFFFFFF

    $aColors[0][0] = 0
    $aColors[0][1] = 0
    $aColors[0][2] = 0
    $aColors[0][3] = 0
    $aColors[0][4] = 0
    $aColors[0][5] = 0

    _ArrayAdd($aLVColors, $aColors)

    GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)

    Local $iLVItmNo
    $iLVItmNo = UBound($aLVArray) - 1
    ConsoleWrite(StringFormat("Count::: %3d\n", $iLVItmNo))
;~     Sleep($iDly)
;~     _GUIListViewEx_ChangeItem($iLVIndex, $iLVItmNo, 3, _Now())
    $aLVArray[$iLVItmNo][3] = _Now()
;~  GUICtrlSendMsg($cLV, $LVM_REDRAWITEMS, $iLVItmNo, $iLVItmNo)
    GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)
;~     Sleep($iDly)
;~     _GUIListViewEx_SetColour($iLVIndex, ";0x00FF00", $iLVItmNo, 3)
    $aLVColors[$iLVItmNo][3] = 0x009900

    GUICtrlSendMsg($cLV, $LVM_SETITEMCOUNT, UBound($aLVArray), 0)
Next

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Local $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $h_cLV
            Switch $iCode
                ;virtual listview and color change from larsj
                ;https://www.autoitscript.com/forum/topic/168707-listview-item-subitem-background-colour/#comment-1234009
                Case $LVN_GETDISPINFOW
                    ; Fill virtual listview
                    Local $tNMLVDISPINFO = DllStructCreate($tagNMLVDISPINFO, $lParam)
                    If BitAND(DllStructGetData($tNMLVDISPINFO, "Mask"), $LVIF_TEXT) Then ;    vvvvvvvvv    these IF UBound() THEN are needed    vvvvvvvvvvvvvvvvvv
                        If DllStructGetData($tNMLVDISPINFO, "Item") < UBound($aLVArray) And DllStructGetData($tNMLVDISPINFO, "SubItem") < UBound($aLVArray, 2) Then
                            Local $sItem = $aLVArray[DllStructGetData($tNMLVDISPINFO, "Item")][DllStructGetData($tNMLVDISPINFO, "SubItem")]
                            DllStructSetData($tText, 1, $sItem)
                            DllStructSetData($tNMLVDISPINFO, "TextMax", StringLen($sItem))
                            DllStructSetData($tNMLVDISPINFO, "Text", DllStructGetPtr($tText))
                        Else
                            ConsoleWrite('! GETDISPINFOW ! ' & DllStructGetData($tNMLVDISPINFO, "Item") & ' , ' & DllStructGetData($tNMLVDISPINFO, "SubItem") & @CRLF)
                        EndIf
                    EndIf

                Case $NM_CUSTOMDRAW
                    Local $tNMLVCUSTOMDRAW = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
                    Local $dwDrawStage = DllStructGetData($tNMLVCUSTOMDRAW, "dwDrawStage")

                    Switch $dwDrawStage              ; Holds a value that specifies the drawing stage

                        Case $CDDS_PREPAINT
                            ; Before the paint cycle begins
                            Return $CDRF_NOTIFYITEMDRAW ; Notify the parent window of any item-related drawing operations

                        Case $CDDS_ITEMPREPAINT
                            ; Before painting an item
                            Return $CDRF_NOTIFYSUBITEMDRAW ; Notify the parent window of any subitem-related drawing operations

                        Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM)
                            ; Before painting a subitem
                            ;Local $iItem = DllStructGetData($tNMLVCUSTOMDRAW, "dwItemSpec")                ; Item index
                            ;Local $iSubItem = DllStructGetData($tNMLVCUSTOMDRAW, "iSubItem")               ; Subitem index
                            ;DllStructSetData( $tNMLVCUSTOMDRAW, "ClrTextBk", $aColors[$iItem][$iSubItem] ) ; Backcolor of item/subitem
                            If DllStructGetData($tNMLVCUSTOMDRAW, "dwItemSpec") < UBound($aLVColors) And DllStructGetData($tNMLVCUSTOMDRAW, "iSubItem") < UBound($aLVColors) Then
                                DllStructSetData($tNMLVCUSTOMDRAW, "ClrTextBk", $aLVColors[DllStructGetData($tNMLVCUSTOMDRAW, "dwItemSpec")][DllStructGetData($tNMLVCUSTOMDRAW, "iSubItem")])
                            Else  ;    vvvvvvvvv    these IF UBound() THEN are needed    vvvvvvvvvvvvvvvvvv
                                ConsoleWrite('! repaint ! ' & DllStructGetData($tNMLVCUSTOMDRAW, "dwItemSpec") & ' , ' & DllStructGetData($tNMLVCUSTOMDRAW, "iSubItem") & @CRLF)
                            EndIf
                            Return $CDRF_NEWFONT     ; $CDRF_NEWFONT must be returned after changing font or colors

                    EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
    #forceref $hWnd, $iMsg, $wParam
EndFunc   ;==>WM_NOTIFY

 

I have a wheel mouse and I tend to spin it. Is a metal one   so it rotates on its own and the momentum brakes the code. So I added If then to save the code from random OMG, wtf moments :)  

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...