Sign in to follow this  
Followers 0
Danp2

Alternating row background color?

16 posts in this topic

#1 ·  Posted (edited)

Is it possible to control the background color for individual rows within a Listview control created using _GUICtrlListView_Create?

Edited by DanP2

Share this post


Link to post
Share on other sites



Figured it out myself by modifying the code found here.

Share this post


Link to post
Share on other sites

Anyone know how this can be accomplished by subclassing the Listview control instead of using GUIRegisterMsg?

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

"Ownerdraw" by its definition implies working through messages of parent window. Subclassing the control itself isn't of much help in this task.

All this seems odd to me, if GUICtrlCreateListView offers alternate row colors, why use _GUICtrlListView_Create to begin with? What advantages does it have to make up for the obvious numerous disadvantages. And if you worked out ownerdrawing, why are you not content with it. What's so wrong about GuiRegisterMsg?

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

Thanks for your reply. There's nothing inherently wrong with using GuiRegisterMsg. I just thought it might be simpler to subclass and override the background color instead of having the draw the entire row, including calculating text spacing, manually.

As far was why I'm not using GUICtrlCreateListView, good question. I originally coded the routine using this, then decided to switch to the "newer" _GUICtrlListView. :D

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

We got your code for you man -

#include <GUIConstants.au3>
#include <Constants.au3>
$switch = False
GUICreate("listview items", 422, 622, -1, -1)
$listview = GUICtrlCreateListView ("Date    |Index|Description                 |Amount  |Debit or Credit", 11, 11, 400, 600)
For $i = 1 To 28
    $xListView = GUICtrlCreateListViewItem(" | | | | ", $listview)
    If $switch Then
        GUICtrlSetBkColor($xListView, 0xEAFAF3)
    EndIf
    SwitchWitches()
    Assign("ListItem" & $i, $xListView, 0)
Next
; $ListItem1, $ListItem2, $ListItem3, etc, now can be written to with GUICtrlSetData(controlID, data [, default])
GUICtrlSetState(-1,$GUI_DROPACCEPTED) ; to allow drag and dropping
GUISetState()
Do
  $msg = GUIGetMsg ()
  Sleep(12)
Until $msg = $GUI_EVENT_CLOSE
Func SwitchWitches()
    If $switch Then
        $switch = False
    Else
        $switch = True
    EndIf
EndFunc
Edited by Squirrely1

Das Häschen benutzt Radar

Share this post


Link to post
Share on other sites

Interesting. I previously implemented using $GUI_BKCOLOR_LV_ALTERNATE.

Assign("ListItem" & $i, $xListView, 0)

I take it this statement is optional, only needed for D&D?

Thanks, Dan

Share this post


Link to post
Share on other sites

...

Assign("ListItem" & $i, $xListView, 0)

I take it this statement is optional, only needed for D&D?...

That statement works with others to ensure that each ListViewItem has a unique controlID to it so that you can write data to the controls.

See the commented line that reads this way:

; $ListItem1, $ListItem2, $ListItem3, etc, now can be written to with GUICtrlSetData ...

$ListItem1 contains the controlID of the first ListViewItem :D


Das Häschen benutzt Radar

Share this post


Link to post
Share on other sites

We got your code for you man -

#include <GUIConstants.au3>
#include <Constants.au3>
$switch = False
GUICreate("listview items", 422, 622, -1, -1)
$listview = GUICtrlCreateListView ("Date    |Index|Description                 |Amount  |Debit or Credit", 11, 11, 400, 600)
For $i = 1 To 28
    $xListView = GUICtrlCreateListViewItem(" | | | | ", $listview)
    If $switch Then
        GUICtrlSetBkColor($xListView, 0xEAFAF3)
    EndIf
    SwitchWitches()
    Assign("ListItem" & $i, $xListView, 0)
Next
; $ListItem1, $ListItem2, $ListItem3, etc, now can be written to with GUICtrlSetData(controlID, data [, default])
GUICtrlSetState(-1,$GUI_DROPACCEPTED); to allow drag and dropping
GUISetState()
Do
  $msg = GUIGetMsg ()
  Sleep(12)
Until $msg = $GUI_EVENT_CLOSE
Func SwitchWitches()
    If $switch Then
        $switch = False
    Else
        $switch = True
    EndIf
