News:

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

Listview sorting.

Started by jckl, April 27, 2007, 08:56:51 AM

Previous topic - Next topic

jckl

I am having trouble with sorting the size field of my listview. In the size i have commas which are causing the sorting to be wierd. It works to a point.

Here is how it would look if i sorted smallest to largest.

1,210,023
1,222,012
1,310,120
      240
      240
    1,120
    2,230
   19,300


I tried to strip the commas before converting ascii to base but that made it way off. I looked in the masm32 dir for examples and found one but it sorts this way aswell. The code i currently have in my app is the same as the example i found. the code for the size sorting is as follows.


         mov     lvi.iSubItem, 1
         INVOKE     SendMessage, hList, LVM_GETITEMTEXT, lParam1, addr lvi
         Invoke AsciiBase2, addr szBuff0

         mov     edi, eax
         INVOKE     SendMessage, hList, LVM_GETITEMTEXT, lParam2, addr lvi
         Invoke AsciiBase2, addr szBuff0       

         .if lParamSort == 3
               sub     edi, eax
               mov     eax, edi
         .else
               sub     eax, edi
         .endif


I used the asciibase from that example as well but had to rename it so it would not conflict with the asciibase function i already had.

The code to strip the commas is


cStrip PROC SRC:DWORD
   mov edi,SRC
   mov esi,edi
  toploop:
   lodsb
   cmp al,","
   jz @F
   stosb
  @@:
   test al,al
   jnz toploop
   ret
cStrip endp


I tried stripping the commas before and after the asciibase but it did not work either way. Like i said without the commas this works just fine.. I am not sure i fully understand how the sorting works or how to fix this. I tried to sort them the same way i sort the names but that also did not work.

Tedd

I'm not sure what mess you've got yourself into :lol but what you should be doing is:
- convert the number-strings into a number-values (ascii -> integer), ignoring the commas (or copy the string while removing them, then use a2d?)
- then compare these number-values (which can be held in registers)
- and return the appropriate value to indicate how the two given number-strings should be ordered relative to each other.
No snowflake in an avalanche feels responsible.

jckl

I tried what you said but my results came out wrong again. It sorted them but it didnt list them as if one number is larger than the others. It listed them based off each diggit for instance my result would look like the following.



    1,120
1,210,023
  121,100
1,222,012
1,310,120
   19,300
    2,230
      240
      240

hutch--

If you want these types of number,


      t0  db "123",0
      t1  db "1234",0
      t2  db "12345",0
      t3  db "123456",0
      t4  db "987",0
      t5  db "9876",0
      t6  db "98765",0
      t7  db "987654",0
      t8  db "234",0
      t9  db "2345",0
      t10 db "23456",0
      t11 db "234567",0
      t12 db "876",0
      t13 db "8765",0
      t14 db "87654",0
      t15 db "876543",0
      t16 db "5647",0
      t17 db "564738",0
      t18 db "56473829",0
      t19 db "5647382910",0


sorted to be like,


123
1234
12345
123456
234
2345
23456
234567
5647
564738
56473829
5647382910
876
8765
87654
876543
987
9876
98765
987654


Try string sorting. These are done witrh the masm32 library sorts.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jckl

I want to sort smallest to largest and largest to smallest based on the user clicking the listview header. I know there is an example in the masm folder but it does not work with commas in the listview items and for some reason it still does not work when i strip the commas before the ascii2base

ic2

jckl, your copy of Masm32 has Ewayne Listview Example in it.    Have you seen it.   He covered sorting too and it has some kind of BASE functions that may give you some ideas ...

jckl

correct his example is the one i went to and actually tried his code. It does not work if the numbers have commas as i display the commas.

zooba

I made this work in VB by creating two columns. One is displayed to the user (in my case in the local currency format), the other has a width of zero and has the number/value in a sortable format (for example, 00000000.00). Then when the user clicks on a column header, I checked if it was the currency one and if it was I'd set the sort column to the hidden one.

Worked fine unless the user dragged the hidden one open. Possibly there is a better way of doing the same thing, but this was good enough for my needs.

Cheers,

Zooba :U

MichaelW

jckl,

I'm still not sure what sort of results you are expecting. Assuming the strings are of a uniform length, and right justified with leading spaces, a string sort will put the strings in order alphabetically and numerically, without any need to eliminate the commas or convert to a number.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      sarr dd s1,s2,s3,s4,s5,s6,s7,s8,s9
      s1   db "    1,120",0
      s2   db "1,210,023",0
      s3   db "  121,100",0
      s4   db "1,222,012",0
      s5   db "1,310,120",0
      s6   db "   19,300",0
      s7   db "    2,230",0
      s8   db "      240",0
      s9   db "      240",0
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    print "smallest to largest",13,10
    invoke assort, ADDR sarr, 9, 0
    xor ebx, ebx
    .WHILE ebx < 9
      mov eax, [sarr+ebx*4]
      print eax,13,10
      inc ebx
    .ENDW

    print "largest to smallest",13,10
    invoke dssort, ADDR sarr, 9, 0
    xor ebx, ebx
    .WHILE ebx < 9
      mov eax, [sarr+ebx*4]
      print eax,13,10
      inc ebx
    .ENDW

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


smallest to largest
      240
      240
    1,120
    2,230
   19,300
  121,100
1,210,023
1,222,012
1,310,120
largest to smallest
1,310,120
1,222,012
1,210,023
  121,100
   19,300
    2,230
    1,120
      240
      240
eschew obfuscation

jckl

Those are the results i am looking for. Now to try and get that to work with my listview

zooba

I think that the strings haven't been right justified, that will have been the column setting in the list-view.

Right justifying with spaces won't look nice in a proportional font, though if the column format is still right-justified it may not be noticeable.

Cheers,

Zooba :U

jckl


    invoke SendMessage,hList, LVM_INSERTCOLUMN, 0, addr lvc
    or lvc.imask,LVCF_TEXT+LVCF_FMT
    mov lvc.fmt,LVCFMT_RIGHT
    mov lvc.pszText,offset Heading2
    mov lvc.lx,75


My column is right justifyed. Like i siad i can get it to sort the numbers if there is no comma but with the comma it causes the sorting to be wrong.

zooba

The comma should not be causing any problem with sorting since it appears in the same location in each number. The problem is either converting the string up to the first comma into a number, or treating numbers as strings.

The solution to the first one is not to stop converting when you hit a comma. If you're using a library function to do the conversion you'll probably need to modify it or find another one.

The solution to the second one is to make sure that each string is the same length by padding the start of it with spaces, as MichaelW has assumed is going on here already. Simply setting LVCFMT_RIGHT doesn't do this. When all strings are the same length with padding at the start the commas are irrelevant, since they will all be at the same offsets into each string. Two things to make sure of are that you select a field width which will be bigger than all the numbers you display and you select a padding character that sorts lower than a number (I've never come across a system where a space won't work for this).

Cheers,

Zooba :U

sinsi

When you add an item to the listview, can't you use LVITEM.lParam to store the value?
Quote
lParam
Value specific to the item. If you use the LVM_SORTITEMS message, the list-view control passes this value to the application-defined comparison function. You can also use the LVM_FINDITEM message to search a list-view control for an item with a specified lParam value.
The only trouble I can see here is if your value is more than 32 bits.
Light travels faster than sound, that's why some people seem bright until you hear them.

zooba

Much better solution, go with that.

If your numbers are bigger than 32-bits, use it as a 32-bit float or a pointer to a 64-bit integer/float, depending on what's appropriate.

Cheers,

Zooba :U