The MASM Forum

General => The Campus => Topic started by: six_L on April 12, 2014, 08:11:20 AM

Title: the listview color lost.
Post by: six_L on April 12, 2014, 08:11:20 AM
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
Title: Re: the listview color lost.
Post by: jj2007 on April 12, 2014, 09:07:44 AM
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 ::)
Title: Re: the listview color lost.
Post by: six_L on April 13, 2014, 11:51:18 AM
thanks your response.
the trouble is still there.
WM_TIMER: creates the random number,set the color of listview cows acorroding to its value. 
Title: Re: the listview color lost.
Post by: jj2007 on April 13, 2014, 05:10:13 PM
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...
Title: Re: the listview color lost.
Post by: GoneFishing on April 13, 2014, 05:22:46 PM
.
Title: Re: the listview color lost.
Post by: fearless on April 13, 2014, 10:37:37 PM
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
Title: Re: the listview color lost.
Post by: six_L on April 14, 2014, 05:58:01 PM
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?
Title: Re: the listview color lost.
Post by: ragdog on April 15, 2014, 01:40:14 AM
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,
Title: Re: the listview color lost.
Post by: six_L on April 15, 2014, 11:57:39 AM
hi ragdog,thanks your help.
this codes have the same trouble while many colors to be setted in the listview.
Title: Re: the listview color lost.
Post by: Gunner on April 15, 2014, 02:38:49 PM
I wrote a tutorial on this, here is the code for custom draw listview.
Title: Re: the listview color lost.
Post by: six_L on April 15, 2014, 04:58:25 PM
Hi,Gunner.thanks your help.
i used a majority of the codes, the exe attachment shows the same question.
Title: Re: the listview color lost.
Post by: jj2007 on April 15, 2014, 07:21:39 PM
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
Title: Re: the listview color lost.
Post by: fearless on April 15, 2014, 10:51:32 PM
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




Title: Re: the listview color lost.
Post by: six_L on April 16, 2014, 01:39:55 AM
it's ok!
Hi,fearless.thanks your help.
thank you very much!
:t :t :t
Title: Re: the listview color lost.
Post by: Gunner on April 16, 2014, 11:36:19 AM
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/)
Title: Re: the listview color lost.
Post by: ragdog on December 20, 2014, 10:30:58 PM
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,

Title: Re: the listview color lost.
Post by: Tedd on December 21, 2014, 05:01:31 AM
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.
Title: Re: the listview color lost.
Post by: 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.
Title: Re: the listview color lost.
Post by: ragdog on December 22, 2014, 05:49:35 AM
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,
Title: Re: the listview color lost.
Post by: Tedd on December 22, 2014, 06:32:30 AM
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.
Title: Re: the listview color lost.
Post by: Tedd on December 22, 2014, 06:39:04 AM
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.
Title: Re: the listview color lost.
Post by: ragdog on December 22, 2014, 08:21:44 AM
Thanks
Title: Re: the listview color lost.
Post by: six_L on December 22, 2014, 03:15:15 PM
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.