I have merged the information
here with evl's sample code.
The resulting example below not only highlights alternating rows in the listview using custom colors, but it also uses (different) custom colors for the selected row.
Code:
#NoEnv
SendMode Input
/*
struct NMHDR {
HWND hwndFrom; uint4 0
UINT idFrom; uint4 4
UINT code; uint4 8
} 12
struct NMCUSTOMDRAW {
NMHDR hdr; 12 0
DWORD dwDrawStage; uint4 12
HDC hdc; uint4 16
RECT rc; 16 20
DWORD_PTR dwItemSpec; uint4 36
UINT uItemState; uint4 40
LPARAM lItemlParam; int4 44
} 48
struct NMLVCUSTOMDRAW {
NMCUSTOMDRAW nmcd; 48 0
COLORREF clrText; uint4 48
COLORREF clrTextBk; uint4 52
#if (_WIN32_IE >= 0x0400)
int iSubItem; int4 56
#endif
#if (_WIN32_IE >= 0x560)
DWORD dwItemType; uint4 60
COLORREF clrFace; uint4 64
int iIconEffect; int4 68
int iIconPhase; int4 72
int iPartId; int4 76
int iStateId: int4 80
RECT rcText; 16 84
UINT uAlign; uint4 100
#endif
} 104
struct LVITEM {
UINT mask; uint4 0
int iItem; 4
int iSubItem; 8
UINT state; uint4 12
UINT stateMask; uint4 16
LPTSTR pszText;
int cchTextMax;
int iImage;
LPARAM lParam;
#if (_WIN32_IE >= 0x0300)
int iIndent;
#endif
#if (_WIN32_WINNT >= 0x560)
int iGroupId;
UINT cColumns; // tile view columns
PUINT puColumns;
#endif
#if (_WIN32_WINNT >= 0x0600)
int* piColFmt
int iGroup
#endif
}
*/
Gui, +LastFound
Gui, Add, ListView, x5 y5 w200 h200 gLV_Sample vLV_Sample, index|day
LV_Add( "", 1, "Monday" )
LV_Add( "", 2, "Tuesday" )
LV_Add( "", 3, "Wednesday" )
LV_Add( "", 4, "Thursday" )
LV_Add( "", 5, "Friday" )
LV_Add( "", 6, "Saturday" )
LV_Add( "", 7, "Sunday" )
LV_ModifyCol( 1, "AutoHdr" )
LV_ModifyCol( 2, "AutoHdr" )
Gui, Show, x50 y50 w210 h210
LV_ColorInitiate() ; (Gui_Number, Control) - defaults to: (1, SysListView321)
; Highlighting alternating lines in the listview.
Loop, % LV_GetCount()
{
If ( Mod( A_Index, 2 ) )
LV_ColorChange(A_Index, "0xFFFFFF", "0xFF0000")
}
Return
LV_Sample:
if A_GuiEvent = DoubleClick
{
LV_GetText(myday, A_EventInfo, 2)
MsgBox, %myday%!
}
Return
GuiClose:
GuiEscape:
Exitapp
LV_ColorInitiate(Gui_Number=1, Control="") ; initiate listview color change procedure
{
global hw_LV_ColorChange, LvItem
If Control =
Control =SysListView321
Gui, %Gui_Number%:+Lastfound
Gui_ID := WinExist()
ControlGet, hw_LV_ColorChange, HWND,, %Control%, ahk_id %Gui_ID%
VarSetCapacity(LvItem, 36, 0)
OnMessage( 0x4E, "WM_NOTIFY" )
}
LV_ColorChange(Index="", TextColor="", BackColor="") ; change specific line's color or reset all lines
{
global
If Index =
Loop, % LV_GetCount()
LV_ColorChange(A_Index)
Else
{
Line_Color_%Index%_Text := TextColor
Line_Color_%Index%_Back := BackColor
WinSet, Redraw,, ahk_id %hw_LV_ColorChange%
}
}
WM_NOTIFY( p_w, p_l, p_m )
{
local draw_stage, Current_Line, Index, IsSelected=0
Critical
if ( DecodeInteger( "uint4", p_l, 0 ) = hw_LV_ColorChange ) { ; NMHDR->hwndFrom
if ( DecodeInteger( "int4", p_l, 8 ) = -12 ) { ; NMHDR->code ; NM_CUSTOMDRAW
draw_stage := DecodeInteger( "uint4", p_l, 12 ) ; NMCUSTOMDRAW->dwDrawStage
Current_Line := DecodeInteger( "uint4", p_l, 36 )+1 ; NMCUSTOMDRAW->dwItemSpec
if ( draw_stage = 1 ) ; CDDS_PREPAINT
return, 0x20 ; CDRF_NOTIFYITEMDRAW
else if ( draw_stage = 0x10000|1 ) { ; CDDS_ITEMPREPAINT
If ( DllCall("GetFocus") = hw_LV_ColorChange ) { ; Control has Keyboard Focus?
SendMessage, 4140, Current_Line-1, 2, , ahk_id %hw_LV_ColorChange% ; LVM_GETITEMSTATE
IsSelected := ErrorLevel
If ( IsSelected = 2 ) { ; LVIS_SELECTED
EncodeInteger( "0xFFFFFF", 4, p_l, 48 ) ; NMCUSTOMDRAW->clrText ; foreground
EncodeInteger( "0x0000FF", 4, p_l, 52 ) ; NMCUSTOMDRAW->clrTextBk ; background
EncodeInteger(0x0, 4, &LvItem, 12) ; LVITEM->state
EncodeInteger(0x2, 4, &LvItem, 16) ; LVITEM->stateMask ; LVIS_SELECTED
SendMessage, 4139, Current_Line-1, &LvItem, , ahk_id %hw_LV_ColorChange% ; Disable Highlighting
; We want item post-paint notifications
Return, 0x00000010 ; CDRF_NOTIFYPOSTPAINT
}
LV_GetText(Index, Current_Line)
If (Line_Color_%Index%_Text != "") {
EncodeInteger( Line_Color_%Index%_Text, 4, p_l, 48 ) ; NMLVCUSTOMDRAW->clrText ; foreground
EncodeInteger( Line_Color_%Index%_Back, 4, p_l, 52 ) ; NMLVCUSTOMDRAW->clrTextBk ; background
}
}
}
else if ( draw_stage = 0x10000|2 ) ; CDDS_ITEMPOSTPAINT
If ( IsSelected ) {
EncodeInteger(0x02, 4, &LvItem, 12) ; LVITEM->state
EncodeInteger(0x02, 4, &LvItem, 16) ; LVITEM->stateMask ; LVIS_SELECTED
SendMessage, 4139, Current_Line-1, &LvItem, , ahk_id %hw_LV_ColorChange% ; LVM_SETITEMSTATE
}
}
}
}
DecodeInteger( p_type, p_address, p_offset, p_hex=true )
{
old_FormatInteger := A_FormatInteger
ifEqual, p_hex, 1, SetFormat, Integer, hex
else, SetFormat, Integer, dec
StringRight, size, p_type, 1
loop, %size%
value += *( ( p_address+p_offset )+( A_Index-1 ) ) << ( 8*( A_Index-1 ) )
if ( size <= 4 and InStr( p_type, "u" ) != 1 and *( p_address+p_offset+( size-1 ) ) & 0x80 )
value := -( ( ~value+1 ) & ( ( 2**( 8*size ) )-1 ) )
SetFormat, Integer, %old_FormatInteger%
return, value
}
EncodeInteger( p_value, p_size, p_address, p_offset )
{
loop, %p_size%
DllCall( "RtlFillMemory", "uint", p_address+p_offset+A_Index-1, "uint", 1, "uchar", p_value >> ( 8*( A_Index-1 ) ) )
}