1. Sorting and listviews
Hi All,
Two things.
Firstly is it possible to use your own sort routine when you click a column
header in a listview.
Secondly has anyone written a sort routine they would like to share. My
problem is as follows:
N1-1-1
N1-1-10
N1-1-2
N1-1-3
This is a typical numbering system used in master key systems and I would
rather have them display in a listview as follows:
N1-1-1
N1-1-2
N1-1-3
N1-1-10
The default sort routine looks very unprofessional, and as I use the lists
to set the order of reports it is even more un professional.
Thanks
Tony Steward
Come Visit Me At www.locksdownunder.com
2. Re: Sorting and listviews
- Posted by euman at bellsouth.net
Jul 13, 2001
-- tagNMHDR
NMHDR_hwndFrom = 0,
NMHDR_idFrom = 4,
NMHDR_code = 8,
SIZEOF_NMHDR = 12
elsif iMsg = WM_NOTIFY then
-- call_back
iMsg = peek4s(lParam + NMHDR_code)
if iMsg = LVN_COLUMNCLICK then
-- could run a sort routine here
elsif iMsg = NM_CLICK then
end if
return 0
Look into the Microsoft Platform SDK for listview
LVN_COLUMNCLICK is the iMsg returned by the
listview control when a header button is clicked.
NM_CLICK is in the data area of the listview.
I looked at Matts code in Win32lib and it isnt set up
like this but this should give you an idea as where to
start looking.
I just finished writting my wrapper to the listview
in streamlined API and it was really fun because
the SDK is kindof confuseing.
set your trace at WM_NOTIFY under LVN_COLUMNCLICK
also, there is a flag that tells Windows to autosort the LV
but am not sure where that is in win32lib but you'll need to remove
this.
look below for a very simple listview wrapper
thats incomplete compared to win32lib but does the job
I modified it some to show you how it might work.
constant
LVS_REPORT = 1,
LVS_SHOWSELALWAYS = 8,
LVIF_TEXT = 1,
LVCF_FMT = 1,
LVCF_WIDTH = 2,
LVCF_TEXT = 4,
LVCF_SUBITEM = 8,
LVCF_ORDER = 20,
LVCFMT_LEFT = 0,
LVM_INSERTCOLUMN = 4123,
LVS_SHAREIMAGELISTS = 40,
LVM_SETITEM = 4102,
LVM_INSERTITEM = 4103,
LVM_SETBKCOLOR = 4097,
LVM_SETTEXTBKCOLOR = 4134,
LVM_SETTEXTCOLOR = 4132,
LVM_SETEXTENDEDLISTVIEWSTYLE = 4150,
LVS_EX_GRIDLINES = 1,
LVS_EX_TRACKSELECT = 8,
LVS_EX_HEADERDRAGDROP = 10,
LVS_EX_FULLROWSELECT = 20,
LVS_EX_ONECLICKACTIVATE = 40
constant
lvcol_mask = 0,
lvcol_fmt = 4,
lvcol_cx = 8,
lvcol_pszText = 12,
lvcol_cchTextMax = 16,
lvcol_iSubItem = 20,
lvcol_iOrder = 24,
sizeof_lvcol = 28
constant
lvitem_mask = 0,
lvitem_iItem = 4,
lvitem_iSubItem = 8,
lvitem_state = 12,
lvitem_stateMask = 16,
lvitem_pszText = 20,
lvitem_cchTextMax = 24,
lvitem_iImage = 28,
lvitem_lParam = 32,
lvitem_iIdent = 36,
sizeof_lvitem = 40
global constant
LVN_COLUMNCLICK = -108,
NM_CLICK = -2
sequence data
data = {{"Ringo","Starr"},
{"George","Harrison"},
{"Paul","McCartney"},
{"John","Lennon"}
}
procedure ListView_Column(atom id, atom lvcol, sequence text, integer item,
integer width )
atom itxt, junk
itxt = allocate_string(text)
poke4( lvcol + lvcol_cx, width)
poke4( lvcol + lvcol_pszText, itxt )
poke4( lvcol + lvcol_iSubItem, item )
junk = c_func(SendMessage,{id, LVM_INSERTCOLUMN, 0, lvcol})
end procedure
global atom ListView1, lvcol
global procedure MakeListView(atom hwnd, atom hInst, integer x1, integer y1,
integer x2, integer y2)
atom szName, szName2, item, seq, lvMask
object junk
lvMask =
or_all({LVS_EX_FULLROWSELECT,LVS_EX_HEADERDRAGDROP,LVS_EX_GRIDLINES,LVS_EX_ONECL
ICKACTIVATE, LVS_EX_TRACKSELECT })
szName = allocate_string("SysListView32")
szName2 = allocate_string("ListView1")
ListView1 = c_func(CreateWindow,{WS_EX_CLIENTEDGE,
szName,
szName2,
or_all({WS_CHILD,
WS_TABSTOP,
WS_VISIBLE,
#241,
WS_BORDER,
LVS_REPORT
--LVS_SHOWSELALWAYS
}),
x1,
y1,
x2,
y2,
hwnd,
0,
hInst,
NULL})
free(szName)
free(szName)
junk = c_func(SendMessage,{ListView1, LVM_SETEXTENDEDLISTVIEWSTYLE, lvMask,
lvMask})
junk = c_func(SendMessage,{ListView1,LVM_SETBKCOLOR, 0, 16744576})
junk = c_func(SendMessage,{ListView1,LVM_SETTEXTBKCOLOR, 0, 16744576})
junk = c_func(SendMessage,{ListView1,LVM_SETTEXTCOLOR, 0, 16777088})
junk = c_func(SendMessage,{ListView1,WM_SETREDRAW,0,0})
lvcol = allocate_struct(sizeof_lvcol)
poke4( lvcol + lvcol_mask, or_all({LVCF_FMT, LVCF_SUBITEM, LVCF_TEXT,
LVCF_WIDTH}))
poke4( lvcol + lvcol_fmt, LVCFMT_LEFT)
ListView_Column(ListView1, lvcol, "7", 7, 33 )
ListView_Column(ListView1, lvcol, "6", 6, 33 )
ListView_Column(ListView1, lvcol, "5", 5, 33 )
ListView_Column(ListView1, lvcol, "4", 4, 33 )
ListView_Column(ListView1, lvcol, "3", 3, 33 )
ListView_Column(ListView1, lvcol, "2", 2, 33 )
ListView_Column(ListView1, lvcol, "1", 1, 98 )
ListView_Column(ListView1, lvcol, "Date", 0, 100 )
item = allocate_struct(sizeof_lvitem)
poke4( item + lvitem_mask, LVIF_TEXT )
for i = 1 to length(data) do
seq = allocate_string(data[i][1])
poke4( item + lvitem_pszText, seq)
poke4( item + lvitem_iItem,0)
poke4( item + lvitem_iSubItem, 0)
junk = c_func(SendMessage,{ListView1, LVM_INSERTITEM, 0, item })
seq = allocate_string(data[i][2])
poke4( item + lvitem_pszText, seq)
poke4( item + lvitem_iItem,0)
poke4( item + lvitem_iSubItem, 1)
junk = c_func(SendMessage,{ListView1, LVM_SETITEM, 0, item })
-- etc....etc
end for
free(seq)
junk =
c_func(SendMessage,{ListView1,WM_SETFONT,c_func(GetStockObject,{DEFAULT_GUI_FONT
}),0})
junk = c_func(SendMessage,{ListView1,WM_SETREDRAW,1,0})
end procedure
Hope this helps some!
Euman
euman at bellsouth.net
>
> Hi All,
> Two things.
> Firstly is it possible to use your own sort routine when you click a column
> header in a listview.
>
> Secondly has anyone written a sort routine they would like to share. My
> problem is as follows:
> N1-1-1
> N1-1-10
> N1-1-2
> N1-1-3
>
> This is a typical numbering system used in master key systems and I would
> rather have them display in a listview as follows:
> N1-1-1
> N1-1-2
> N1-1-3
> N1-1-10
>
> The default sort routine looks very unprofessional, and as I use the lists
> to set the order of reports it is even more un professional.
>
> Thanks
> Tony Steward
>
> Come Visit Me At www.locksdownunder.com
3. Re: Sorting and listviews
----- Original Message -----
From: "Tony Steward" <figjam at nlc.net.au>
To: "EUforum" <EUforum at topica.com>
Subject: Sorting and listviews
> Two things.
> Firstly is it possible to use your own sort routine when you click a
column
> header in a listview.
Hi Tony,
if you make the changes I've got below to win32lib.ew, you will be able to
use your own sort routine.
You need to replace the existing function called "lvSortitems" in the
library with the code below...
---Start New Code---------
global integer lvSortRoutine
function local_lvsortrtn(integer id, integer col,
integer direction,
sequence a, sequence b)
return( compare(a, b) * direction )
end function
lvSortRoutine = routine_id("local_lvsortrtn")
function lvSortitems( atom lParam1, atom lParam2, atom owner )
integer sign, lv
lv = lv_allowsort[owner]
if lv < 0 then
sign = -1
lv = - lv
else
sign = 1
end if
return call_func(lvSortRoutine,{lv_id[owner], lv, sign,
peek_string(lvitem_data[lParam1][2][lv][1] ),
peek_string(lvitem_data[lParam2][2][lv][1] )
})
end function
---End New Code---------
then in your program you need to create a sort function that takes five
parameters.
1) The integer ID of the listview control requesting the sort.
2) The integer column number that was clicked.
3) The integer direction to sort in. -1 means Largest to Smallest, 1 means
Smallest to Largest.
4) A sequence value (string) from the column the user clicked.
5) Another sequence value (string) from the same column.
Your function must return an integer.
0 ==> When values are equal.
1 ==> When first string should go after the second.
-1 ==> When first string should go before the second.
Next, set the global variable "lvSortRoutine" with the routine_id() of your
sorting function. And that's it.
> Secondly has anyone written a sort routine they would like to share. My
> problem is as follows:
> N1-1-1
> N1-1-10
> N1-1-2
> N1-1-3
>
> This is a typical numbering system used in master key systems and I would
> rather have them display in a listview as follows:
> N1-1-1
> N1-1-2
> N1-1-3
> N1-1-10
>
For your specific situation you could try something like this ...
-- Custom Sort Routine --
function expand_key(sequence key)
atom val
sequence newkey, elem
integer digit
-- Initialize
newkey = {}
elem = {}
val = -1
-- Inspect each character
for i = 1 to length(key) do
-- Test for digit.
digit = find(key[i], "0123456789") - 1
-- Is this a digit?
if digit < 0 then
-- No. Am I collecting non-digits?
if val < 0 then
-- Yes. Add it to current element.
elem &= key[i]
else
-- No. Append current number.
newkey &= {{val}}
-- Indicate that I'm now collecting non-digits
val = -1
-- Init current element to this char.
elem = {key[i]}
end if
else
-- Yes. Am I collecting digits?
if val < 0 then
-- No. Append uppercase version of current element.
newkey &= {upper(elem)}
-- reset current element.
elem = {}
-- indicate that I'm now collecting digits and
-- get first digit.
val = digit
else
-- Yes. Convert digit to number
val = (val * 10) + digit
end if
end if
end for
-- Don't forget to append the last token.
if val < 0 then
newkey &= {upper(elem)}
else
newkey &= {{val}}
end if
-- Send back the expanded key.
return newkey
end function
integer stdsort
function SortKeyNumbers(integer id,
integer colm,
integer direction,
sequence KeyA,
sequence KeyB
)
sequence
lExpandedKeyA,
lExpandedKeyB
-- If this is not the right listview or column
-- use the original sorting routine.
if id != myLV or colm != myColumn then
return call_func(stdsort, {id, direction, KeyA, KeyB})
end if
-- Convert the key 'numbers' into expanded form.
lExpandedKeyA = expand_key(KeyA)
lExpandedKeyB = expand_key(KeyB)
return (compare(lExpandedKeyA, lExpandedKeyB) * direction)
end function
-- Save original sorting routine.
stdsort = lvSortRoutine
-- Insert my custom routine.
lvSortRoutine = routine_id("SortKeyNumbers")
-- End of Custom Sort Routine --
---------------
Good luck,
Derek
4. Re: Sorting and listviews
Hi Tony,
> Secondly has anyone written a sort routine they would like to share. > My
problem is as follows:
> N1-1-1
> N1-1-10
> N1-1-2
> N1-1-3
>
> This is a typical numbering system used in master
> key systems and I would
> rather have them display in a listview as follows:
> N1-1-1
> N1-1-2
> N1-1-3
> N1-1-10
>
> The default sort routine looks very unprofessional,
> and as I use the lists
> to set the order of reports it is even more un professional.
The possible solution is :
N1-1-01
N1-1-10
N1-1-02
N1-1-03
Then standard RDS include sort.e
and sort() works as you wish, i.e.
N1-1-01
N1-1-02
N1-1-03
N1-1-10
Same about DOS's sort command.
Maybe, this helps too.
Regards,
Igor Kachan
kinz at peterlink.ru
5. Re: Sorting and listviews
- Posted by gertie at ad-tek.net
Jul 13, 2001
On 13 Jul 2001, at 22:17, Igor Kachan wrote:
>
> Hi Tony,
>
> > Secondly has anyone written a sort routine they would like to share. > My
> problem is as follows:
> > N1-1-1
> > N1-1-10
> > N1-1-2
> > N1-1-3
> >
> > This is a typical numbering system used in master
> > key systems and I would
> > rather have them display in a listview as follows:
> > N1-1-1
> > N1-1-2
> > N1-1-3
> > N1-1-10
> >
> > The default sort routine looks very unprofessional,
> > and as I use the lists
> > to set the order of reports it is even more un professional.
>
>
> The possible solution is :
>
> N1-1-01
> N1-1-10
> N1-1-02
> N1-1-03
>
> Then standard RDS include sort.e
> and sort() works as you wish, i.e.
>
> N1-1-01
> N1-1-02
> N1-1-03
> N1-1-10
Great minds think alike, eh, Igor? I was just coding that solution too! The
code to do this would be sort of like:
-- Sort a list
-- Kat
-- July 13, 2001
with trace
include sort.e
include get.e
include strtok.e - you might haveto make parse() and deparse() global
atom key
sequence list, parsedlist
-- set list to something, so we can sort it
list = {
"N1-1-1",
"N1-1-10",
"N1-1-2",
"N1-1-3",
"N3-1-10",
"N3-4-2",
"N21-5-9"
}
puts(1,"starting with:\n")
for loop = 1 to length(list) do
puts(1,list[loop]&"\n")
end for
puts(1,"\n\n")
for loop = 1 to length(list) do
parsedlist = parse(list[loop],'-')
for loop2 = 1 to length(parsedlist) do
while length(parsedlist[loop2]) < 5 do -- 5 is a rather random number
parsedlist[loop2] = "0" & parsedlist[loop2]
end while
end for
list[loop] = deparse(parsedlist,'-')
end for
list = sort(list)
for loop = 1 to length(list) do
parsedlist = parse(list[loop],'-')
for loop2 = 1 to length(parsedlist) do
while equal('0',parsedlist[loop2][1]) do
parsedlist[loop2] = parsedlist[loop2][2..length(parsedlist[loop2])]
end while
end for
list[loop] = deparse(parsedlist,'-')
end for
for loop = 1 to length(list) do
puts(1,list[loop]&"\n")
end for
puts(1,"\n\nall done, press something to close out\n\n")
key = wait_key()
Kat
6. Re: Sorting and listviews
- Posted by irvm at ellijay.com
Jul 13, 2001
On Friday 13 July 2001 05:25, Tony Steward wrote:
> Secondly has anyone written a sort routine they would like to share. My
> problem is as follows:
> N1-1-1
> N1-1-10
> N1-1-2
> N1-1-3
>
> This is a typical numbering system used in master key systems and I would
> rather have them display in a listview as follows:
> N1-1-1
> N1-1-2
> N1-1-3
> N1-1-10
>
> The default sort routine looks very unprofessional, and as I use the lists
> to set the order of reports it is even more un professional.
>
> Thanks
> Tony Steward
Here's a way that works by converting the array into numbers, sorting, then
converting back to strings for display. If you've got a mix of numeric and
non-numerics, ("N1-1-10A") then it won't without some serious modifications.
include sort.e
include get.e
include strtok.e
sequence s, sn
object v
s = {"N1-1-1","N1-1-10","N1-1-3","N1-1-2"}
sn = s -- save into temporary new array
for i = 1 to length(sn) do
sn[i] = parse(sn[i],'-') -- parse into numbers
v = value(sn[i][2]) -- convert to numeric
sn[i][2] = v[2]
v = value(sn[i][3])
sn[i][3] = v[2]
? sn[i]
end for
puts(1,"Sorted\n")
sn = sort(sn)
for i = 1 to length(sn) do -- change 'em back to strings
printf(1,"%s-%d-%d\n",{sn[i][1],sn[i][2],sn[i][3]})
end for
7. Re: Sorting and listviews
- Posted by gertie at ad-tek.net
Jul 13, 2001
On 13 Jul 2001, at 21:03, irvm at ellijay.com wrote:
>
> On Friday 13 July 2001 05:25, Tony Steward wrote:
>
> > Secondly has anyone written a sort routine they would like to share. My
> > problem is as follows:
> > N1-1-1
> > N1-1-10
> > N1-1-2
> > N1-1-3
> >
> > This is a typical numbering system used in master key systems and I would
> > rather have them display in a listview as follows:
> > N1-1-1
> > N1-1-2
> > N1-1-3
> > N1-1-10
> >
> > The default sort routine looks very unprofessional, and as I use the lists
> > to set the order of reports it is even more un professional.
> >
> > Thanks
> > Tony Steward
>
> Here's a way that works by converting the array into numbers, sorting, then
> converting back to strings for display. If you've got a mix of numeric and
> non-numerics, ("N1-1-10A") then it won't without some serious modifications.
<snip>
-- copy/pasted from screen:
starting with:
N1-1-1
N21-5-9
N1-1-10
N1-1-2
N1-1-3
B6-3-65
X32-6ba-2
X32-6a2-2
X32-6a-2
N3-1-10
N3-4-2
B6-3-65a
press something to sort it
B6-3-65
B6-3-65a
N1-1-1
N1-1-2
N1-1-3
N1-1-10
N3-1-10
N3-4-2
N21-5-9
X32-6a-2
X32-6a2-2
X32-6ba-2
all done, press something to close out
-- Sort a list
-- Kat
-- July 13, 2001
with trace
include sort.e
include get.e
include strtok.e
atom key
sequence list, parsedlist
-- set list to something, so we can sort it
list = {
"N1-1-1",
"N21-5-9",
"N1-1-10",
"N1-1-2",
"N1-1-3",
"B6-3-65",
"X32-6ba-2",
"X32-6a2-2",
"X32-6a-2",
"N3-1-10",
"N3-4-2",
"B6-3-65a"
}
puts(1,"starting with:\n")
for loop = 1 to length(list) do
puts(1,list[loop]&"\n")
end for
puts(1,"\n\npress something to sort it\n\n")
key = wait_key()
for loop = 1 to length(list) do
parsedlist = parse(list[loop],'-')
for loop2 = 1 to length(parsedlist) do
while length(parsedlist[loop2]) < 5 do
parsedlist[loop2] = "0" & parsedlist[loop2]
end while
end for
list[loop] = deparse(parsedlist,'-')
end for
list = sort(list)
for loop = 1 to length(list) do
parsedlist = parse(list[loop],'-')
for loop2 = 1 to length(parsedlist) do
while equal('0',parsedlist[loop2][1]) do
parsedlist[loop2] = parsedlist[loop2][2..length(parsedlist[loop2])]
end while
end for
list[loop] = deparse(parsedlist,'-')
end for
for loop = 1 to length(list) do
puts(1,list[loop]&"\n")
end for
puts(1,"\n\nall done, press something to close out\n\n")
key = wait_key()