Sign in to follow this  
Followers 0
Achilles

Setting the selection color of a listview

19 posts in this topic

I want to set the selection color of a listview... For example, I click a listview item and it turns hot pink instead of blue. Any ideas?

I've tried looking at _GUICtrlListView_SetTextColor, _GUICtrlListView_SetTextBkColor and _GUICtrlListView_SetOutlineColor but the first two of those are for the whole listview and the third isn't what I want.


My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list]

Share this post


Link to post
Share on other sites



I want to set the selection color of a listview... For example, I click a listview item and it turns hot pink instead of blue. Any ideas?

I've tried looking at _GUICtrlListView_SetTextColor, _GUICtrlListView_SetTextBkColor and _GUICtrlListView_SetOutlineColor but the first two of those are for the whole listview and the third isn't what I want.

Here's a basic example (NOTE: coded for 3.2.10.0 (work mandate - we haven't migrated versions yet) so if running 3.2.12.x, you'll likely need to change the GUIContants.au3 include to GUIConstantsEx.au3 if I remember correctly from the change notes):

#include <GUIConstants.au3>
AutoItSetOption("GUIOnEventMode", 1)

$GUITitle = "Listview Item Recolor"
$GUIWidth = 400
$GUIHeight = 300

$GUI = GUICreate($GUITitle, $GUIWidth, $GUIHeight, (@DesktopWidth - $GUIWidth) / 2, (@DesktopHeight - $GUIHeight) / 2)
$listviewStuff = GUICtrlCreateListView("Listview stuff", 10, 10, $GUIWidth - 20, $GUIHeight - 50)
$buttonselected = GUICtrlCreateButton("Tag selected item", 10, $GUIHeight - 30, $GUIWidth - 20, 20)
$iListviewCount = 20
GUICtrlCreateListViewItem("Index 0", $listviewStuff)

For $i = 1 To $iListviewCount
    GUICtrlCreateListViewItem("Index " & $i, $listviewStuff)
Next

GUISetState()

#Region Events list
GUISetOnEvent($GUI_EVENT_CLOSE, "_ExitIt")
GUICtrlSetOnEvent($buttonselected, "_TagSelected")

#EndRegion Events list

While 1
    Sleep(10)
WEnd


Func _ExitIt()
    Exit
EndFunc

Func _TagSelected()
    $selected = GUICtrlRead(GUICtrlRead($listviewStuff))
    GUICtrlSetColor(GUICtrlRead($listviewStuff), 0xff00ff)
    GUICtrlSetBkColor(GUICtrlRead($listviewStuff), 0x00ffff)
    ConsoleWrite($selected & @CRLF)
EndFunc
1 person likes this

- MoChr(77)& Chr(97)& Chr(100)& Chr(101)& Chr(32)& Chr(121)& Chr(97)& Chr(32)& Chr(108)& Chr(111)& Chr(111)& Chr(107)-------I've told you 100,000 times not to exaggerate!-------Don't make me hit you with my cigarette hand...-------My scripts:Random Episode Selector, Keyboard MouseMover, CopyPath v2.1, SmartRename for XP,Window Tracer[sup]New![/sup]

Share this post


Link to post
Share on other sites

Achilles

Solution with ownerdrawing:

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>

Global Const $ODT_LISTVIEW = 102

Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4

Global Const $ODS_SELECTED = 0x0001

$hGUI = GUICreate("Test GUI", 300, 200)

$hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 10, 10, 280, 180, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED))

_GUICtrlListView_SetExtendedListViewStyle($hListView, $LVS_EX_FULLROWSELECT)

For $i = 1 To 10
    _GUICtrlListView_AddItem($hListView, "Item " & $i)
    _GUICtrlListView_AddSubItem($hListView, $i - 1, "SubItem " & $i, 1)
Next

GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")

GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
    Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected
    
    $tagDRAWITEMSTRUCT = DllStructCreate("uint cType;uint cID;uint itmID;uint itmAction;uint itmState;" & _
                                         "hwnd hItm;hwnd hDC;int itmRect[4];dword itmData", $lParam)
                                         
    If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
    
    $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")
    $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")
    $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")
    $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")
    $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")
    $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")
    
    $bSelected = BitAND($itmState, $ODS_SELECTED)
    
    Switch $itmAction
        Case $ODA_DRAWENTIRE
            If $itmState = $bSelected Then
                $iBrushColor = 0xFFFFFF
            Else
                $iBrushColor = 0x0000FF
            EndIf
            
            Local $aBrush = DLLCall("gdi32.dll","hwnd","CreateSolidBrush", "int", $iBrushColor)
            
            Local $aBrushOld = _WinAPI_SelectObject($hDC, $aBrush[0])
            
            Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
            DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 5, 1)
            
            _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])
            
            _WinAPI_SelectObject($hDC, $aBrushOld)
            
            _WinAPI_DeleteObject($aBrush[0])
            
            Local $itmText = _GUICtrlListView_GetItemText($hListView, $itmID)

            DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1) + 2, 1)
            
            DllCall("user32.dll", "int", "DrawText", "hwnd", $hDC, "str", $itmText, "int", StringLen($itmText), _
                    "ptr", DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), "int", $DT_LEFT)
                    
            Local $iSubItmText = _GUICtrlListView_GetItemText($hListView, $itmID, 1)
            Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hListView, $itmID, 1)
            
            Local $iSubItmRect = DllStructCreate("int[4]")
            
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[0], 1)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[1], 2)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[2], 3)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[3], 4)
            
            DllCall("user32.dll", "int", "DrawText", "hwnd", $hDC, "str", $iSubItmText, "int", StringLen($iSubItmText), _
                    "ptr", DllStructGetPtr($iSubItmRect), "int", $DT_LEFT)
    EndSwitch
    
    Return $GUI_RUNDEFMSG
EndFunc

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Thanks rasim. This will come in handy.

Edit:

Hmm, how would I make this work so that any checked items ($LVS_EX_CHECKBOXES) would stay highlighted?

Right now I'm using WM_NOTIFY to check checkboxes if a row is clicked. How would I integrate the above code so that when the row is clicked, and the item is checked, the row stays highlighted as long as it is checked?

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) ;Detects clicks in the list view, and checks checkboxes ------------------------------------------------------------------o
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo
    $hWndListView = $list
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $NM_CLICK ;Sent by a list view control when the user clicks/dbl clicks an item with the left mouse button
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    If DllStructGetData($tInfo, "Index") <> -1 Then ;If index returned is not -1 (which it is, if user clicks in an unfilled part of the listbox)
                        If _GUICtrlListView_GetItemChecked($xlist, DllStructGetData($tInfo, "Index")) Then ;If item checked
                            _GUICtrlListView_SetItemChecked($xlist, DllStructGetData($tInfo, "Index"), False) ;Uncheck the item when clicked
                        Else
                            _GUICtrlListView_SetItemChecked($xlist, DllStructGetData($tInfo, "Index"), True) ;otherwise, check it
                        EndIf
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc ;WM_NOTIFY
Edited by v3rt1g0

Share this post


Link to post
Share on other sites

v3rt1g0

Rough example (trick):

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>

Global Const $ODT_LISTVIEW = 102

Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4

Global Const $ODS_SELECTED = 0x0001

Global $aBitmap[10]

$hGUI = GUICreate("Test GUI", 300, 220)

$hListView = GUICtrlCreateListView("Items|SubItems", 10, 10, 280, 200, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED), $LVS_EX_CHECKBOXES)

For $i = 1 To 10
    GUICtrlCreateListViewItem("Item " & $i & "|" & "SubItem " & $i, $hListView)
Next

_GDIPlus_Startup()

$hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\CheckOff.bmp")

$hBitmap2 = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\CheckOn.bmp")

$hDC = _WinAPI_GetDC($hGUI)

$hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC)

_GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 10, 49)

_WinAPI_ReleaseDC($hGUI, $hDC)

