qsek Posted August 3, 2009 Share Posted August 3, 2009 I am experimenting lately with Virtual Listviews and i am wondering if there is a possibility to make repeated mass updates of many LV items (Item Color, value, icon) more CPU friendly and faster. Would subclassing be an option or using a custom external Dll? This is what i got so far: expandcollapse popup;~ #include <_GUICtrlListView.au3> #include <WindowsConstants.au3> #include <GuiListView.au3> #Include <GuiImageList.au3> #include <GUIConstants.au3> Global $switch = 0 Global $tTextBufferV, $sSeparatorV,$aArrayV[1] $sTextBuff = "char[100]" If Execute("@Unicode") Then $sTextBuff = "w" & $sTextBuff $tTextBufferV = DllStructCreate($sTextBuff) Global $iNum = 23 $change = 23 $width = 4 Dim $aArrayV[$iNum][$width+1] #Region ### START Koda GUI section ### Form= $Form1 = GUICreate("Form1", 750, 590, 191, 113) $hImage = _GUIImageList_Create(16,16,5) $I_blank = _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 110) $I_comstar = _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 131) ;~ Global const $LVS_OWNERDATA=0x1000 $ListView1 = GUICtrlCreateListView("ID|1 |2 |3 |4 ", 2, 120, 363, 431, $LVS_SHOWSELALWAYS + $LVS_OWNERDATA, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_GRIDLINES, $LVS_EX_TRACKSELECT, $LVS_EX_SUBITEMIMAGES)) $hhLV = GUICtrlGetHandle($ListView1) GUICtrlSendMsg(-1, 0x101E, 0, 100) GUICtrlSendMsg($ListView1, $LVM_SETITEMCOUNT, $iNum, 0) ;;set total item count - necessary for virtual lv _SendMessage($hhLV, $LVM_SETIMAGELIST, $LVSIL_SMALL, $hImage, 0, "wparam", "hwnd", "hwnd") $ListView2 = GUICtrlCreateListView("ID|1 |2 |3 |4 ", 121*3+15, 120, 121*3, 431, $LVS_SHOWSELALWAYS + $LVS_OWNERDATA, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_CLIENTEDGE, $LVS_EX_DOUBLEBUFFER, $LVS_EX_GRIDLINES, $LVS_EX_TRACKSELECT, $LVS_EX_SUBITEMIMAGES)) $hhLV2 = GUICtrlGetHandle($ListView2) GUICtrlSendMsg(-1, 0x101E, 0, 100) GUICtrlSendMsg($ListView2, $LVM_SETITEMCOUNT, $iNum, 0) ;;set total item count - necessary for virtual lv _SendMessage($hhLV2, $LVM_SETIMAGELIST, $LVSIL_SMALL, $hImage, 0, "wparam", "hwnd", "hwnd") GUISetState(@SW_SHOW) GUIRegisterMsg($WM_NOTIFY,"_UDF_WM_NOTIFY") #EndRegion ### START Koda GUI section ### Form= $sec = 0 While 1 If Not ($sec = @SEC) Then ; Do every second $switch = Not $switch For $ei = 0 To $change-1 Step 1;$iNum-1 $aArrayV[$ei][0] += 2 For $ej = 1 To $width Step 1 $aArrayV[$ei][$ej] += 1 Next Local $tRect = DllStructCreate($tagRECT) DllStructSetData($tRect, "Left", 3) _SendMessage($hhLV, $LVM_GETITEMRECT, $ei, DllStructGetPtr($tRect), 0, "wparam", "ptr") _WinAPI_InvalidateRect($hhLV,$tRect,false) ;~ Local $tRect = DllStructCreate($tagRECT) ;~ DllStructSetData($tRect, "Left", 3) _SendMessage($hhLV2, $LVM_GETITEMRECT, $ei, DllStructGetPtr($tRect), 0, "wparam", "ptr") _WinAPI_InvalidateRect($hhLV2,$tRect,false) ; Update one Item after another Next ;~ _WinAPI_InvalidateRect($hhLV,0,false) ;~ _WinAPI_InvalidateRect($hhLV2,0,false) ; Update all Items even if there is no change $sec = @SEC EndIf $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func _startup($iNumF) $width = 6 Local $aStart[$iNum][$width] for $i = 0 to $iNum-1 $aStart[$i][0] = _randString(Random(4,14,1),Asc("A"),Asc("z")) for $j = 1 to $width-1 $aStart[$i][$j] = $i & "|" & $j next next Return $aStart EndFunc ;==>_startup Func _randString($_end = 5, $chrS = 65, $chrE = 90) Local $str = "" For $i = 1 To $_end $str &= Chr(Random($chrS,$chrE,1)) Next Return $str EndFunc Func _UDF_WM_NOTIFY($hWnd, $Msg, $wParam, $lParam) Local $i, $j, $tNMLVDISPINFO, $text, $textlen, $maxlen ;;$WM_NOTIFY = 0x004E ;~ If $Msg <> 0x004E Then Return Local $tNMHDR = DllStructCreate("hwnd hwndfrom;int idfrom;int code", $lParam) Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hwndfrom")) Local $iCode = DllStructGetData($tNMHDR, "code") ;~ ConsoleWrite(Hex($Msg) &", "& $iCode& @CRLF) Switch $hWndFrom Case $hhLV,$hhLV2 Switch $iCode Case -150, -177 ;;$LVN_GETDISPINFOA = -150, $LVN_GETDISPINFOW = -177 ;;give requested items one by one (kinda slow if a lot of items are visible at the same time) $tNMLVDISPINFO = DllStructCreate("hwnd hwndfrom;int idfrom;int code;" & _ "uint mask;int item;int subitem;uint state;uint statemask;ptr text;int textmax;int image;dword lparam;int;uint[5]", $lParam) ;~ If BitAND(DllStructGetData($tNMLVDISPINFO, "mask"), $LVIF_TEXT) Then $i = DllStructGetData($tNMLVDISPINFO, "item") ;~ ConsoleWrite($i&" =? "&DllStructGetData($tNMLVDISPINFO, "item") & @CRLF) $j = DllStructGetData($tNMLVDISPINFO, "subitem") ;~ ConsoleWrite($i&","&$j-1 & @CRLF) $text = $aArrayV[$i][$j] $textlen = StringLen($text) $maxlen = DllStructGetSize($tTextBufferV) ;~ If Execute("@Unicode") Then $maxlen = $maxlen / 2 If $textlen > $maxlen - 1 Then $text = StringLeft($text, $maxlen - 1) DllStructSetData($tTextBufferV, 1, $text) DllStructSetData($tNMLVDISPINFO, "textmax", $textlen) DllStructSetData($tNMLVDISPINFO, "text", DllStructGetPtr($tTextBufferV)) If (Not $j Or $i = 4) And $i < $change Then DllStructSetData($tNMLVDISPINFO, "image", Not($switch)+0) ;~ EndIf Case $NM_CUSTOMDRAW ;~ Return Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam) Local $iDrawStage, $iItem, $iSubitem, $hDC, $tRect $iDrawStage = DllStructGetData($tCustDraw, 'dwDrawStage') ;~ ConsoleWrite("customdraw item("&DllStructGetData($tCustDraw, 'dwItemSpec')&"),drawstage("&$CDDS_ITEMPREPAINT&"):"&$iDrawStage & @CRLF) Switch $iDrawStage Case $CDDS_PREPAINT ; Stage 0: something is about to be drawned Return $CDRF_NOTIFYITEMDRAW ; We want to be informed if an Item is about to be drawned Case $CDDS_ITEMPREPAINT ; Stage 1: an Item is about to be drawned ;~ Return $CDRF_NOTIFYITEMDRAW; We want to be informed if an SUBitem is about to be drawned ;~ Case BitOR($CDDS_ITEMPREPAINT, $CDDS_SUBITEM); Stage 2: an SUBitem is about to be drawned ;~ ConsoleWrite("Subitem" & @CRLF) $iItem = DllStructGetData($tCustDraw, 'dwItemSpec') ;~ $iSubitem = DllStructGetData($tCustDraw, 'iSubItem') ;~ ConsoleWrite($iItem&","&$iSubitem & @CRLF) ;~ If $iSubitem > 1 Then Return ;#### $iSlot = _GUICtrlListView_GetItemParam($nID, $iItem) ###### ;~ $tItem = DllStructCreate($tagLVITEM) ;~ DllStructSetData($tItem, "Mask", $LVIF_PARAM) ;~ DllStructSetData($tItem, "Item", $iItem) ;~ $pItem = DllStructGetPtr($tItem) ;~ GUICtrlSendMsg($wParam, $LVM_GETITEMW, 0, $pItem) ;~ $iSlot = DllStructGetData($tItem, "Param") ;~ ConsoleWrite("$iSlot: "&$iSlot & @CRLF) ;############# ;~ ConsoleWrite($iSlot & @CRLF) ;~ If $PlistArr[$iSlot][0] == "" Or Not ($PlistArr[$iSlot][1] = $iItem) Then Return ; no custom info for this subitem, no change If $switch Or $iItem >= $change Then Return 1 DllStructSetData($tCustDraw, 'clrText', 0x000000) DllStructSetData($tCustDraw, 'clrTextBk', 0xFFFFFF) Else ;~ Return $CDRF_Newfont DllStructSetData($tCustDraw, 'clrText', 0xFFFFFF) DllStructSetData($tCustDraw, 'clrTextBk', 0x000000) ;~ _SetItemCol($nID, $hDC, $tCustDraw, $iItem, $iSubitem); Obsolete, wird alles hier erledigt EndIf Return 1 EndSwitch EndSwitch EndSwitch Return EndFunc Teamspeak 3 User Viewer - Quick and functional TS3 Query script, which shows online users.Cached Screenshot Deleter - Deletes older Fraps Screenshots if they exceed a specified limit.Unresolved Topics:Intercept and modify dragdrop text behaviour in scite Link to comment Share on other sites More sharing options...
Authenticity Posted August 4, 2009 Share Posted August 4, 2009 It seems like there is nothing to subclass. The $WM_NOTIFY is send to the parent GUI window so unless you want to do it in much low-level than you want it seems like all you need is a few sleeps here and there to reduce CPU usage and speeding it up by calling _WinAPI_InvalidateRect($hhLV, 0, False) and _WinAPI_InvalidateRect($hhLV2, 0, False) each second and manipulate the specific items and sub-items in the handler. It'll make more sense to put the loop inside an adlib function in my opinion. You can subclass the control and handle the WM_PAINT in your own way but it'd be much more painful than the way it's now. >_ Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now