qsek Posted August 3, 2009 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
Authenticity Posted August 4, 2009 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. >_
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