The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Mr Earl on January 18, 2005, 04:46:23 PM

Title: Alternating the color on listview rows
Post by: Mr Earl on January 18, 2005, 04:46:23 PM
Does anyone know how to alternate the color of listview rows using assembly only?
Title: Re: Alternating the color on listview rows
Post by: jimh on January 18, 2005, 08:10:14 PM
To change any non-standard option in an ActiveX control (such as the ListView), you have to subclass the control.  Doing this can be quite a feat if you've never attempted it before.  At its roots however, you aren't doing much more than intercepting messages send to the control's window, handling the ones you need and passing the rest on to the window's original WndProc.

1:  Create the window for the ActiveX control.
2:  Call GetWindowLong with GWL_WNDPROC to get the address of the old window procedure
3:  Call SetWindowLong to set the address or your own WndProc
4:  In your custom WndProc call CallWndProc for all messages you don't handle
5:  Restore the old window procedure when you close down your app. (see step 3)

Now, that was fairly simplistic but it is a place to start.  MSDN has an article titled Safe Subclassing in Win32 (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_subclas3.asp).  That is a good reference.
Title: Re: Alternating the color on listview rows
Post by: greenant on January 18, 2005, 09:06:10 PM
ListView isn't an activex control.
To change color & font of common controls you can use custom draw

This is taken from Gremaf (listview.asm), a program of mine


mov ecx, pHdr
mov eax, [ecx.NMHDR].code

.elseif eax == NM_CUSTOMDRAW
mov eax, [ecx.NMCUSTOMDRAW].dwDrawStage
.if eax == CDDS_PREPAINT
mov eax, CDRF_NOTIFYITEMDRAW
ret

.elseif eax == CDDS_ITEMPREPAINT
invoke VirtualLw_PaintRow, ecx
mov eax, CDRF_NEWFONT
ret
.endif




VirtualLw_PaintRow proc private uses esi pHdr:DWORD
LOCAL buffer[256] : BYTE

mov ecx, pHdr

mov esi, [ecx.NMCUSTOMDRAW].dwItemSpec

;Calculate the value of [pGameStr][ecx->dwItemSpec]
mov eax, [ecx.NMCUSTOMDRAW].dwItemSpec ;Row number
mov edx, pGameStr ;Array base
mov esi, [edx + eax*4] ;Address of our GAME_STR structure

;Check the status
mov al, [esi.GAME_STR].StatusMask ;Load status bitmask
.if al == STATUS_GOOD
mov eax, ColorGood
.elseif al == STATUS_BEST
mov eax, ColorBest
.elseif al == STATUS_BAD
mov eax, ColorBad
.else
mov eax, ColorNot
.endif

mov esi, pHdr
mov [esi.NMLVCUSTOMDRAW].clrTextBk, eax

ret
VirtualLw_PaintRow endp


pHdr is the pointer to the NMHDR structure. The first code is the code in response to WM_NOTIFY.

This code changes the color of the row according to the value of a variable (member of a private game_str structure) but you can check if the row is even or odd
StatusGood, StatusBad, .... ColorBad, ColorNot are private variables (or private constants)
Title: Re: Alternating the color on listview rows
Post by: Mr Earl on January 19, 2005, 07:05:32 PM
Thanks greenant,
Your solution works fine for the 1st screen, but when I scroll the screen it doesn't alternate the color.  I have very little API experience, so I expect it's some simple thing I'm not yet aware of.  I appreciate your help.
Title: Re: Alternating the color on listview rows
Post by: greenant on January 19, 2005, 09:37:16 PM
I don't know. Maybe a property of the listview.
Try downloading gremaf and study the listview.asm file
Title: Re: Alternating the color on listview rows
Post by: taff_e on January 20, 2005, 09:39:06 AM
Hi Mr Earl

This is from one of my current projects that I use in the office - it should alternate the colours in the listview

I subclass the listview by using this in my main Proc

; ........ some code
invoke SetWindowLong,hList,GWL_WNDPROC,listViewProc
mov hOldListProc,eax
; ........ more code

and this is the subclassing code

listViewProc proc  hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL lvi:LV_ITEM
mov eax,uMsg
.if eax==WM_NOTIFY
mov edi,lParam
ASSUME edi:ptr NMHDR
.if [edi].code == NM_CUSTOMDRAW
mov ecx,edi
ASSUME ecx:ptr NMLVCUSTOMDRAW
.if [ecx].nmcd.dwDrawStage == CDDS_PREPAINT
mov eax,CDRF_NOTIFYITEMDRAW
ret
.elseif [ecx].nmcd.dwDrawStage == CDDS_ITEMPREPAINT
mov   eax, [ecx].nmcd.dwItemSpec
and   eax, 1
dec   eax
and   eax, (00EEF2C8h - 00D6F8D3h) ;=(a-b)+b = a ; change these values to change colours
add   eax, 00D6F8D3h ;(0)+b=b
mov   [ecx].clrTextBk, eax
mov   eax, CDRF_NEWFONT
ret
ASSUME ecx:nothing
.endif
; ------check for double click --------;
.elseif [edi].code == NM_DBLCLK
invoke SendMessage,hList,LVM_GETNEXTITEM,-1,LVNI_FOCUSED
mov lvi.iItem,eax
mov lvi.iSubItem,0
mov lvi.cchTextMax,60
mov lvi.pszText,offset selectedProject
mov lvi.imask,LVIF_TEXT
invoke SendMessage,hList,LVM_GETITEM,0,addr lvi
invoke DialogBoxParam, hInstance, IDD_ProjectView , hWin, addr ProjectViewProc , NULL
.else
invoke CallWindowProc, hOldListProc,hWin,uMsg,wParam,lParam ; let windows deal with rest
.endif
ASSUME edi:nothing
.else
invoke CallWindowProc, hOldListProc,hWin,uMsg,wParam,lParam ; let windows deal with rest
.endif
ret

listViewProc endp


The code may not be perfect but it works for me - and I'm still learning :)

Hope this helps

Taff
Title: Re: Alternating the color on listview rows
Post by: Mr Earl on January 20, 2005, 03:36:51 PM
Thanks taff_e
After much juggling code I finally got it to work.  The problem was my method for determining even/odd.  When I took taff_e's algorithm for even/odd and put it into greenant's code it works perfectly.  Subclassing wasn't needed, but thanks taff_e, your code enabled me to get it working.