For $i = 0 To UBound($aBitmap) - 1
    $aBitmap[$i] = $hBitmap
Next

GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

;Release objects
_GDIPlus_ImageDispose($hBitmap)
_GDIPlus_ImageDispose($hBitmap2)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()

Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
    Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected
    
    $tagDRAWITEMSTRUCT = DllStructCreate("uint cType;uint cID;uint itmID;uint itmAction;uint itmState;" & _
                                         "hwnd hItm;hwnd hDC;int itmRect[4];dword itmData", $lParam)
                                         
    If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
    
    $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")
    $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")
    $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")
    $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")
    $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")
    $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")
    
    $bSelected = BitAND($itmState, $ODS_SELECTED)
    
    Switch $itmAction
        Case $ODA_DRAWENTIRE
            If $itmState = $bSelected Then
                $iBrushColor = 0xFFFFFF
            Else
                $iBrushColor = 0x0000FF
            EndIf
            
            Local $aBrush = DLLCall("gdi32.dll","hwnd","CreateSolidBrush", "int", $iBrushColor)
            
            Local $aBrushOld = _WinAPI_SelectObject($hDC, $aBrush[0])
            
            Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
            DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 15, 1)
            
            _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])
            
            _WinAPI_SelectObject($hDC, $aBrushOld)
            
            _WinAPI_DeleteObject($aBrush[0])
            
            Local $itmText = _GUICtrlListView_GetItemText($hListView, $itmID)

            DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1) + 2, 1)
            
            DllCall("user32.dll", "int", "DrawText", "hwnd", $hDC, "str", $itmText, "int", StringLen($itmText), _
                    "ptr", DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), "int", $DT_LEFT)
                    
            Local $iSubItmText = _GUICtrlListView_GetItemText($hListView, $itmID, 1)
            Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hListView, $itmID, 1)
            
            Local $iSubItmRect = DllStructCreate("int[4]")
            
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + 10, 1)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[1], 2)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[2], 3)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[3], 4)
            
            DllCall("user32.dll", "int", "DrawText", "hwnd", $hDC, "str", $iSubItmText, "int", StringLen($iSubItmText), _
                    "ptr", DllStructGetPtr($iSubItmRect), "int", $DT_LEFT)
            
            $iImageLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
            $iImageTop = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 2)
            
            _GDIPlus_GraphicsDrawImage($hGraphic, $aBitmap[$itmID], $iImageLeft - 7, $iImageTop + 11)
    EndSwitch
    
    Return $GUI_RUNDEFMSG
EndFunc

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    Local $tNMHDR, $iIDFrom, $iCode
    
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    
    Switch $iIDFrom
        Case $hListView
            Switch $iCode
                Case $NM_CLICK
                    Local $tInfo = DllStructCreate($tagNMLISTVIEW, $lParam)
                    Local $iItem = DllStructGetData($tInfo, "Item")
                    
                    Local $tPoint = _WinAPI_GetMousePos(True, $hGUI)
                    Local $iX = DllStructGetData($tPoint, "X")
                    Local $iY = DllStructGetData($tPoint, "Y")
                    
                    If ($iItem <> -1) And ($iX < 22) Then
                        If $aBitmap[$iItem] = $hBitmap Then
                            $aBitmap[$iItem] = $hBitmap2
                            ConsoleWrite("-> Item " & $iItem + 1 & " checked" & @LF)
                        Else
                            $aBitmap[$iItem] = $hBitmap
                            ConsoleWrite("-> Item " & $iItem + 1 & " unchecked" & @LF)
                        EndIf
                        _WinAPI_RedrawWindow(GUICtrlGetHandle($hListView), 0, 0, $RDW_INVALIDATE)
                    EndIf
            EndSwitch
    EndSwitch
    
    Return $GUI_RUNDEFMSG
EndFunc

img.zip

Share this post


Link to post
Share on other sites

Thanks rasim.

I tried your code, but the rows do not stay highlighted in red when they have a checkbox filled.

