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.
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.
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
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.
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
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 ...
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.
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
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
Those are the results i am looking for. Now to try and get that to work with my listview
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
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.
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
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.
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
ok i understand what you mean to pad the string with zeros and it makes sense to me now why it does not work when i compare as a string. I will give both the ideas a try and i think the lParam idea is better since i wont have to worry about files that may be larger than my padding allows.
well i couldnt figure out how to get the lParam option to work but i wrote a function that adds "0"s to the beginning and then i use my function to strip the commas and compare them as a string and it works perfect now. Thanks for the help as always :D