News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Alternating the color on listview rows

Started by Mr Earl, January 18, 2005, 04:46:23 PM

Previous topic - Next topic

Mr Earl

Does anyone know how to alternate the color of listview rows using assembly only?

jimh

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.  That is a good reference.

greenant

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)

Mr Earl

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.

greenant

I don't know. Maybe a property of the listview.
Try downloading gremaf and study the listview.asm file

taff_e

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

Mr Earl

#6
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.