Somewhere in the function, I'm wondering if there's some way I can do the equivlent of:

If _GUICtrlListView_GetItemChecked($xlist, DllStructGetData($tInfo, "Index")) Then 'Don't Redraw a White Rect'.

Usually the function will only draw the selected item, but maybe there's a way to leave the previous item in a drawn state when a new item is selected?

Share this post


Link to post
Share on other sites

v3rt1g0

Mmm...try this:

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>

Global Const $ODT_LISTVIEW = 102

Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4

Global Const $ODS_SELECTED = 0x0001

Global $aBitmap[10]

$hGUI = GUICreate("Test GUI", 300, 220)

$hListView = GUICtrlCreateListView("Items|SubItems", 10, 10, 280, 200, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED), $LVS_EX_CHECKBOXES)

For $i = 1 To 10
    GUICtrlCreateListViewItem("Item " & $i & "|" & "SubItem " & $i, $hListView)
Next

_GDIPlus_Startup()

$hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\CheckOff.bmp")

$hBitmap2 = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\CheckOn.bmp")

$hDC = _WinAPI_GetDC($hGUI)

$hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC)

_GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 10, 49)

_WinAPI_ReleaseDC($hGUI, $hDC)

For $i = 0 To UBound($aBitmap) - 1
    $aBitmap[$i] = $hBitmap
Next

GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

;Release objects
_GDIPlus_ImageDispose($hBitmap)
_GDIPlus_ImageDispose($hBitmap2)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()

Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
    Local $tagDRAWITEMSTRUCT, $iBrushColor = 0xFFFFFF, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected
    
    $tagDRAWITEMSTRUCT = DllStructCreate("uint cType;uint cID;uint itmID;uint itmAction;uint itmState;" & _
                                         "hwnd hItm;hwnd hDC;int itmRect[4];dword itmData", $lParam)
                                         
    If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
    
    $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")
    $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")
    $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")
    $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")
    $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")
    $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")
    
    $bSelected = BitAND($itmState, $ODS_SELECTED)
    
    Switch $itmAction
        Case $ODA_DRAWENTIRE
            ;If $itmState = $bSelected Then
                ;$iBrushColor = 0xFFFFFF
            ;Else
                If $aBitmap[$itmID] = $hBitmap2 Then
                    $iBrushColor = 0x0000FF
                Else
                    $iBrushColor = 0xFFFFFF
                EndIf
            ;EndIf
            
            Local $aBrush = DLLCall("gdi32.dll","hwnd","CreateSolidBrush", "int", $iBrushColor)
            
            Local $aBrushOld = _WinAPI_SelectObject($hDC, $aBrush[0])
            
            Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
            DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 15, 1)
            
            _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])
            
            _WinAPI_SelectObject($hDC, $aBrushOld)
            
            _WinAPI_DeleteObject($aBrush[0])
            
            Local $itmText = _GUICtrlListView_GetItemText($hListView, $itmID)

            DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1) + 2, 1)
            
            DllCall("user32.dll", "int", "DrawText", "hwnd", $hDC, "str", $itmText, "int", StringLen($itmText), _
                    "ptr", DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), "int", $DT_LEFT)
                    
            Local $iSubItmText = _GUICtrlListView_GetItemText($hListView, $itmID, 1)
            Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hListView, $itmID, 1)
            
            Local $iSubItmRect = DllStructCreate("int[4]")
            
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + 10, 1)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[1], 2)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[2], 3)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[3], 4)
            
            DllCall("user32.dll", "int", "DrawText", "hwnd", $hDC, "str", $iSubItmText, "int", StringLen($iSubItmText), _
                    "ptr", DllStructGetPtr($iSubItmRect), "int", $DT_LEFT)
            
            $iImageLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
            $iImageTop = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 2)
            
            _GDIPlus_GraphicsDrawImage($hGraphic, $aBitmap[$itmID], $iImageLeft - 7, $iImageTop + 11)
    EndSwitch
    
    Return $GUI_RUNDEFMSG