EndFunc
Good example with Assign("ListItem" & $i, $xListView, 0), i don`t know about this function. :D Facilitate example, without function:

#include <GUIConstants.au3>

Dim $switch = False

GUICreate("listview items", 422, 622)

$listview = GUICtrlCreateListView ("Date    |Index|Description                   |Amount  |Debit or Credit", 11, 11, 400, 600)

For $i = 1 To 28
    $xListView = GUICtrlCreateListViewItem(" | | | | ", $listview)
    If $switch Then
        GUICtrlSetBkColor($xListView, 0xEAFAF3)
    EndIf
    $switch = Not $switch
    Assign("ListItem" & $i, $xListView, 0)
Next

GUICtrlSetState(-1, $GUI_DROPACCEPTED)

GUISetState()

Do
  Until GUIGetMsg() = $GUI_EVENT_CLOSE

:P

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Thanks for your reply. There's nothing inherently wrong with using GuiRegisterMsg. I just thought it might be simpler to subclass and override the background color instead of having the draw the entire row, including calculating text spacing, manually.

Subclassing listview would get you access to its own WM_PAINT, WM_NOTIFY etc messages, but that's not what you really need to use for item drawing. I think this would be necessary if you'd want to paint headers and do some transparency stuff.

Anyway.

Instead of ownerdraw you can use customdraw, this way you don't have to deal with text writing manually at all, and can also pass and let LV do default drawing at any time:

#Include <GuiConstantsEx.au3>
#Include <GuiListView.au3>

;custom draw constants
Global Const $CDDS_ITEM = 0x10000
Global Const $CDDS_MAPPART = 0x5
Global Const $CDDS_POSTERASE = 0x4
Global Const $CDDS_POSTPAINT = 0x2
Global Const $CDDS_PREERASE = 0x3
Global Const $CDDS_PREPAINT = 0x1
Global Const $CDDS_SUBITEM = 0x20000
Global Const $CDDS_ITEMPOSTERASE = BitOR($CDDS_ITEM, $CDDS_POSTERASE)
Global Const $CDDS_ITEMPOSTPAINT = BitOR($CDDS_ITEM, $CDDS_POSTPAINT)
Global Const $CDDS_ITEMPREERASE = BitOR($CDDS_ITEM, $CDDS_PREERASE)
Global Const $CDDS_ITEMPREPAINT = BitOR($CDDS_ITEM, $CDDS_PREPAINT)

Global Const $CDRF_DODEFAULT = 0x0
Global Const $CDRF_NEWFONT = 0x2
Global Const $CDRF_NOTIFYITEMDRAW = 0x20
Global Const $CDRF_NOTIFYPOSTERASE = 0x40
Global Const $CDRF_NOTIFYPOSTPAINT = 0x10
Global Const $CDRF_NOTIFYSUBITEMDRAW = 0x20
Global Const $CDRF_SKIPDEFAULT = 0x4

;fonts for custom draw example
;bold
Global $aFont1 = DLLCall("gdi32.dll","int","CreateFont", "int", 14, "int", 0, "int", 0, "int", 0, "int", 700, _
                        "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, _
                        "dword", 0, "str", "")
;italic
Global $aFont2 = DLLCall("gdi32.dll","int","CreateFont", "int", 14, "int", 0, "int", 0, "int", 0, "int", 400, _
                        "dword", 1, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, _
                        "dword", 0, "str", "")
                        


$GUI = GUICreate("Listview Custom Draw", 400, 300)

$cListView = GUICtrlCreateListView("", 2, 2, 394, 268)
$hListView = GUICtrlGetHandle($cListView)
;or
;~ $hListView = _GUICtrlListView_Create($GUI, "", 2, 2, 394, 268)

_GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))

_GUICtrlListView_InsertColumn($hListView, 0, "Column 1", 100)
_GUICtrlListView_InsertColumn($hListView, 1, "Column 2", 100)
_GUICtrlListView_InsertColumn($hListView, 2, "Column 3", 100)

; Add items
For $i = 1 To 30
    _GUICtrlListView_AddItem($hListView, "Row" & $i & ": Col 1", $i-1)
    For $j = 1 To 2
        _GUICtrlListView_AddSubItem ($hListView, $i-1, "Row" & $i & ": Col " & $j+1, $j)
    Next
Next

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
DLLCall("gdi32.dll","int","DeleteObject", "hwnd", $aFont1[0])
DLLCall("gdi32.dll","int","DeleteObject", "hwnd", $aFont2[0])
Exit

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR

    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $NM_CUSTOMDRAW
                    If Not _GUICtrlListView_GetViewDetails($hWndFrom) Then Return $GUI_RUNDEFMSG
                     Local $tCustDraw = DllStructCreate('hwnd hwndFrom;int idFrom;int code;' & _
                                        'dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;' & _
                                        'dword clrText;dword clrTextBk;int SubItem;' & _
                                        'dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align', _ ;winxp or later
                                        $lParam), $iDrawStage, $iItem, $iSubitem, $hDC, $iColor1, $iColor2, $iColor3
                    $iDrawStage = DllStructGetData($tCustDraw, 'DrawStage')
                    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ;request custom drawing of items
                    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW ;request drawing each cell separately
                    If Not BitAND($iDrawStage, $CDDS_SUBITEM) Then Return $CDRF_DODEFAULT
                    $iItem = DllStructGetData($tCustDraw, 'ItemSpec')
                    $iSubitem = DllStructGetData($tCustDraw, 'SubItem')
                    Switch $iItem
                        Case 0 To 9 ;for rows 1-10 lets do this
                            $iColor1 = RGB2BGR(0xFBFFD8)
                            $iColor2 = RGB2BGR(-1)
                            $iColor3 = RGB2BGR(0xFF0000)
                            If Mod($iSubitem, 2) Then ;odd columns
                                DllStructSetData($tCustDraw, 'clrTextBk', $iColor1)
                                DllStructSetData($tCustDraw, 'clrText', 0)
                            Else ;even columns
                                DllStructSetData($tCustDraw, 'clrTextBk', $iColor2)
                                DllStructSetData($tCustDraw, 'clrText', $iColor3)
                            EndIf
                        Case 10 To 19 ;for rows 11-20 lets do this
                            $iColor1 = RGB2BGR(0xFBFFD8)
                            $iColor2 = RGB2BGR(0x3DF8FF)
                            $hDC = DllStructGetData($tCustDraw, 'hdc')
                            If Mod($iItem, 2) Then
                                If Mod($iSubitem, 2) Then
                                    DllStructSetData($tCustDraw, 'clrTextBk', $iColor1)
                                Else
                                    DllStructSetData($tCustDraw, 'clrTextBk', $iColor2)
                                EndIf
                                DLLCall("gdi32.dll","hwnd","SelectObject", "hwnd", $hDC, "hwnd", $aFont1[0]) ;select our chosen font into DC
                            Else
                                If Mod($iSubitem, 2) Then
                                    DllStructSetData($tCustDraw, 'clrTextBk', $iColor2)
                                Else
                                    DllStructSetData($tCustDraw, 'clrTextBk', $iColor1)
                                EndIf
                                DLLCall("gdi32.dll","hwnd","SelectObject", "hwnd", $hDC, "hwnd", $aFont2[0])
                            EndIf
                        Case 20 To 29 ;for rows 21-30 lets do this
                            $iColor1 = RGB2BGR(0xFBFFD8)
                            $iColor2 = RGB2BGR(-1)
                            If Mod($iItem, 2) Then ;odd rows
                                DllStructSetData($tCustDraw, 'clrTextBk', $iColor2)
                            Else
                                DllStructSetData($tCustDraw, 'clrTextBk', $iColor1)
                            EndIf                           
                    EndSwitch
                    Return $CDRF_NEWFONT
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func RGB2BGR($iColor)
    Return BitAND(BitShift(String(Binary($iColor)), 8), 0xFFFFFF)
EndFunc

As far was why I'm not using GUICtrlCreateListView, good question. I originally coded the routine using this, then decided to switch to the "newer" _GUICtrlListView. :D

Not a very good decision 99% of the time, and I wish UDF documentation would warn that this is in no way mandatory, and has quite a few serious drawbacks if you chose to go that way. Right now lot of GUI newbies for whatever reason seem to be inclined to think that in order to use other GuiListview UDF functions they need to create listview using that function, or that it's somehow "newer" and "more advanced". Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

Nice technique Uzebekistan - "$switch = Not $switch"

We aren't supposed to SwitchWitches in my religion either, anyway.


Das Häschen benutzt Radar

Share this post


Link to post
Share on other sites

Thanks, Siao. The customdraw functionality is exactly what I was looking for.

Share this post


Link to post
Share on other sites
Siao great work! You the best :D

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Siao cool~!!!

Edited by tryer777

Share this post


Link to post
Share on other sites

Miss your coding Siao

UPDATED 11-11-2008

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


;fonts for custom draw example
;bold
Global $aFont1 = DLLCall("gdi32.dll","int","CreateFont", "int", 14, "int", 0, "int", 0, "int", 0, "int", 700, _
                        "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, _
                        "dword", 0, "str", "")
;italic
Global $aFont2 = DLLCall("gdi32.dll","int","CreateFont", "int", 14, "int", 0, "int", 0, "int", 0, "int", 400, _
                        "dword", 1, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, "dword", 0, _
                        "dword", 0, "str", "")
                        


$GUI = GUICreate("Listview Custom Draw", 400, 300)

$cListView = GUICtrlCreateListView("", 2, 2, 394, 268)
$hListView = GUICtrlGetHandle($cListView)
;or
;~ $hListView = _GUICtrlListView_Create($GUI, "", 2, 2, 394, 268)

_GUICtrlListView_SetExtendedListViewStyle($hListView, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT))

_GUICtrlListView_InsertColumn($hListView, 0, "Column 1", 100)
_GUICtrlListView_InsertColumn($hListView, 1, "Column 2", 100)
_GUICtrlListView_InsertColumn($hListView, 2, "Column 3", 100)

; Add items
For $i = 1 To 30
    _GUICtrlListView_AddItem($hListView, "Row" & $i & ": Col 1", $i-1)
    For $j = 1 To 2
        _GUICtrlListView_AddSubItem ($hListView, $i-1, "Row" & $i & ": Col " & $j+1, $j)
    Next
Next

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
DLLCall("gdi32.dll","int","DeleteObject", "hwnd", $aFont1[0])
DLLCall("gdi32.dll","int","DeleteObject", "hwnd", $aFont2[0])
Exit

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR

    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $NM_CUSTOMDRAW
                    If Not _GUICtrlListView_GetViewDetails($hWndFrom) Then Return $GUI_RUNDEFMSG
                     Local $tCustDraw = DllStructCreate('hwnd hwndFrom;int idFrom;int code;' & _
                                        'dword DrawStage;hwnd hdc;long rect[4];dword ItemSpec;int ItemState;dword Itemlparam;' & _
                                        'dword clrText;dword clrTextBk;int SubItem;' & _
                                        'dword ItemType;dword clrFace;int IconEffect;int IconPhase;int PartID;int StateID;long rectText[4];int Align', _ ;winxp or later
                                        $lParam), $iDrawStage, $iItem, $iSubitem, $hDC, $iColor1, $iColor2, $iColor3
                    $iDrawStage = DllStructGetData($tCustDraw, 'DrawStage')
                    If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ;request custom drawing of items
                    If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW ;request drawing each cell separately
                    If Not BitAND($iDrawStage, $CDDS_SUBITEM) Then Return $CDRF_DODEFAULT
                    $iItem = DllStructGetData($tCustDraw, 'ItemSpec')
                    $iSubitem = DllStructGetData($tCustDraw, 'SubItem')
                    Switch $iItem
                        Case 0 To 9 ;for rows 1-10 lets do this
                            $iColor1 = RGB2BGR(0xFBFFD8)
                            $iColor2 = RGB2BGR(-1)
                            $iColor3 = RGB2BGR(0xFF0000)
                            If Mod($iSubitem, 2) Then ;odd columns
                                DllStructSetData($tCustDraw, 'clrTextBk', $iColor1)
                                DllStructSetData($tCustDraw, 'clrText', 0)
                            Else ;even columns
                                DllStructSetData($tCustDraw, 'clrTextBk', $iColor2)
                                DllStructSetData($tCustDraw, 'clrText', $iColor3)
                            EndIf
                        Case 10 To 19 ;for rows 11-20 lets do this
                            $iColor1 = RGB2BGR(0xFBFFD8)
                            $iColor2 = RGB2BGR(0x3DF8FF)
                            $hDC = DllStructGetData($tCustDraw, 'hdc')
                            If Mod($iItem, 2) Then
                                If Mod($iSubitem, 2) Then
                                    DllStructSetData($tCustDraw, 'clrTextBk', $iColor1)
                                Else
                                    DllStructSetData($tCustDraw, 'clrTextBk', $iColor2)
                                EndIf
                                DLLCall("gdi32.dll","hwnd","SelectObject", "hwnd", $hDC, "hwnd", $aFont1[0]) ;select our chosen font into DC
                            Else
                                If Mod($iSubitem, 2) Then
                                    DllStructSetData($tCustDraw, 'clrTextBk', $iColor2)
                                Else
                                    DllStructSetData($tCustDraw, 'clrTextBk', $iColor1)
                                EndIf
                                DLLCall("gdi32.dll","hwnd","SelectObject", "hwnd", $hDC, "hwnd", $aFont2[0])
                            EndIf
                        Case 20 To 29 ;for rows 21-30 lets do this
                            $iColor1 = RGB2BGR(0xFBFFD8)
                            $iColor2 = RGB2BGR(-1)
                            If Mod($iItem, 2) Then ;odd rows
                                DllStructSetData($tCustDraw, 'clrTextBk', $iColor2)
                            Else
                                DllStructSetData($tCustDraw, 'clrTextBk', $iColor1)
                            EndIf                     
                    EndSwitch
                    Return $CDRF_NEWFONT
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func RGB2BGR($iColor)
    Return BitAND(BitShift(String(Binary($iColor)), 8), 0xFFFFFF)
EndFunc

8)


NEWHeader1.png

Share this post


Link to post
Share on other sites

Siao, this is a breakthrough!

Cant say how glad i am that finally you can color single ListView Items, and even set the Font.

In the past this only was possible with GUICtrlSetBkColor where you had to deal with internal LV functions and the ControlID's for the items.

Now we can use the new List view UDF's which hold much more possibilities AND have custom coloring :P

BugFix extended this to a nice usable Template: http://www.autoitscript.com/forum/index.ph...=0&p=644312

Just wanted to thank you again for showing us this possibility!


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

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