Zedna Posted August 31, 2011 Share Posted August 31, 2011 How to get color of row previously created by GUICtrlCreateListViewItem() + GUICtrlSetColor()? #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> GUICreate("listview items", 220, 250, 100, 200) $listview = GUICtrlCreateListView("col1 |col2|col3 ", 10, 10, 200, 150) $button = GUICtrlCreateButton("Value?", 75, 170, 70, 20) $item1 = GUICtrlCreateListViewItem("item2|col22|col23", $listview) GUICtrlSetColor(-1, 0xff0000) $item3 = GUICtrlCreateListViewItem("item3|col32|col33", $listview) GUISetState() Do $msg = GUIGetMsg() Select Case $msg = $button MsgBox(0, "listview row color", '???') EndSelect Until $msg = $GUI_EVENT_CLOSE Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
Valuater Posted August 31, 2011 Share Posted August 31, 2011 (edited) I would think it's better to use.... MsgBox(4160, "Information", "Back Color ....: " & _GUICtrlListView_GetBkColor($hListView) & @CRLF & _ "Text Color ....: " & _GUICtrlListView_GetTextColor($hListView) & @CRLF & _ "Text Back Color: " & _GUICtrlListView_GetTextBkColor($hListView)) 8) EDIT, I thought it would give you the color you wanted....Was working on it... got close but have to leave Sorry, that was not the answer you wanted. Edited September 1, 2011 by Valuater Link to comment Share on other sites More sharing options...
Spiff59 Posted September 1, 2011 Share Posted September 1, 2011 Whether there is something that involves fun stuff like _SendMessage() or DllStructGetData() that would get you your required info I can't say. What does come to mind is, if you are creating the listview, can you not maintain a small array with an entry for each row of the listview containing your color info, and reference that later when a row is clicked? Not an option for you? Link to comment Share on other sites More sharing options...
UEZ Posted September 1, 2011 Share Posted September 1, 2011 (edited) Look here: Example_LV_Format1.1.au3 shows how to read the color value. Br,UEZ Edited September 1, 2011 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
Zedna Posted September 1, 2011 Author Share Posted September 1, 2011 (edited) I would think it's better to use.... MsgBox(4160, "Information", "Back Color ....: " & _GUICtrlListView_GetBkColor($hListView) & @CRLF & _ "Text Color ....: " & _GUICtrlListView_GetTextColor($hListView) & @CRLF & _ "Text Back Color: " & _GUICtrlListView_GetTextBkColor($hListView)) 8) EDIT, I thought it would give you the color you wanted....Was working on it... got close but have to leave Sorry, that was not the answer you wanted. This is for coloring whole ListView not for row in ListView. Whether there is something that involves fun stuff like _SendMessage() or DllStructGetData() that would get you your required info I can't say. What does come to mind is, if you are creating the listview, can you not maintain a small array with an entry for each row of the listview containing your color info, and reference that later when a row is clicked? Not an option for you? Yes of course I thought about this as about workaround but I prefer to use some clever API function call as better solution. I investigated in ListView's examples about coloring columns to see what API is used but all examples use NM_CUSTOMDRAW notification where are related structures with clrText property. But When I need to get color of existing row and probably can't use these structures or I don't know how. CUSTOMDRAW column coloring example http://www.autoitscript.com/forum/index....=&showtopic=71681&view=findpos Edited September 1, 2011 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
Spiff59 Posted September 1, 2011 Share Posted September 1, 2011 (edited) Yes of course I thought about this as about workaround but I prefer to use some clever API function call as better solution.I investigated in ListView's examples about coloring columns to see what API is used but all examples use NM_CUSTOMDRAW notification where are related structures with clrText property.But When I need to get color of existing row and probably can't use these structures or I don't know how.That seems to be the standard method, intercepting WM_NOTIFY and NM_CUSTOMDRAW to individually set subitems via clrText and clrTextBk. I had one script a couple years ago that set a subitems color to red on one of about 6 different error conditions. When a user made a choice to clear the error, I didn't want to run through all 6 error tests to determine if it was red, so went on the same search you're on. I was unable to find any example of direclty querying the API to return a structure with the pertinent data. It appears Melba23's UDF, that UEZ pointed out, uses _GUICtrlListView_SetItemParam() to embed extra info in the listview item and _GUICtrlListView_GetItemParam() to retrieve it. Edit: PS - in the prior script I mentioned, I just opted for storing the values in an internal array. Edited September 1, 2011 by Spiff59 Link to comment Share on other sites More sharing options...
Zedna Posted September 1, 2011 Author Share Posted September 1, 2011 It appears Melba23's UDF, that UEZ pointed out, uses _GUICtrlListView_SetItemParam() to embed extra info in the listview item and _GUICtrlListView_GetItemParam() to retrieve it. I looked at it and finally it stores all items/columns properties in global array anyway ItemParam store only pointer to structure/array for each item/column.But as far as I know Autoit uses internally ItemParam property for its internal job so if you use nativeGUICtrlCreateListViewItem() then you can't use/overwrite ItemParam structure because Autoit can miss this information.So in case of using ItemParam you must create Listview items by UDF _GUICtrlListView_AddItem() which is unfortunally slower than native one.I prefer not using global array of colors for each row and don't want to use slower UDF for creating ListView items so ItemParam is not way for me either.Is there any way to get color of existing row in ListView created by native GUICtrlCreateListViewItem()?If there will not any soluion I will use global array of colors for each row but I'm curious about some clever simple API solution. Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
UEZ Posted September 1, 2011 Share Posted September 1, 2011 What do you want to achieve? When you set any color you know it already because you can save it in any data structure! Br, UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
Zedna Posted September 1, 2011 Author Share Posted September 1, 2011 (edited) What do you want to achieve? When you set any color you know it already because you can save it in any data structure! My project is viewer with advanced filterig/searching around CSV file(s).I have got global two dimensional array of data parsed from CSV - rows and columns.Color of each row is calculated at time of parsing CSV data so it's stored in this global array (as last column).In GUI there are controls for quick filtering - In Filter() function I go through my global array (rows/columns) and rows which pass filter options add from array to ListView by GUICtrlCreateListViewItem(), some of rows (based on other option "Coloring: ON/OFF") can be colored by GUICtrlSetColor() I need to get color of actual row when I do Export of Listview (filtered) content to XML/HTML output,so in this case I can't use directly global array because in ListView there is only subset of filtered rows,so I must create at each filtering another helper array of filtered rows and their colors (which will slow down each filtering)just for the case of not so often called export to XML/HTML.That's why I would prefer to get color of row from ListView directly at time of export to XML/HTML. I need to keep my Filter() function as fast as possible because there are thousands of rows so filtering should be quick. Edited September 1, 2011 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
UEZ Posted September 1, 2011 Share Posted September 1, 2011 (edited) How about a 3D array where the 3rd dimension holds the color value or even more information? I don't know what the impact is to the speed of a 3D array compared with a 2D array. Br, UEZ Edited September 1, 2011 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
Zedna Posted September 1, 2011 Author Share Posted September 1, 2011 (edited) How about a 3D array where the 3rd dimension holds the color value or even more information? I don't know what the impact is to the speed of a 3D array compared with a 2D array. I fill color as last column in 2D array at the moment I fill 2D array by values from parsed CSV.As I said problem is that Export is done from ListView (not from this array) which is only filtered subset of array. EDIT: I have written workaround with another global helper array of ListView's rows/colors created in my Filter() function when creating ListView itemsand used at time of Export to XML/HTML but as I said it slows down my Filter() function so I prefer some way of getting colors from ListView when doing export. Edited September 1, 2011 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
rover Posted September 1, 2011 Share Posted September 1, 2011 (edited) @Zedna This code is just a curiosity, not a workable solution. Returns the items text and background colours, but one time only. The first time the mouse is hovered over the items the colour is returned,but not on subsequent mouse hovering or if new items are coloured,then the mouse is hovered over the new and previously coloured items. Edit: Why not? expandcollapse popup#include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", 1) Global $GUI = GUICreate("Listview Custom Draw") Global $cListView = GUICtrlCreateListView("Column 1|Column 2|Column 3", 2, 2, 396, 396) _GUICtrlListView_SetTextBkColor($cListView, 0xF0F0F0) _GUICtrlListView_SetBkColor($cListView, 0xF0F0F0) For $i = 1 To 30 GUICtrlCreateListViewItem("Row" & $i & ": Col 1|Row" & $i & ": Col 2|Row" & $i & ": Col 3", $cListView) Next GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() Global $ctrlID = _GUICtrlListView_GetItemParam($cListView, 4) GUICtrlSetColor($ctrlID, 0x5A5B5C) GUICtrlSetBkColor($ctrlID, 0xDDDD07) $ctrlID = _GUICtrlListView_GetItemParam($cListView, 6) GUICtrlSetColor($ctrlID, 0xFBFBFB) GUICtrlSetBkColor($ctrlID, 0x494949) Sleep(3000) __GUICtrlListView_HoverItem($cListView, 4) __GUICtrlListView_HoverItem($cListView, 6) Sleep(3000) Global $ctrlID = _GUICtrlListView_GetItemParam($cListView, 8) GUICtrlSetColor($ctrlID, 0xF9F9F9) GUICtrlSetBkColor($ctrlID, 0x246810) $ctrlID = _GUICtrlListView_GetItemParam($cListView, 9) GUICtrlSetColor($ctrlID, 0xDADADA) GUICtrlSetBkColor($ctrlID, 0x090909) Sleep(3000) __GUICtrlListView_HoverItem($cListView, 4) __GUICtrlListView_HoverItem($cListView, 6) __GUICtrlListView_HoverItem($cListView, 8) __GUICtrlListView_HoverItem($cListView, 9) Do Until GUIGetMsg() = -3 Exit Func __GUICtrlListView_HoverItem($hWnd, $iIndex, $sButton = "left", $fMove = False, $iClicks = 1, $iSpeed = 1) If $Debug_LV Then __UDF_ValidateClassName($hWnd, $__LISTVIEWCONSTANT_ClassName) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) _GUICtrlListView_EnsureVisible($hWnd, $iIndex, False) Local $tRect = _GUICtrlListView_GetItemRectEx($hWnd, $iIndex, $LVIR_LABEL) Local $tPoint = _WinAPI_PointFromRect($tRect, True) $tPoint = _WinAPI_ClientToScreen($hWnd, $tPoint) Local $iX, $iY _WinAPI_GetXYFromPoint($tPoint, $iX, $iY) Local $iMode = Opt("MouseCoordMode", 1) Local $aPos = MouseGetPos() _WinAPI_ShowCursor(False) MouseMove($iX, $iY, 0) MouseMove($aPos[0], $aPos[1], 0) _WinAPI_ShowCursor(True) Opt("MouseCoordMode", $iMode) EndFunc ;==>__GUICtrlListView_HoverItem Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam) Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom") $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $iIDFrom Case $cListView Switch $iCode Case $LVN_DELETEITEM _WinAPI_InvalidateRect($hWndFrom, 0, 0) Case $NM_CUSTOMDRAW Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam) Local $iItem = DllStructGetData($tCustDraw, "dwItemSpec") Switch DllStructGetData($tCustDraw, "dwDrawStage") Case $CDDS_PREPAINT Return BitOR($CDRF_NOTIFYITEMDRAW, $CDRF_NOTIFYPOSTPAINT) Case $CDDS_POSTPAINT Local $iCnt = _GUICtrlListView_GetItemCount($cListView) Local $iTxtCol = "0x" & StringRegExpReplace(Hex(DllStructGetData($tCustDraw, "clrText"), 6), "(.{2})(.{2})(.{2})", "\3\2\1") Local $iBkCol = "0x" & StringRegExpReplace(Hex(DllStructGetData($tCustDraw, "clrTextBk"), 6), "(.{2})(.{2})(.{2})", "\3\2\1") If $iTxtCol <> 0 And $iItem <= $iCnt Then ConsoleWrite('-$iItem: ' & $iItem & " Txt: " & $iTxtCol & " Bk: " & $iBkCol & @CRLF) EndIf EndSwitch EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Edited September 1, 2011 by rover I see fascists... Link to comment Share on other sites More sharing options...
rover Posted September 1, 2011 Share Posted September 1, 2011 each time you add an item using GUICtrlCreateListViewItem() when applying the filter get the items unique ID with _GUICtrlListView_MapIndexToID() and add it to your array when reading from the listview use the ID to identify items that have a colour value in your array I see fascists... Link to comment Share on other sites More sharing options...
Zedna Posted September 2, 2011 Author Share Posted September 2, 2011 @rover Thanks for nice example! Unfortunately this is very ineficient way for many rows because you need to physically redraw listview for each row. I think this your way doesn't work for other then first try because system (Windows) somehow cached once rendered rows and it know rows didn't change - probably. I tried modification of your script to use just RedrawWindow API instead of MouseMove but it doesn't work, anyway here is my script: expandcollapse popup#include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <WindowsConstants.au3> Global $lv_item ; filled before calling WM_NOTIFY Global $lv_color ; filled in WM_NOTIFY Global $GUI = GUICreate("Listview Custom Draw", 300, 400) Global $cListView = GUICtrlCreateListView("Column 1|Column 2|Column 3", 2, 2, 396, 330) Global $hListView = GUICtrlGetHandle($cListView) Global $cbutton = GUICtrlCreateButton("Get colors", 100, 350, 100, 20) For $i = 1 To 15 GUICtrlCreateListViewItem("Row" & $i & ": Col 1|Row" & $i & ": Col 2|Row" & $i & ": Col 3", $cListView) ; some coloring of items $color = 0x0 If Mod($i, 2) Then $color = 0xFF0000 If Not Mod($i, 4) Then $color = 0x0000FF If Not Mod($i, 3) Then $color = 0x00FF00 GUICtrlSetColor(-1, $color) Next GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() While 1 $msg = GUIGetMsg() If $msg = $GUI_EVENT_CLOSE Then ExitLoop If $msg = $cbutton Then GetColors() WEnd Exit Func GetColors() $colors = '' For $i = 1 To _GUICtrlListView_GetItemCount($cListView) $color = GetColor($i) $colors &= 'LV item=' & $i & ' color=' & $color & @CRLF Next MsgBox(0, 'ListView Item Colors', $colors) EndFunc ;==>GetColors Func GetColor($index) $lv_item = $index ; set global variable _GUICtrlListView_EnsureVisible($hListView, $index, False) ;~ _WinAPI_InvalidateRect($hListView, 0, 0) _WinAPI_RedrawWindow($hListView) ; invoke $NM_CUSTOMDRAW $lv_item = -1 Return $lv_color ; read global variable EndFunc ;==>GetColor Func WM_NOTIFY($hWnd, $msg, $wParam, $lParam) Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom") $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $iIDFrom Case $cListView Switch $iCode Case $NM_CUSTOMDRAW Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam) Local $iItem = DllStructGetData($tCustDraw, "dwItemSpec") ;~ $tmp = "0x" & StringRegExpReplace(Hex(DllStructGetData($tCustDraw, "clrText"), 6), "(.{2})(.{2})(.{2})", "\3\2\1") ;~ ConsoleWrite('NM_CUSTOMDRAW iItem: ' & $iItem & " Txt: " & $tmp & @CRLF) Switch DllStructGetData($tCustDraw, "dwDrawStage") Case $CDDS_PREPAINT ;~ $tmp = "0x" & StringRegExpReplace(Hex(DllStructGetData($tCustDraw, "clrText"), 6), "(.{2})(.{2})(.{2})", "\3\2\1") ;~ ConsoleWrite('CDDS_PREPAINT iItem: ' & $iItem & " Txt: " & $tmp & @CRLF) Return BitOR($CDRF_NOTIFYITEMDRAW, $CDRF_NOTIFYPOSTPAINT) Case $CDDS_POSTPAINT ;~ $tmp = "0x" & StringRegExpReplace(Hex(DllStructGetData($tCustDraw, "clrText"), 6), "(.{2})(.{2})(.{2})", "\3\2\1") ;~ ConsoleWrite('CDDS_POSTPAINT iItem: ' & $iItem & " Txt: " & $tmp & @CRLF) If $lv_item <> -1 And $lv_item = $iItem Then $lv_color = "0x" & StringRegExpReplace(Hex(DllStructGetData($tCustDraw, "clrText"), 6), "(.{2})(.{2})(.{2})", "\3\2\1") ;~ ConsoleWrite('-$ 2 iItem: ' & $iItem & " Txt: " & $lv_color & @CRLF) EndIf EndSwitch EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
rover Posted September 2, 2011 Share Posted September 2, 2011 @roverThanks for nice example! Unfortunately this is very ineficient way for many rows because you need to physically redraw listview for each row.I think this your way doesn't work for other then first try because system (Windows) somehow cached once rendered rows and it know rows didn't change - probably. I tried modification of your script to use just RedrawWindow API instead of MouseMove but it doesn't work, anyway here is my script: I couldn't get any of the usual redraw/paint/invalidate methods to work with this.As you can see, most of the items report incorrect colours, and the returned item index from the struct is sometimes a large invalid number.This just isn't a supported feature. be seeing you... I see fascists... 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