EndFunc

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    Local $tNMHDR, $iIDFrom, $iCode
    
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    
    Switch $iIDFrom
        Case $hListView
            Switch $iCode
                Case $NM_CLICK
                    Local $tInfo = DllStructCreate($tagNMLISTVIEW, $lParam)
                    Local $iItem = DllStructGetData($tInfo, "Item")
                    
                    Local $tPoint = _WinAPI_GetMousePos(True, $hGUI)
                    Local $iX = DllStructGetData($tPoint, "X")
                    Local $iY = DllStructGetData($tPoint, "Y")
                    
                    If ($iItem <> -1) And ($iX < 22) Then
                        If $aBitmap[$iItem] = $hBitmap Then
                            $aBitmap[$iItem] = $hBitmap2
                            ConsoleWrite("-> Item " & $iItem + 1 & " checked" & @LF)
                        Else
                            $aBitmap[$iItem] = $hBitmap
                            ConsoleWrite("-> Item " & $iItem + 1 & " unchecked" & @LF)
                        EndIf
                        _WinAPI_RedrawWindow(GUICtrlGetHandle($hListView), 0, 0, $RDW_INVALIDATE)
                    EndIf
            EndSwitch
    EndSwitch
    
    Return $GUI_RUNDEFMSG
EndFunc

Share this post


Link to post
Share on other sites

That's perfect :P

Many thanks rasim!

Share this post


Link to post
Share on other sites

Achilles

Solution with ownerdrawing:

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>

Global Const $ODT_LISTVIEW = 102

Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4

Global Const $ODS_SELECTED = 0x0001

$hGUI = GUICreate("Test GUI", 300, 200)

$hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 10, 10, 280, 180, BitOR($LVS_REPORT, $LVS_OWNERDRAWFIXED))

_GUICtrlListView_SetExtendedListViewStyle($hListView, $LVS_EX_FULLROWSELECT)

For $i = 1 To 10
    _GUICtrlListView_AddItem($hListView, "Item " & $i)
    _GUICtrlListView_AddSubItem($hListView, $i - 1, "SubItem " & $i, 1)
Next

GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")

GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
    Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected
    
    $tagDRAWITEMSTRUCT = DllStructCreate("uint cType;uint cID;uint itmID;uint itmAction;uint itmState;" & _
                                         "hwnd hItm;hwnd hDC;int itmRect[4];dword itmData", $lParam)
                                         
    If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
    
    $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")
    $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")
    $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")
    $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")
    $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")
    $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")
    
    $bSelected = BitAND($itmState, $ODS_SELECTED)
    
    Switch $itmAction
        Case $ODA_DRAWENTIRE
            If $itmState = $bSelected Then
                $iBrushColor = 0xFFFFFF
            Else
                $iBrushColor = 0x0000FF
            EndIf
            
            Local $aBrush = DLLCall("gdi32.dll","hwnd","CreateSolidBrush", "int", $iBrushColor)
            
            Local $aBrushOld = _WinAPI_SelectObject($hDC, $aBrush[0])
            
            Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
            DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 5, 1)
            
            _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush[0])
            
            _WinAPI_SelectObject($hDC, $aBrushOld)
            
            _WinAPI_DeleteObject($aBrush[0])
            
            Local $itmText = _GUICtrlListView_GetItemText($hListView, $itmID)

            DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1) + 2, 1)
            
            DllCall("user32.dll", "int", "DrawText", "hwnd", $hDC, "str", $itmText, "int", StringLen($itmText), _
                    "ptr", DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), "int", $DT_LEFT)
                    
            Local $iSubItmText = _GUICtrlListView_GetItemText($hListView, $itmID, 1)
            Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hListView, $itmID, 1)
            
            Local $iSubItmRect = DllStructCreate("int[4]")
            
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[0], 1)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[1], 2)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[2], 3)
            DllStructSetData($iSubItmRect, 1, $aSubItmRect[3], 4)
            
            DllCall("user32.dll", "int", "DrawText", "hwnd", $hDC, "str", $iSubItmText, "int", StringLen($iSubItmText), _
                    "ptr", DllStructGetPtr($iSubItmRect), "int", $DT_LEFT)
    EndSwitch
    
    Return $GUI_RUNDEFMSG
