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

new topic     » topic index » view message » categorize

2. Re: Sorting and listviews

-- 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

new topic     » goto parent     » topic index » view message » categorize

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

new topic     » goto parent     » topic index » view message » categorize

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

new topic     » goto parent     » topic index » view message » categorize

5. Re: Sorting and listviews

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

new topic     » goto parent     » topic index » view message » categorize

6. Re: Sorting and listviews

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

new topic     » goto parent     » topic index » view message » categorize

7. Re: Sorting and listviews

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()

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu