tatane

Slow Listview items create

9 posts in this topic

#1 ·  Posted (edited)

Hi,

I've got a problem with the item loading in a listview that is very slow.

Here is a example (which works faster than my main script even if you can see the same problem) :

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

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

$gui = GUICreate("listview items", 500, 500, -1, -1)

$idListview_clic = GUICtrlCreateListView("col", 10, 10, 200, 450, BitOR($LVS_NOSORTHEADER, $LVS_SHOWSELALWAYS, $LVS_SINGLESEL, $LVS_REPORT))
_GUICtrlListView_SetExtendedListViewStyle(GUICtrlGetHandle($idListview_clic), BitOR($LVS_EX_FULLROWSELECT, $WS_EX_CLIENTEDGE))
For $i = 0 To 10
    GUICtrlCreateListViewItem("item", $idListview_clic)
Next

$idListview_flicker = GUICtrlCreateListView("col1|col2|col3  ", 270, 10, 200, 450, BitOR($LVS_NOSORTHEADER, $LVS_SHOWSELALWAYS, $LVS_REPORT))
_GUICtrlListView_SetExtendedListViewStyle(GUICtrlGetHandle($idListview_flicker), BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES, $LVS_EX_GRIDLINES))

$idButton = GUICtrlCreateButton("test", 230, 470, 70, 20)

GUISetState(@SW_SHOW)


While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop

        Case $idButton
            _generate($idListview_flicker)

    EndSwitch
WEnd



Func _generate($idLV)
    $depart = TimerInit()
    _GUICtrlListView_DeleteAllItems($idLV)
    For $i = 0 To 30
        $idItem1 = GUICtrlCreateListViewItem("item"&$i&"|col22|col23", $idLV)
    Next
    ConsoleWrite("temps = "&TimerDiff($depart)&@CRLF)
EndFunc


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    ; $iwParam : The identifier of the common control sending the message. This identifier is not guaranteed to be unique. An application should use the hwndFrom or idFrom member of the NMHDR structure (passed as the lParam parameter) to identify the control.
    ; $ilParam : A pointer to an NMHDR structure that contains the notification code and additional information.
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) ; handle du control qui envoie le message
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")          ; identifier du control
    $iCode = DllStructGetData($tNMHDR, "Code")              ; code de notification du message

    $h_Listview = GUICtrlGetHandle($idListview_clic)

    ; selon le control sur lequel il y a un événement...
    Switch $hWndFrom
        Case $h_Listview
            Switch $iCode
                Case $NM_CLICK
                    _generate($idListview_flicker)

            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

So, when the items of the Listview on the right side are generated, the total duration is different if it's launched from WM_NOTIFY() or by the button click in the main loop.

GUICtrlCreateListViewItem() is 2 times slower. In my main script, it is even worse (6ms -> 402ms) and of course I've got flickering !

I tried with _beginupdate()/_endupdate(), it's better but another bug appears with the  listview header not refreshing correctly sometimes (in my main script)...

Any idea how I can fix this ?

Edited by tatane

Share this post


Link to post
Share on other sites



Generating array and adding with _GUICtrlListView_AddArray is faster.

Share this post


Link to post
Share on other sites

Yep I know. The problem is that I need the ID of each created items. :(

Share this post


Link to post
Share on other sites

Can't you do it this way:

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

$gui = GUICreate("listview items", 500, 500, -1, -1)

$idListview_clic = GUICtrlCreateListView("col", 10, 10, 200, 450, BitOR($LVS_NOSORTHEADER, $LVS_SHOWSELALWAYS, $LVS_SINGLESEL, $LVS_REPORT))
_GUICtrlListView_SetExtendedListViewStyle(GUICtrlGetHandle($idListview_clic), BitOR($LVS_EX_FULLROWSELECT, $WS_EX_CLIENTEDGE))
$item0 = GUICtrlCreateListViewItem("item", $idListview_clic)
For $i = 0 To 9
    GUICtrlCreateListViewItem("item", $idListview_clic)
Next

$idListview_flicker = GUICtrlCreateListView("col1|col2|col3  ", 270, 10, 200, 450, BitOR($LVS_NOSORTHEADER, $LVS_SHOWSELALWAYS, $LVS_REPORT))
_GUICtrlListView_SetExtendedListViewStyle(GUICtrlGetHandle($idListview_flicker), BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES, $LVS_EX_GRIDLINES))

$idButton = GUICtrlCreateButton("test", 230, 470, 70, 20)

GUISetState(@SW_SHOW)


While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop

        Case $idButton, $item0 To $item0 + 10
            _generate($idListview_flicker)

    EndSwitch
WEnd


Func _generate($idLV)
    Local Static $idItem1
    $depart = TimerInit()
    _GUICtrlListView_BeginUpdate($idLV)
    If $idItem1 Then
      For $i = 0 To 30
        GUICtrlDelete($idItem1+$i)
      Next
    EndIf
    $idItem1 = GUICtrlCreateListViewItem("item0"&"|col22|col23", $idLV)
    For $i = 1 To 30
      GUICtrlCreateListViewItem("item"&$i&"|col22|col23", $idLV)
    Next
    _GUICtrlListView_EndUpdate($idLV)
    ConsoleWrite("temps = "&TimerDiff($depart)&@CRLF)
EndFunc

 

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Unfortunatly no. I need WM_NOTIFY to change partial subitem colors, right click & context menu, ... and the most important is when I click an item in the left listview, it loads different items in the right one.

It seems repainting the listview while in the WM_NOTIFY function is faster (handled differently ?) than main loop.

Edited by tatane

Share this post


Link to post
Share on other sites
3 hours ago, tatane said:

Yep I know. The problem is that I need the ID of each created items. :(

Why need ID?

In advanced GuiGetMsg-Modus the ID is part of returned array. In GuiOnEvent-Modus @GUI_CtrlId can be used. 

Share this post


Link to post
Share on other sites

Getting or not the items ID is not relative to my problem. I'm wondering why there is such a difference in generating listview items duration when it's called inside WM_NOTIFY or the main loop.

Share this post


Link to post
Share on other sites

Yep it's working with this example but it's flickering once after the UNLOCK in my main script.

Share this post


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