EndFunc
I can't seem to get this to work with multiple items selected, can it? Also, when you select one item why does it appear to have more selection area on the bottom then on the top? Basically, the text isn't centered vertically in the selected rectangle, is that fixable?

My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list]

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Ugh, it should be possible. I found this on the MSDN library, I don't have any idea how to implement it though.

Edit: I bet all it is a simple GUICtrlSendMsg(), but I don't know what the code would be... I looked through the ListView constants and there's definitely some that haven't been used yet.. The numbering goes up to 210 but there's not 210 constants.

Edited by Achilles

My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list]

Share this post


Link to post
Share on other sites

Raism

The solution you posted for changing the "blue bar" selected listview item color is GREATLY appreciated. My original search of forums didn't turn up this thread, so I spent a couple of hours Googling and read details about the owner drawn method, but sure wasn't looking forward to attempting to implement it in AutoIt!

You have saved me HOURS of work, so again, thank you!

I have also been trying to figure out a couple of other things:

1. How to get the current selection color (which may or may not be "blue", depending on the windows theme. After researching this on MSDN, it "appeared" as simple as:

_WinAPI_GetSysColor ($COLOR_HOTLIGHT)

which returns a color, but not the right color. I tried numerous of the other GetSysColor constants, but none of them return the typical "blue bar" color. I even tried the GetThemeSysColor function, but still couldn't retrieve the correct color. Do you have any ideas on this?

2. The other item I've been researching is how to change the color of the Listview scroll bar, but I'm not sure it can be done -- I already tried the SetSystemMetrics function and that didn't work for the Listview scoll bar. I posted a question on how to do this a couple of months ago and had zero replies, so it seems it has never been done in AutoIt. If you have any ideas how to approach this, I'd appreciate the tip.

Thanks again for your contribution.

Share this post


Link to post
Share on other sites

Raism

The solution you posted for changing the "blue bar" selected listview item color is GREATLY appreciated. My original search of forums didn't turn up this thread, so I spent a couple of hours Googling and read details about the owner drawn method, but sure wasn't looking forward to attempting to implement it in AutoIt!

You have saved me HOURS of work, so again, thank you!

I have also been trying to figure out a couple of other things:

1. How to get the current selection color (which may or may not be "blue", depending on the windows theme. After researching this on MSDN, it "appeared" as simple as:

_WinAPI_GetSysColor ($COLOR_HOTLIGHT)

which returns a color, but not the right color. I tried numerous of the other GetSysColor constants, but none of them return the typical "blue bar" color. I even tried the GetThemeSysColor function, but still couldn't retrieve the correct color. Do you have any ideas on this?

2. The other item I've been researching is how to change the color of the Listview scroll bar, but I'm not sure it can be done -- I already tried the SetSystemMetrics function and that didn't work for the Listview scoll bar. I posted a question on how to do this a couple of months ago and had zero replies, so it seems it has never been done in AutoIt. If you have any ideas how to approach this, I'd appreciate the tip.

Thanks again for your contribution.

don't know about changing listview scrollbar, nothing on the forum with this search term: 'listview "scrollbar color"'

at a glance some links turned up on Google

the highlight colour is BGR

_WinAPI_GetSysColor($COLOR_HIGHLIGHT)

Cheers

#include <GUIConstantsEX.au3>
#include <WindowsConstants.au3>

#include <WinAPI.au3>

Opt('MustDeclareVars', 1)

Local $msg
Local $iColHilite = _WinAPI_GetSysColor($COLOR_HIGHLIGHT); RGB
GUICreate("")
Local $cLabel = GUICtrlCreateLabel("COLOR_HIGHLIGHT - RGB:" & " 0x" & Hex($iColHilite, 6), 10, 20)
GUICtrlSetBkColor(-1, $iColHilite)
GUISetState()
Sleep(2000)
$iColHilite = BitAND(BitShift(String(Binary($iColHilite)), 8), 0xFFFFFF); From RGB2BGR() Author: Siao
GUICtrlSetBkColor(-1, $iColHilite)
GUICtrlSetData($cLabel, "COLOR_HIGHLIGHT - BGR:" & " 0x" & Hex($iColHilite, 6))

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd

I see fascists...

Share this post


Link to post
Share on other sites

Rover, Thank You -- what you showed me indeed works. I don't understand what's going on though. According to the MSDN documentation and AutoIt's documentation, GetSysColor returns RGB values. The comment on Siao's statement suggests its converting from RGB to BGR, but AutoIt works in RGB. :)

Well, even if I don't understand it, it indeed works --- I wouldn't have figured that one out on my own....

I've also seen a couple of articles about how to change the color of a ListView scrollbar, but it's beyond my current ability to be able to translate those code excerpts into AutoIt.

Maybe someone else will see this and welcome the challenge.

Thank you again Rover,

Paul

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Rover, Thank You -- what you showed me indeed works. I don't understand what's going on though. According to the MSDN documentation and AutoIt's documentation, GetSysColor returns RGB values. The comment on Siao's statement suggests its converting from RGB to BGR, but AutoIt works in RGB. :)

