The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: hutch-- on March 06, 2006, 06:58:13 AM

Title: List View quirk
Post by: hutch-- on March 06, 2006, 06:58:13 AM
I usually try and avoid the common controls like the plague as I dislike the interface for most of them but I needed to use a list view set up as close as possible to and old fashion listbox. I created the list view control with CreateWindowEx, set it up with one column and loaded some test items into it. To get the items from the list I made a subclass processing the WM_LBUTTONDBLCLICK message, fed the X Y co-ordinates into a LV_HITTESTINFO.POINT structure, retreived the index of the selected item with LVM_GETITEM and everything works except for one quirk, I must first click on the header button to get the text to display otherwise I get garbage back.

This is the subclass.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

LviewProc proc hCtl   :DWORD,
               uMsg   :DWORD,
               wParam :DWORD,
               lParam :DWORD

    LOCAL pbuf  :DWORD
    LOCAL buffer[128]:BYTE
    LOCAL lvi   :LV_ITEM
    LOCAL lht   :LV_HITTESTINFO

    .if uMsg == WM_COMMAND

    .elseif uMsg == WM_LBUTTONDBLCLK
      movsx eax, word ptr [ebp+20]
      mov lht.pt.x, eax
      movsx eax, word ptr [ebp+22]
      mov lht.pt.y, eax

      lea eax, buffer
      mov lvi.pszText, eax
      mov lvi.cchTextMax, 128

      invoke SendMessage,hLview,LVM_HITTEST,0,ADDR lht  ; get index of selection

      mov lvi.iItem, eax

      invoke SendMessage,hCtl,LVM_GETITEM,0,ADDR lvi
      fn MessageBox,hCtl,lvi.pszText,"Title",MB_OK

    .endif

    invoke CallWindowProc,lpLviewProc,hCtl,uMsg,wParam,lParam

    ret

LviewProc endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««


I want to run the list view control without a header button using the LVS_NOCOLUMNHEADER style but if I remove it, I have no way of activating the text and just get garbage back.

Has anyone run into this problem before ?
Title: Re: List View quirk
Post by: zooba on March 06, 2006, 09:58:14 AM
I haven't run into this specific problem before, but I would be inclined to use LVM_GETNEXTITEM (http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/listview/messages/lvm_getnextitem.asp) to search for the first selected and focused item rather than a hit-test. I've never had much success using hit-testing methods in VB before.

Cheers,

Zooba :U
Title: Re: List View quirk
Post by: PBrennick on March 06, 2006, 12:15:46 PM
Hutch,
Take a look at the attachment to see how I did my old style listbox.  Doubleclick any lineitem to see the text returned.  It may not be exactly what you are looking for but it sure works without a header.

Paul


[attachment deleted by admin]
Title: Re: List View quirk
Post by: arafel on March 06, 2006, 12:29:55 PM
Why resort to subclassing? You could catch double clicks from the main message procedure as well. Something like:

        .if uMsg == WM_NOTIFY

        mov     edi, lParam
        mov     eax, [edi.NMHDR].hwndFrom

                .if eax == [hListView]

                        .if [edi.NMHDR].code == NM_DBLCLK

                        invoke  SendMessage, [hListView], LVM_GETNEXTITEM, -1, LVNI_SELECTED
                        cmp     eax, -1
                        je      @f

                        mov     lvi.iItem, eax
                        mov     lvi.iSubItem, 0
                        mov     lvi.imask, LVIF_TEXT
                        lea     eax, tmp_buffer
                        mov     lvi.pszText, eax
                        mov     lvi.cchTextMax, tmp_buffer_size
                        invoke  SendMessage, [hListView], LVM_GETITEM, 0, ADDR lvi
                @@:
.endif
.endif
.endif
Title: Re: List View quirk
Post by: PBrennick on March 06, 2006, 12:49:36 PM
Arafel,
That is EXACTLY what I did in the attached project above.  Catch double clicks and no subclassing and return text.  Take a peek at it.  I like it when people think along the same lines.

Paul
Title: Re: List View quirk
Post by: arafel on March 06, 2006, 01:51:38 PM
Hehe, sorry Paul. I guess I was too hasty, so I didn't check the attachments.
Title: Re: List View quirk
Post by: PBrennick on March 06, 2006, 02:10:14 PM
arafel,
Actually, I was happy to see your posting.  It gives me the idea that my method might be useful.  :U

