while the vScroll is being moved, the listview color will missing.
edit: the exe Attachment for you'll easily test it.
.586
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\shell32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\gdi32.inc
include \masm32\include\advapi32.inc
include \masm32\include\comctl32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\advapi32.lib
includelib \masm32\lib\comctl32.lib
includelib \masm32\lib\masm32.lib
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include \masm32\macros\macros.asm
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.const
IDD_DIALOG equ 1000
IDB_EXIT equ 1001
IDB_STOP equ 1003
IDC_LIST equ 1004
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.data
ListCap1 db "Index",0
ListCap2 db "RandNum",0
buffer1 db 512 dup (0)
@dwSetTextBKColor dd 0FFff00H
IndexOfList dd 0H
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.data?
hInstance dd ?
hList dd ?
lvi LV_ITEM <?>
Buffer db 32 dup(?)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.code
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
iRand proc _dwMin:DWORD, _dwMax:DWORD
local @dwRet:dword, @dqFreq:qword
pushad
invoke QueryPerformanceCounter,addr @dqFreq
mov eax,dword ptr @dqFreq
mov ecx, 13
mul ecx
add eax, 5
mov ecx, _dwMax
sub ecx, _dwMin
inc ecx
xor edx, edx
div ecx
mov @dwRet, edx
popad
mov eax, @dwRet
add eax,_dwMin ; eax = Rand_Number
ret
iRand endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
InsertColumns proc
LOCAL lvc:LV_COLUMN
invoke SendMessage,hList,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT or LVS_EX_FLATSB ,-1
mov lvc.imask,LVCF_TEXT+LVCF_WIDTH
mov lvc.pszText,offset ListCap1
mov lvc.lx,100
invoke SendMessage,hList, LVM_INSERTCOLUMN,0,addr lvc
or lvc.imask,LVCF_FMT
mov lvc.fmt,LVCFMT_LEFT ;CENTER
mov lvc.pszText,offset ListCap2
mov lvc.lx,130
invoke SendMessage,hList, LVM_INSERTCOLUMN, 1 ,addr lvc
ret
InsertColumns endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AddItem proc _hList:DWORD, item:DWORD, subitem:DWORD, tdata:DWORD
LOCAL newitem:LV_ITEM
LOCAL lstmsg:DWORD
mov newitem.imask, LVIF_TEXT
m2m newitem.iItem, item
m2m newitem.iSubItem, subitem
m2m newitem.pszText, tdata
invoke lstrlen, tdata
inc eax
mov newitem.cchTextMax, eax
.IF subitem == 0h
mov lstmsg, LVM_INSERTITEM
.ELSE
mov lstmsg, LVM_SETITEM
.ENDIF
invoke SendMessage, _hList, lstmsg, 0h, addr newitem
invoke SendMessage, _hList, LVM_ENSUREVISIBLE, item, FALSE
ret
AddItem endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AddItemInt proc _hList:DWORD,item:DWORD,subitem:DWORD,tdword:DWORD
invoke RtlZeroMemory,addr Buffer,sizeof Buffer
invoke wsprintf,addr Buffer, CTXT('%i'), tdword
invoke AddItem, _hList,item,subitem,addr Buffer
ret
AddItemInt endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CreateButton proc hParent:DWORD,lpText:DWORD,x:DWORD,y:DWORD,w:DWORD,h:DWORD,ID:DWORD
LOCAL hFont :DWORD
invoke CreateFont,14,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE, \
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, \
DEFAULT_QUALITY,DEFAULT_PITCH, CTXT("Arial")
mov hFont, eax
invoke CreateWindowEx,0,CTXT('BUTTON'),lpText,WS_CHILD or WS_VISIBLE ,
x,y,w,h,hParent,ID,
hInstance,NULL
push eax
invoke SendMessage,eax,WM_SETFONT,hFont, 0
pop eax
ret
CreateButton endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CreateListView proc hParent:DWORD, x:DWORD,y:DWORD,w:DWORD,h:DWORD,ID:DWORD
LOCAL hFont :DWORD
invoke CreateFont,15,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE, \
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, \
DEFAULT_QUALITY,DEFAULT_PITCH, CTXT("Arial")
mov hFont, eax
invoke CreateWindowEx, WS_EX_STATICEDGE + WS_EX_TRANSPARENT,\
CTXT("SysListView32"),CTXT("test"),WS_TABSTOP + WS_VSCROLL + CBS_SIMPLE + WS_VISIBLE + WS_CHILD,x,y,w,h,\
hParent,ID,hInstance,NULL
push eax
invoke SendMessage,eax,WM_SETFONT,hFont, 0
pop eax
ret
CreateListView endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax == WM_CREATE
invoke CreateButton,hWnd,CTXT('Stop'),71,256,56,20,IDB_STOP
invoke CreateButton,hWnd,CTXT('Exit'),7,256,56,20,IDB_EXIT
invoke CreateListView,hWnd,7,16,398,229,IDC_LIST
mov hList,eax
invoke SendMessage,hList,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT or LVS_EX_HEADERDRAGDROP OR LVS_EX_GRIDLINES,-1
invoke InsertColumns
invoke SetTimer,hWnd,0,1000,0
.elseif eax==WM_TIMER
push ebx
invoke iRand,100,800
mov eax,IndexOfList
inc eax
invoke AddItemInt,hList,IndexOfList,0,eax
invoke iRand,100,800
mov ebx,eax
invoke AddItemInt,hList,IndexOfList,1,ebx
.if ebx > 100 && ebx < 150
mov @dwSetTextBKColor,0FFADADH
.elseif ebx >= 150 && ebx < 300
mov @dwSetTextBKColor,0ADFFADH
.elseif ebx >= 300 && ebx < 400
mov @dwSetTextBKColor,0ADADFFH
.elseif ebx >= 400 && ebx < 550
mov @dwSetTextBKColor,0FF00ADH
.elseif ebx >= 550 && ebx < 800
mov @dwSetTextBKColor,000ADFFH
.else
mov @dwSetTextBKColor,0FF0000H
.endif
inc IndexOfList
pop ebx
.elseif eax == WM_COMMAND
.if wParam == IDB_EXIT
invoke DestroyWindow, hWnd
.elseif wParam==IDB_STOP
invoke KillTimer,hWnd,0
.endif
.elseif eax == WM_NOTIFY
mov edi,lParam
assume edi:ptr NMLVCUSTOMDRAW
mov eax,[edi].nmcd.hdr.code
.if eax== NM_CUSTOMDRAW
mov eax,[edi].nmcd.dwDrawStage
.if eax==CDDS_PREPAINT
mov eax,CDRF_NOTIFYITEMDRAW
ret
.elseif eax==CDDS_ITEMPREPAINT
m2m [edi].clrTextBk,@dwSetTextBKColor
mov eax,CDRF_NOTIFYSUBITEMDRAW
ret
.elseif eax==CDDS_SUBITEM or CDDS_ITEMPREPAINT
m2m [edi].clrTextBk,@dwSetTextBKColor
.endif
mov eax,CDRF_NEWFONT
ret
.endif
ASSUME edi:nothing
.elseif eax == WM_CLOSE
invoke KillTimer,hWnd,0
invoke DestroyWindow, hWnd
.elseif eax == WM_DESTROY
invoke PostQuitMessage, NULL
.else
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.endif
xor eax, eax
ret
DlgProc endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TopXY proc wDim:DWORD, sDim:DWORD
shr sDim, 1
shr wDim, 1
mov eax, wDim
sub sDim, eax
mov eax, sDim
ret
TopXY endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WinMain proc hInst:DWORD,hPrevInst:DWORD, CmdLine:DWORD, CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL Wwd:DWORD
LOCAL Wht:DWORD
LOCAL Wtx:DWORD
LOCAL Wty:DWORD
LOCAL hWnd:HANDLE
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_BYTEALIGNCLIENT or CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc, offset DlgProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance,hInst
mov wc.hbrBackground, COLOR_BTNFACE+1
mov wc.lpszClassName, CTXT("test_list")
invoke LoadIcon, NULL, IDI_APPLICATION
mov wc.hIcon, eax
mov wc.hIconSm, eax
invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax
invoke RegisterClassEx, addr wc
mov Wwd, 425
mov Wht, 320
invoke GetSystemMetrics,SM_CXSCREEN
invoke TopXY,Wwd,eax
mov Wtx, eax
invoke GetSystemMetrics,SM_CYSCREEN
invoke TopXY,Wht,eax
mov Wty, eax
invoke CreateWindowEx, NULL, CTXT("test_list"),CTXT("test_list"), WS_OVERLAPPEDWINDOW,\
Wtx,Wty,Wwd,Wht,NULL, NULL, hInst, NULL
mov hWnd, eax
invoke ShowWindow, hWnd, SW_SHOWNORMAL
invoke UpdateWindow, hWnd
.while TRUE
invoke GetMessage, addr msg, NULL, 0, 0
.break .if (!eax)
invoke TranslateMessage, addr msg
invoke DispatchMessage, addr msg
.endw
mov eax, msg.wParam
ret
WinMain endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke GetCommandLine
invoke WinMain, hInstance ,NULL, eax, SW_SHOWDEFAULT
invoke ExitProcess,0
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
end start
To keep the colours to their rows, you need to set them in a WM_PAINT handler, not in WM_TIMER, and you must keep a table that associates rows with colours, e.g. with
mov newitem.lParam, TheColour
invoke SendMessage, _hList, lstmsg, 0h, addr newitem
You may use this (http://www.masmforum.com/board/index.php?topic=12027.msg91634#msg91634) as a template.
BTW CreateListView failed miserably under XP SP3 until I replaced all headers including macros.asm with my usual one-liner .. MasmBasic.inc - very odd ::)
thanks your response.
the trouble is still there.
WM_TIMER: creates the random number,set the color of listview cows acorroding to its value.
Quote from: six_L on April 13, 2014, 11:51:18 AMthe trouble is still there
It won't go away until you do what I proposed above. You might start reading on subclassing and WM_PAINT...
.
You'll need to find a way of storing the dwSetTextBKColor var to associate it with a particular row, and then in your NM_CUSTOMDRAW part, recall it. Otherwise as you have seen the call to redraw all visible items (via the scroller being activated/moved) with cause those visible rows to change color to the last known dwSetTextBKColor (which is a global value)
You could use LVIF_PARAM with the lParam value of the row to store info, like the color, or use some memory array that is in sync with listview item indexes.
To get the item and subitem:
mov ecx, lParam
mov eax, (NMLVCUSTOMDRAW ptr[ecx]).iSubItem
mov nSubItem, eax
mov eax, (NMLVCUSTOMDRAW ptr[ecx]).nmcd.dwItemSpec ; item
mov nItem, eax
with item indentified you could then call LVM_GETITEM (using item we just obtained) with LVIF_PARAM flag, and recall lParam value. Then store it to a local var, which would change each time the listview calls for custom draw part of your code (which would be once for each visible item when scroller moves). The fetch color part needs to be inside this NMCUSTOMDRAW part of your code for it to work.
Hope that helps
thanks all for your help.
Quotewith item indentified you could then call LVM_GETITEM (using item we just obtained) with LVIF_PARAM flag, and recall lParam value. Then store it to a local var, which would change each time the listview calls for custom draw part of your code (which would be once for each visible item when scroller moves). The fetch color part needs to be inside this NMCUSTOMDRAW part of your code for it to work.
:t this's helpful.
have tried a lot of times, i'm still failed. can't implement your helpful idea.
Could you show me the part codes?
Hi Six_L
You have for many years send this example here is a part of my colorlistview
OnInitListView PROC hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL rect:RECT
LOCAL lvi:LV_ITEM
LOCAL local_buffer[255] :BYTE
mov edx,lParam
.if wParam==IDC_LISTVIEW
.if [edx].NMHDR.code==NM_CUSTOMDRAW
assume edx: ptr NMLVCUSTOMDRAW
.if [edx].nmcd.dwDrawStage == CDDS_PREPAINT
@@:
invoke SetWindowLong,hWnd,DWL_MSGRESULT,CDRF_NOTIFYITEMDRAW
ret
.elseIf [edx].nmcd.dwDrawStage == CDDS_ITEMPREPAINT
jmp @B
.elseIf [edx].nmcd.dwDrawStage == CDDS_ITEMPREPAINT || CDDS_SUBITEM ;|| CDDS_ITEM
.if [edx].nmcd.uItemState & CDIS_SELECTED
mov esi,[edx].nmcd.dwItemSpec; Get the item number
mov ebx,[edx].nmcd.hdc ; Get the device context
mov [rect.left],LVIR_BOUNDS ; Get the bounding rect of the item
invoke SendMessage,hListView,LVM_GETITEMRECT,esi,addr rect
invoke FillRect,ebx,addr rect,hCurselColor ; Draw the background color and frame
invoke FrameRect,ebx,addr rect,hFramecolor
invoke SelectObject,ebx,eax
invoke SetTextColor,ebx,005ADFC1h;IDC_TEXTCOLOR
; Get the item count from the header control
invoke SendMessage,hListView,LVM_GETHEADER,0,0
invoke SendMessage,eax,HDM_GETITEMCOUNT,0,0
mov ecx,eax
; Loop through all the labels and draw their text
mov lvi.iItem,esi
lea eax, local_buffer
mov lvi.pszText,eax
mov lvi.cchTextMax,255
xor edi,edi; EDI is no longer needed so we'll use it for a counter
.while edi !=ecx
push ecx ; save the item count
; Get the bounding rect of the label
; the API uses the rect struct to pass parameters
mov [rect.left],LVIR_LABEL
mov [rect.top],edi
invoke SendMessage,hListView,LVM_GETSUBITEMRECT,esi,addr rect
.if edi!=0
add [rect.left],4 ; extra indent for sub items
.endif
add [rect.left],2 ; indent isn't right with LVM_GETITEM
mov [lvi.iSubItem],edi
invoke SendMessage,hListView,LVM_GETITEMTEXT,esi,addr lvi
; Draw the text to the items
invoke DrawText,ebx,addr local_buffer,-1,addr rect,DT_LEFT + DT_VCENTER + DT_SINGLELINE
pop ecx ; restore the item count
inc edi
.endw
invoke SetWindowLong,hWnd,DWL_MSGRESULT,CDRF_SKIPDEFAULT
ret
.endif
mov [edx].clrText,005ADFC1h;IDC_TEXTCOLOR
mov [edx].clrTextBk,0h;IDC_BACKCOLOR
assume edx: nothing
invoke SetWindowLong,hWnd,DWL_MSGRESULT,CDRF_DODEFAULT
ret
.endif
assume edx: nothing
.endif
.endif
xor eax,eax
ret
OnInitListView endp
Greets,
hi ragdog,thanks your help.
this codes have the same trouble while many colors to be setted in the listview.
I wrote a tutorial on this, here is the code for custom draw listview.
Hi,Gunner.thanks your help.
i used a majority of the codes, the exe attachment shows the same question.
Looks good, Gunner :t
There is also an interesting one on CodeProject, ListView Alternating Row Colours (Using Windows API) (http://www.codeproject.com/Articles/20796/ListView-Alternating-Row-Colours-Using-Windows-API) - see the comments on WinAPI vs NM_CUSTOMDRAW
Here is your code as per OP, with the amendment to use the LVM_GETITEM / LVM_SETITEM for storing/recalling backcolor using the lparam value of the listview item. I marked the changed areas with comments. Tested moving the scroller once the list fills up past visible view (then stopped) and the colors remain as they should each listview row. Hope this helps.
.586
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\shell32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\gdi32.inc
include \masm32\include\advapi32.inc
include \masm32\include\comctl32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\advapi32.lib
includelib \masm32\lib\comctl32.lib
includelib \masm32\lib\masm32.lib
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include \masm32\macros\macros.asm
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.const
IDD_DIALOG equ 1000
IDB_EXIT equ 1001
IDB_STOP equ 1003
IDC_LIST equ 1004
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.data
ListCap1 db "Index",0
ListCap2 db "RandNum",0
buffer1 db 512 dup (0)
@dwSetTextBKColor dd 0FFff00H
IndexOfList dd 0H
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.data?
hInstance dd ?
hList dd ?
lvi LV_ITEM <?>
Buffer db 32 dup(?)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.code
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
iRand proc _dwMin:DWORD, _dwMax:DWORD
local @dwRet:dword, @dqFreq:qword
pushad
invoke QueryPerformanceCounter,addr @dqFreq
mov eax,dword ptr @dqFreq
mov ecx, 13
mul ecx
add eax, 5
mov ecx, _dwMax
sub ecx, _dwMin
inc ecx
xor edx, edx
div ecx
mov @dwRet, edx
popad
mov eax, @dwRet
add eax,_dwMin ; eax = Rand_Number
ret
iRand endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
InsertColumns proc
LOCAL lvc:LV_COLUMN
invoke SendMessage,hList,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT or LVS_EX_FLATSB ,-1
mov lvc.imask,LVCF_TEXT+LVCF_WIDTH
mov lvc.pszText,offset ListCap1
mov lvc.lx,100
invoke SendMessage,hList, LVM_INSERTCOLUMN,0,addr lvc
or lvc.imask,LVCF_FMT
mov lvc.fmt,LVCFMT_LEFT ;CENTER
mov lvc.pszText,offset ListCap2
mov lvc.lx,130
invoke SendMessage,hList, LVM_INSERTCOLUMN, 1 ,addr lvc
ret
InsertColumns endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AddItem proc _hList:DWORD, item:DWORD, subitem:DWORD, tdata:DWORD
LOCAL newitem:LV_ITEM
LOCAL lstmsg:DWORD
mov newitem.imask, LVIF_TEXT
m2m newitem.iItem, item
m2m newitem.iSubItem, subitem
m2m newitem.pszText, tdata
invoke lstrlen, tdata
inc eax
mov newitem.cchTextMax, eax
.IF subitem == 0h
mov lstmsg, LVM_INSERTITEM
.ELSE
mov lstmsg, LVM_SETITEM
.ENDIF
invoke SendMessage, _hList, lstmsg, 0h, addr newitem
invoke SendMessage, _hList, LVM_ENSUREVISIBLE, item, FALSE
ret
AddItem endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AddItemInt proc _hList:DWORD,item:DWORD,subitem:DWORD,tdword:DWORD
invoke RtlZeroMemory,addr Buffer,sizeof Buffer
invoke wsprintf,addr Buffer, CTXT('%i'), tdword
invoke AddItem, _hList,item,subitem,addr Buffer
ret
AddItemInt endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CreateButton proc hParent:DWORD,lpText:DWORD,x:DWORD,y:DWORD,w:DWORD,h:DWORD,ID:DWORD
LOCAL hFont :DWORD
invoke CreateFont,14,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE, \
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, \
DEFAULT_QUALITY,DEFAULT_PITCH, CTXT("Arial")
mov hFont, eax
invoke CreateWindowEx,0,CTXT('BUTTON'),lpText,WS_CHILD or WS_VISIBLE ,
x,y,w,h,hParent,ID,
hInstance,NULL
push eax
invoke SendMessage,eax,WM_SETFONT,hFont, 0
pop eax
ret
CreateButton endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CreateListView proc hParent:DWORD, x:DWORD,y:DWORD,w:DWORD,h:DWORD,ID:DWORD
LOCAL hFont :DWORD
invoke CreateFont,15,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE, \
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, \
DEFAULT_QUALITY,DEFAULT_PITCH, CTXT("Arial")
mov hFont, eax
invoke CreateWindowEx, WS_EX_STATICEDGE + WS_EX_TRANSPARENT,\
CTXT("SysListView32"),CTXT("test"),WS_TABSTOP + WS_VSCROLL + CBS_SIMPLE + WS_VISIBLE + WS_CHILD,x,y,w,h,\
hParent,ID,hInstance,NULL
push eax
invoke SendMessage,eax,WM_SETFONT,hFont, 0
pop eax
ret
CreateListView endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
;---------------------------------------------------------
; Added some local vars here
;---------------------------------------------------------
LOCAL lvitem:LV_ITEM ; local var for listview item used for LVM_GETITEM and LVM_SETITEM
LOCAL nItem:DWORD ; temp var for our listview item index used during NMCUSTOMDRAW - could use a reg instead of a var if you wanted
;---------------------------------------------------------
mov eax,uMsg
.if eax == WM_CREATE
invoke CreateButton,hWnd,CTXT('Stop'),71,256,56,20,IDB_STOP
invoke CreateButton,hWnd,CTXT('Exit'),7,256,56,20,IDB_EXIT
invoke CreateListView,hWnd,7,16,398,229,IDC_LIST
mov hList,eax
invoke SendMessage,hList,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT or LVS_EX_HEADERDRAGDROP OR LVS_EX_GRIDLINES,-1
invoke InsertColumns
invoke SetTimer,hWnd,0,1000,0
.elseif eax==WM_TIMER
push ebx
invoke iRand,100,800
mov eax,IndexOfList
inc eax
invoke AddItemInt,hList,IndexOfList,0,eax
invoke iRand,100,800
mov ebx,eax
invoke AddItemInt,hList,IndexOfList,1,ebx
.if ebx > 100 && ebx < 150
mov @dwSetTextBKColor,0FFADADH
.elseif ebx >= 150 && ebx < 300
mov @dwSetTextBKColor,0ADFFADH
.elseif ebx >= 300 && ebx < 400
mov @dwSetTextBKColor,0ADADFFH
.elseif ebx >= 400 && ebx < 550
mov @dwSetTextBKColor,0FF00ADH
.elseif ebx >= 550 && ebx < 800
mov @dwSetTextBKColor,000ADFFH
.else
mov @dwSetTextBKColor,0FF0000H
.endif
;---------------------------------------------------------
; Here we set the backcolor to the listview item we created
; using lParam to store the backcolor value for later on
;---------------------------------------------------------
mov eax, LVIF_PARAM
mov lvitem.imask, eax
mov eax, IndexOfList
mov lvitem.iItem, eax
mov lvitem.iSubItem, 0
mov eax, @dwSetTextBKColor
mov lvitem.lParam, eax
Invoke SendMessage, hList, LVM_SETITEM, 0, Addr lvitem
;---------------------------------------------------------
inc IndexOfList
pop ebx
.elseif eax == WM_COMMAND
.if wParam == IDB_EXIT
invoke DestroyWindow, hWnd
.elseif wParam==IDB_STOP
invoke KillTimer,hWnd,0
.endif
.elseif eax == WM_NOTIFY
;---------------------------------------------------------
; i changed this a little bit
;---------------------------------------------------------
mov ecx, lParam
mov eax, ( [ecx].NMHDR.code)
mov ebx, ( [ecx].NMHDR.hwndFrom)
.IF ebx == hList ; in case we have other listview controls, we check which one we are going to modify nmcustomdraw for
.IF eax == NM_CUSTOMDRAW
mov ecx, lParam
mov eax, (NMLVCUSTOMDRAW ptr[ecx]).nmcd.dwDrawStage
.IF eax == CDDS_PREPAINT
mov eax, CDRF_NOTIFYITEMDRAW
ret
.ELSEIF eax == CDDS_ITEMPREPAINT
mov eax, CDRF_NOTIFYSUBITEMDRAW
ret
.ELSEIF eax == CDDS_ITEMPREPAINT or CDDS_SUBITEM
mov ecx, lParam
mov eax, (NMLVCUSTOMDRAW ptr[ecx]).nmcd.dwItemSpec ; listview item
mov nItem, eax ; could use a reg instead of a var for this i suppose
mov eax, LVIF_PARAM
mov lvitem.imask, eax
mov eax, nItem
mov lvitem.iItem, eax
mov lvitem.iSubItem, 0
Invoke SendMessage, hList, LVM_GETITEM, 0, Addr lvitem ; fetch lparam which holds color to use
mov eax, lvitem.lParam ; we have it now in eax
mov ecx, lParam
mov (NMLVCUSTOMDRAW ptr[ecx]).clrTextBk, eax ; set color of listview item
mov eax, CDRF_NOTIFYSUBITEMDRAW
ret
.ELSE
mov eax, CDRF_DODEFAULT
ret
.ENDIF
.ENDIF
.ENDIF
;---------------------------------------------------------
.elseif eax == WM_CLOSE
invoke KillTimer,hWnd,0
invoke DestroyWindow, hWnd
.elseif eax == WM_DESTROY
invoke PostQuitMessage, NULL
.else
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.endif
xor eax, eax
ret
DlgProc endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TopXY proc wDim:DWORD, sDim:DWORD
shr sDim, 1
shr wDim, 1
mov eax, wDim
sub sDim, eax
mov eax, sDim
ret
TopXY endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WinMain proc hInst:DWORD,hPrevInst:DWORD, CmdLine:DWORD, CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL Wwd:DWORD
LOCAL Wht:DWORD
LOCAL Wtx:DWORD
LOCAL Wty:DWORD
LOCAL hWnd:HANDLE
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_BYTEALIGNCLIENT or CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc, offset DlgProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance,hInst
mov wc.hbrBackground, COLOR_BTNFACE+1
mov wc.lpszClassName, CTXT("test_list")
invoke LoadIcon, NULL, IDI_APPLICATION
mov wc.hIcon, eax
mov wc.hIconSm, eax
invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax
invoke RegisterClassEx, addr wc
mov Wwd, 425
mov Wht, 320
invoke GetSystemMetrics,SM_CXSCREEN
invoke TopXY,Wwd,eax
mov Wtx, eax
invoke GetSystemMetrics,SM_CYSCREEN
invoke TopXY,Wht,eax
mov Wty, eax
invoke CreateWindowEx, NULL, CTXT("test_list"),CTXT("test_list"), WS_OVERLAPPEDWINDOW,\
Wtx,Wty,Wwd,Wht,NULL, NULL, hInst, NULL
mov hWnd, eax
invoke ShowWindow, hWnd, SW_SHOWNORMAL
invoke UpdateWindow, hWnd
.while TRUE
invoke GetMessage, addr msg, NULL, 0, 0
.break .if (!eax)
invoke TranslateMessage, addr msg
invoke DispatchMessage, addr msg
.endw
mov eax, msg.wParam
ret
WinMain endp
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke GetCommandLine
invoke WinMain, hInstance ,NULL, eax, SW_SHOWDEFAULT
invoke ExitProcess,0
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
end start
it's ok!
Hi,fearless.thanks your help.
thank you very much!
:t :t :t
Forgot to post the link to the my tutorial yesterday... MASM - Custom Draw Listview and Header (http://www.dreamincode.net/forums/topic/283055-masm-custom-draw-listview-and-header/)
Hi
I use a Report listview an try to draw the color
I use this exmample from Fearless
http://masm32.com/board/index.php?topic=3106.msg32299#msg32299
but send not any CDDS_ITEMPREPAINT Messages by add a item
.elseif uMsg == WM_NOTIFY
mov ecx, lParam
mov eax, ( [ecx].NMHDR.code)
mov ebx, ( [ecx].NMHDR.hwndFrom)
.IF ebx == hList ; in case we have other listview controls, we check which one we are going to modify nmcustomdraw for
.IF eax == NM_CUSTOMDRAW
mov ecx, lParam
mov eax, (NMLVCUSTOMDRAW ptr[ecx]).nmcd.dwDrawStage
.IF eax == CDDS_PREPAINT
mov eax, CDRF_NOTIFYITEMDRAW
ret
.ELSEIF eax == CDDS_ITEMPREPAINT ;<<<<<<
invoke MessageBox,hWnd,0,0,0
mov eax, CDRF_NOTIFYSUBITEMDRAW
ret
.ELSEIF eax == CDDS_ITEMPREPAINT or CDDS_SUBITEM ;<<<<<<
invoke MessageBox,hWnd,0,0,0
mov ecx, lParam
mov eax, (NMLVCUSTOMDRAW ptr[ecx]).nmcd.dwItemSpec ; listview item
mov nItem, eax ; could use a reg instead of a var for this i suppose
...
..
Can you tell me what is wrong?
Solved
but why must a use SetWindowLong
.if [edx].nmcd.dwDrawStage == CDDS_PREPAINT
mov eax,CDRF_NOTIFYSUBITEMDRAW
@@:
invoke SetWindowLong,hWnd,DWL_MSGRESULT,eax
ret
.elseIf [edx].nmcd.dwDrawStage == CDDS_ITEMPREPAINT
mov eax,CDRF_NOTIFYSUBITEMDRAW
jmp @B
Other example works without SetWindowLong
Regards,
One more example of color listview (previously posted on the old board.)
As for the SetWindowLong requirement, it's necessary within DlgProc because the value returned in eax is to indicate whether the message was processed (whereas WndProc can return the value directly), so it's used as an alternative way to return a value without interfering with DlgProc's return value.
hi,Tedd
there is some the flaw in codes.
.ELSEIF (eax==WM_CREATE)
invoke CenterScreen,hwnd
invoke InitCommonControls
invoke CreateWindowEx, NULL,ADDR LvClass,NULL,WS_CHILD or WS_VISIBLE or LVS_REPORT or LVS_SHOWSELALWAYS,0,0,0,0,hwnd,IDLISTVIEW,hInstance,NULL
mov hListview,eax
invoke SendMessage, hListview,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT
invoke LvAddColumns,hListview,ADDR LvCols
invoke example_data
invoke example_data
invoke example_data
the method of fearless can store the listview color forever.
Hi Tedd
I have read i must use SetWindowlong if i have a resource Dialog and not virtual Dialog
And i put the WM_NOTIFY part from your example in my project it not works without SetWindowLong why?
Regards,
Quote from: six_L on December 22, 2014, 02:36:54 AM
hi,Tedd
there is some the flaw in codes.
.ELSEIF (eax==WM_CREATE)
invoke CenterScreen,hwnd
invoke InitCommonControls
invoke CreateWindowEx, NULL,ADDR LvClass,NULL,WS_CHILD or WS_VISIBLE or LVS_REPORT or LVS_SHOWSELALWAYS,0,0,0,0,hwnd,IDLISTVIEW,hInstance,NULL
mov hListview,eax
invoke SendMessage, hListview,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT
invoke LvAddColumns,hListview,ADDR LvCols
invoke example_data
invoke example_data
invoke example_data
the method of fearless can store the listview color forever.
The flaw is caused by your modification.
As a simple example, the row index is used to look up the color in the palette 'brg_pal', which is only 5 items long. So the colors for the 6th item onwards are essentially undefined (come from junk in memory.)
You could either extend brg_pal to match the number of items so there are enough colors, or wrap the palette index to start from zero again.
It obviously depends on your application, but the aim should be to determine the color for each item according to your own purpose. It may be appropriate to use the item's index to decide its color, or you can assign persistent colors in lParam.
Quote from: ragdog on December 22, 2014, 05:49:35 AM
I have read i must use SetWindowlong if i have a resource Dialog and not virtual Dialog
And i put the WM_NOTIFY part from your example in my project it not works without SetWindowLong why?
If you have a DialogProc, you must use SetWindowLong to return values for custom draw.
Thanks
hi,Tedd
QuoteIt may be appropriate to use the item's index to decide its color, or you can assign persistent colors in lParam.
:t
Thanks.