Well, even if I don't understand it, it indeed works --- I wouldn't have figured that one out on my own....

I've also seen a couple of articles about how to change the color of a ListView scrollbar, but it's beyond my current ability to be able to translate those code excerpts into AutoIt.

Maybe someone else will see this and welcome the challenge.

Thank you again Rover,

Paul

your welcome

Siao's code converts RGB-BGR or BGR-RGB

many ways of doing this on the forum, the listview udf has a version in it

system colours are BGR

MSDN page for GetSysColor says it returns RGB when it actually returns BGR

be seeing you

Edited by rover

I see fascists...

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

Another (more proper?) version. No conversion back and forth to a string. Performance is the same.

100,000 iterations -

1.13 sec for this one

1.11 sec for the other

Func _BGR2RGB($iColor)
    Return BitOR(BitShift(BitAND($iColor, 0x0000FF), -16), BitAND($iColor, 0x00FF00), BitShift(BitAND($iColor, 0xFF0000), 16))
EndFunc
Edited by wraithdu

Share this post


Link to post
Share on other sites

Another (more proper?) version. No conversion back and forth to a string. Performance is the same.

100,000 iterations -

1.13 sec for this one

1.11 sec for the other

Func _BGR2RGB($iColor)
    Return BitOR(BitShift(BitAND($iColor, 0x0000FF), -16), BitAND($iColor, 0x00FF00), BitShift(BitAND($iColor, 0xFF0000), 16))
EndFunc
six of one and half a dozen of the other

but, I like a convenient single line of code.

that's why I used Siao's

btw, cut the sarcasm, I've only used 'proper' a few times on the forum.

I'll use 'correct method' from now on, does that please you?


I see fascists...

Share this post


Link to post
Share on other sites

Sarcasm? None intended. I say 'proper' since I don't consider it best practice to do integer conversions using intermediate string conversions. Take it or leave it. No offense intended, k?

Share this post


Link to post
Share on other sites

@wraithdu

@rover

many ways of doing this on the forum

One more way

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

GUICreate("My GUI", 200, 100)

$BGR = _WinAPI_GetSysColor($COLOR_ACTIVECAPTION) ;Active caption is blue

GUICtrlCreateLabel("", 50, 35, 100, 20)
GUICtrlSetBkColor(-1, _BGR2RGB($BGR))

GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd

Func _BGR2RGB($sColor)
    Return Int("0x" & StringRegExpReplace(Hex($sColor, 6), "(..)(..)(..)", "\3\2\1"))
EndFunc   ;==>_BGR2RGB

:)

Share this post


Link to post
Share on other sites

Heh, that's a fun one too :)

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
Sign in to follow this  
Followers 0