Paul
Title: Re: List View quirk
Post by: donkey on March 06, 2006, 02:14:47 PM
Hi Paul,

I haven't checked the attachments either because I am at work right now but in WinExplorer I do some pretty interesting things to listviews without any subclassing, context menus and the sort. I wrote a whole slew of demos and test beds for them while I was figuring them out, I may just end up doing a little tutorial on listviews from the basics right up to virtual listviews and custom drawn ones. Would you be interested in participating in a tutorial if I do one ? (MASM/GoAsm formats). Actually a full common controls tutorial by control type would be a more ambitious project.
Title: Re: List View quirk
Post by: PBrennick on March 06, 2006, 02:34:56 PM
Edgar,
That would be a very useful tutorial for address books, tables and such.  I would be happy to help.

Paul
Title: Re: List View quirk
Post by: Shantanu Gadgil on March 07, 2006, 10:12:08 AM
A complete "reading my mind" here!!! Will like to help !!!

After struggling with listviews, treeviews, owner drawn buttons, toolbars (and having succeded beacuse of the gracious helping on MASM Forum and of course Iczelion's tutorials) I was thinking the same.

What I was thinking was a bit more evil  :green2 ...take each and every control, rip it to shreds, chew it up and explain it nicely as to what it is...how it works, etc...more on the lines from a UI Designer perspective

Obviously the first "control", if any should be the dialog itself. I remember many hours spent because either some teeny-tiny style was not set or (the DlgProc not written correctly)
Title: Re: List View quirk
Post by: Gustav on March 07, 2006, 04:18:50 PM

Hutch,

as you surely know but possibly forgot: the LVITEM structure has a "mask" (or "imask") field where you have to tell windows what fields you want to be filled. Seems this field isn't filled in your code.

Regards


Title: Re: List View quirk
Post by: hutch-- on March 08, 2006, 02:16:02 PM
This scruffy mess actually works, probably one of the worst interfaces to a control i have ever seen.


      case WM_NOTIFY
        mov edx, lParam
        mov eax, (NMHDR PTR [edx]).hwndFrom
        .if eax == hLview
          mov eax, (NMHDR PTR [edx]).code
          .if eax == NM_DBLCLK
            invoke GetCursorPos,ADDR pt
            invoke ScreenToClient,hLview,ADDR pt
            mov ecx, pt.x
            mov edx, pt.y
            mov lht.pt.x, ecx
            mov lht.pt.y, edx
            invoke SendMessage,hLview,LVM_HITTEST,0,ADDR lht  ; get index of selection
            mov lvi.imask, LVIF_TEXT
            lea eax, buffer
            mov lvi.pszText, eax
            mov lvi.cchTextMax, 128
            mov lvi.iSubItem, 0
            invoke SendMessage,hLview,LVM_GETITEMTEXT,lht.iItem,ADDR lvi
            fn MessageBox,hWin,lvi.pszText,str$(lht.iItem),MB_OK
          .endif
        .endif


Microsoft YUK !
Title: Re: List View quirk
Post by: farrier on March 08, 2006, 02:50:12 PM
hutch--,

Instead of code between GetCursorPos thru LVM_HITTEST, you should be able to use:

invoke SendMessage, [hList], LVM_GETNEXTITEM, -1, LVNI_FOCUSED ;find the item that has the focus
mov [lvi.iItem], eax


hth,

farrier

Edit: This will only give the row, and not the row and column which is what you wanted :red
ReEdit: Actually, it might work, since you specify mov lvi.iSubItem, 0 :red
Title: Re: List View quirk
Post by: zcoder on March 08, 2006, 10:05:47 PM
Is there a reason your doing a hittest?
I do it like this:


        .elseif uMsg == WM_NOTIFY
                  mov esi,lParam
                  assume esi:ptr NMHDR
                  .if [esi].NMHDR.code == NM_DBLCLK
                      mov eax,[esi].NMHDR.hwndFrom
                      .if eax == hListView
                          invoke SendMessage,hListView,LVM_GETNEXTITEM,-1,LVNI_FOCUSED
                          or eax,eax
                          js No_Good
                          push eax
                          mov [lvi.iItem],eax
                          mov [lvi.iSubItem],0
                          mov [lvi.imask],LVIF_PARAM or LVIF_TEXT
                          mov [lvi.pszText],offset szFileName
                          mov [lvi.cchTextMax],MAX_PATH
                          mov byte ptr[szFileName],0
                          invoke SendMessage,hListView,LVM_GETITEM,0,addr lvi
                          pop eax
                          mov [lvi.iItem],eax
                          mov [lvi.iSubItem],2
                          mov [lvi.imask],LVIF_PARAM or LVIF_TEXT
                          mov [lvi.pszText],offset szFileType
                          mov [lvi.cchTextMax],MAX_PATH
                          mov byte ptr[szFileType],0
                          invoke SendMessage,hListView,LVM_GETITEM,0,addr lvi
                         ; at this point the item string is in szFileName
                    .endif
               .endif
No_Good:



If there is a reason for doing a hittest then ignore this code. :bg


Zcoder....
Title: Re: List View quirk
Post by: donkey on March 09, 2006, 12:06:10 AM
Hi Hutch,

I have found that with listviews the CLICK messages can be slightly delayed, making GetCursorPos unreliable. I use the following for a hit test in WM_NOTIFY where EDI contains the value in lParam (for listviews only - treeviews do not seem to suffer from the same issue)

invoke GetMessagePos
movzx edx,ax
mov D[lvhi.pt.x],edx
shr eax,16
and eax,0FFFFh
mov D[lvhi.pt.y],eax
invoke ScreenToClient,[edi+NMHDR.hwndFrom],OFFSET lvhi.pt
invoke SendMessage,[edi+NMHDR.hwndFrom],LVM_HITTEST,0,OFFSET lvhi
mov eax,[lvhi.iItem]
test eax,eax
js >.NOITEM
; perform a LVM_GETNEXTITEM to determine which item if any has the focus
invoke SendMessage,[edi+NMHDR.hwndFrom],LVM_GETNEXTITEM,-1,LVNI_FOCUSED
test eax,eax
js >.NOITEM


BTW if you use GetCursorPos there is no need for 2 POINT structures...

invoke GetCursorPos,ADDR lht.pt
invoke ScreenToClient,hLview,ADDR lht.pt
invoke SendMessage,hLview,LVM_HITTEST,0,ADDR lht  ; get index of selection
Title: Re: List View quirk
Post by: hutch-- on March 09, 2006, 12:22:50 AM
Donkey,

Thanks, for the test piece I wanted the LVM_HITTEST method as the task I had in mind was mouse based. Using the lht.pt structure is a good idea that saves the extra code.
Title: Re: List View quirk
Post by: donkey on March 09, 2006, 12:30:02 AM
Hi Hutch,

My pleasure. I generally only use the HITTEST to ensure that the user has actually clicked on an item then determine the item number using GETNEXTITEM. Otherwise the routine is called for any click inside the listview and if you set it to retain the focus using GETNEXTITEM will return the wrong item number. The example I posted is the most reliable way I have found to determine if first - the user actually selected an item and second - what the item number is. Every other way I attempted to solve this issue had it's own particular quirks.
Title: Re: List View quirk
Post by: farrier on March 09, 2006, 02:39:48 AM
In my WM_NOTIFY handler, this handles sort--thanks to donkey--,Enter Key, Single Click, and Double Click to process ListView line with focus, or line Clicked or DoubleClicked.



wmnotify:
.else
mov eax, NMHDR.hwndFrom ;NMHDR.hwndFrom
.if eax, e, [hList]
.if NMHDR.code, e, LVN_COLUMNCLICK
.if NM_LISTVIEW.iSubItem, e, 1
;sort listview here
.endif
.elseif NMHDR.code, e, LVN_KEYDOWN
.if NMLVKEYDOWN.wVKey, e, VK_RETURN
jmp .display_line
.endif
.elseif NMHDR.code, e, NM_CLICK
jmp .display_line
.elseif NMHDR.code, e, NM_DBLCLK
jmp .display_line
.endif
.endif
.endif
jmp .finish
.display_line:
invoke SendMessage, [hList], LVM_GETNEXTITEM, -1, LVNI_FOCUSED ;find the item that has the focus, was clicked on
mov [.lvi.iItem], eax
mov [.lvi.iSubItem], 0
mov [.lvi.imask], LVIF_TEXT
lea eax, [.buffer]
mov [.lvi.pszText], eax
mov [.lvi.cchTextMax], 256
lea eax, [.lvi]
invoke SendMessage, [hList], LVM_GETITEM, 0, eax ;gets info from listview


farrier