IonicWind Software

Announcements => User Offerings => Topic started by: Andy on May 26, 2019, 01:47:43 AM

Title: Easy way to move list view items up or down.
Post by: Andy on May 26, 2019, 01:47:43 AM
Thought this might be useful to lots of you.

It's a little sub routine to move an item in a list view up or down.

To begin you will need this at the top of your program:

$include "windowssdk.inc"
$include "commctrl.inc"

Now you need this to keep the selected list view item in view.

SetID "LVM_ENSUREVISIBLE",4115

Also this, the NMLISTVIEW structure so we can track which list view item is clicked:

TYPE NMLISTVIEW
    UINT hwndFrom
    INT  idFrom
    INT  code
    INT  iItem
    INT  iSubItem
    UINT uNewState
    UINT uOldState
    UINT uChanged
    INT  ptActionx
    INT  ptActiony
    INT  lParam
ENDTYPE

An int variable to store the position of the selected list view item

int LVpos = 0

In my program, I have two buttons called MoveUp and MoveDown ("+" and "-").

CONTROL win,@SysButton,"+",300,70,35,25,0x50018001,MoveUp
CONTROL win,@SysButton,"-",300,100,35,25,0x50018001,MoveDown

And of course a list view control...

CONTROL win,@LISTVIEW,"",340,70,940,510,@LVSREPORT|@BORDER|@LVSSHOWSELALWAYS|@LVSSINGLESEL|@VSCROLL,ListView
 SENDMESSAGE win,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT|LVS_EX_FLATSB|LBS_WANTKEYBOARDINPUT|LVS_EX_ONECLICKACTIVATE,ListView
 CONTROLCMD win,ListView,@LVINSERTCOLUMN,0,"Col 1"
 CONTROLCMD win,ListView,@LVINSERTCOLUMN,1,"Col 2"
 CONTROLCMD win,ListView,@LVINSERTCOLUMN,2,"Col 3"
 CONTROLCMD win,ListView,@LVINSERTCOLUMN,3,"Col 4"
 CONTROLCMD win,ListView,@LVINSERTCOLUMN,4,"Col 5"
 CONTROLCMD win,ListView,@LVINSERTCOLUMN,5,"Col 6"
 CONTROLCMD win,ListView,@LVINSERTCOLUMN,6,"Col 7"
 CONTROLCMD win,ListView,@LVINSERTCOLUMN,7,"Col 8"
 CONTROLCMD win,ListView,@LVSETCOLWIDTH,0,260
 CONTROLCMD win,ListView,@LVSETCOLWIDTH,1,70
 CONTROLCMD win,ListView,@LVSETCOLWIDTH,2,100
 CONTROLCMD win,ListView,@LVSETCOLWIDTH,3,100
 CONTROLCMD win,ListView,@LVSETCOLWIDTH,4,100
 CONTROLCMD win,ListView,@LVSETCOLWIDTH,5,100
 CONTROLCMD win,ListView,@LVSETCOLWIDTH,6,100
 CONTROLCMD win,ListView,@LVSETCOLWIDTH,7,-2

In you window's handler, you need this:

CASE ListView

SELECT @NOTIFYCODE

      case @NMCLICK
      LVpos=*<NMLISTVIEW>@LPARAM.iItem


ENDSELECT

And of course what to do when the up / down buttons are clicked:

CASE MoveUp
    IF @NOTIFYCODE=0
        LVpos = MoveLVitem(win,ListView,LVpos,"+")
    ENDIF

CASE MoveDown
    IF @NOTIFYCODE=0
        LVpos = MoveLVitem(win,ListView,LVpos,"-")
    ENDIF

Finally the sub routine:

SUB MoveLVitem(window WinIn,pointer LV,int Pos,string Direction),int

        UINT hProgress = GETCONTROLHANDLE(WinIn,LV)      'Handle to the List view control.
        UINT HDR=SendMessage(hProgress,LVM_GETHEADER,0,0) 'Handle to the List view header.
        INT Columns=SendMessage(HDR,HDM_GETITEMCOUNT,0,0) 'Number of columns in the List view.

        Int LListCount = 0
        int ColLoop = 0 
        int StorePos = Pos
        Istring ColNameUp[255,10]
        Istring ColNameDown[255,10]

        LListCount = 0
        LListCount=CONTROLCMD(WinIn,LV,@LVGETCOUNT)
        if LListCount = 0 then return 0

        if Pos = 0 and Direction = "+" then return 0
        if Pos = LListCount-1 and Direction = "-" then return Pos

        if Direction = "-" then Pos = LVpos + 1
        if Direction = "+" then Pos = LVpos - 1

        for ColLoop = 0 to Columns - 1
            CONTROLCMD(WinIn,LV,@LVGETTEXT,StorePos,ColLoop,ColNameUp[0,ColLoop])
            CONTROLCMD(WinIn,LV,@LVGETTEXT,Pos,ColLoop,ColNameDown[0,ColLoop])
            CONTROLCMD(WinIn,LV,@LVSETTEXT,Pos,ColLoop,ColNameUp[0,ColLoop])
            CONTROLCMD(WinIn,LV,@LVSETTEXT,StorePos,ColLoop,ColNameDown[0,ColLoop])
        next ColLoop

        if Direction = "-" then StorePos = StorePos + 1
        if Direction = "+" then StorePos = StorePos - 1

        CONTROLCMD WinIn,LV,@LVSETSELECTED,StorePos
        SendMessage(WinIn,@LVM_ENSUREVISIBLE,StorePos,0,LV)

RETURN StorePos
ENDSUB


If you follow these steps it should work for you.

Note:- I've only allowed for 10 columns here, but of course you can up this (in the sub routine).

Istring ColNameUp[255,10] '<--- 10 columns here
Istring ColNameDown[255,10] '<--- 10 columns here

Andy.
:)
Title: Re: Easy way to move list view items up or down - update.
Post by: Andy on May 28, 2019, 12:38:12 AM
Thanks to Bill's suggestion, we can now amend the sub routine so it can cope with how ever many columns the list view has.

sub MoveLVitem(window WinIn,pointer LV,int Pos,string Direction),int

        UINT hProgress = GETCONTROLHANDLE(WinIn,LV)       'Handle to the List view control.
UINT HDR=SendMessage(hProgress,LVM_GETHEADER,0,0) 'Handle to the List view header.
INT Columns=SendMessage(HDR,HDM_GETITEMCOUNT,0,0) 'Number of columns in the List view.

        Int LListCount = 0
        int ColLoop = 0 
        int StorePos = Pos

        string ColNameUp
        string ColNameDown

LListCount = 0
LListCount=CONTROLCMD(WinIn,LV,@LVGETCOUNT)
        if LListCount = 0 then return 0

        if Pos = 0 and Direction = "+" then return 0
        if Pos = LListCount-1 and Direction = "-" then return Pos

        if Direction = "-" then Pos = LVpos + 1
        if Direction = "+" then Pos = LVpos - 1

        for ColLoop = 0 to Columns - 1
    CONTROLCMD(WinIn,LV,@LVGETTEXT,StorePos,ColLoop,ColNameUp)
    CONTROLCMD(WinIn,LV,@LVGETTEXT,Pos,ColLoop,ColNameDown)
    CONTROLCMD(WinIn,LV,@LVSETTEXT,Pos,ColLoop,ColNameUp)
    CONTROLCMD(WinIn,LV,@LVSETTEXT,StorePos,ColLoop,ColNameDown)
        next ColLoop

if Direction = "-" then StorePos = StorePos + 1
if Direction = "+" then StorePos = StorePos - 1

CONTROLCMD WinIn,LV,@LVSETSELECTED,StorePos
SendMessage(WinIn,@LVM_ENSUREVISIBLE,StorePos,0,LV)

return StorePos
endsub

thanks Bill!

Andy.
 :)
Title: Re: Easy way to move list view items up or down.
Post by: billhsln on May 28, 2019, 08:35:30 AM
Great routine. 

This is what is great about our little community.  There are so many inventive people gathering, sharing and helping out when they can.

Keep up the great work, Andy.

Take care,
Bill
Title: Re: Easy way to move list view items up or down.
Post by: Andy on June 01, 2019, 04:44:28 AM
Thanks Bill, sorry for the late reply.

If we wanted to just use local variables completely in the sub routine and keep the selected line highlighted it would look like this:

sub MoveLVitem(window WinIn,pointer LV,int Pos,string Direction),int

        UINT hProgress = GETCONTROLHANDLE(WinIn,LV)      'Handle to the List view control.
        UINT HDR=SendMessage(hProgress,LVM_GETHEADER,0,0) 'Handle to the List view header.
        INT Columns=SendMessage(HDR,HDM_GETITEMCOUNT,0,0) 'Number of columns in the List view.
        if Columns = 0 then return Pos

        string ColNameUp,ColNameDown
        Int LListCount,ColLoop,StorePos = Pos

        LListCount = 0
        LListCount=CONTROLCMD(WinIn,LV,@LVGETCOUNT)
        if LListCount = 0 then return 0

        if Pos = 0 and Direction = "+"
           setfocus WinIn,LV
           return 0
        endif

        if Pos = LListCount-1 and Direction = "-"
           setfocus WinIn,LV
           return Pos
        endif

        if Direction = "-" then Pos = Pos + 1
        if Direction = "+" then Pos = Pos - 1[

        for ColLoop = 0 to Columns - 1
            CONTROLCMD(WinIn,LV,@LVGETTEXT,StorePos,ColLoop,ColNameUp)
            CONTROLCMD(WinIn,LV,@LVGETTEXT,Pos,ColLoop,ColNameDown)
            CONTROLCMD(WinIn,LV,@LVSETTEXT,Pos,ColLoop,ColNameUp)
            CONTROLCMD(WinIn,LV,@LVSETTEXT,StorePos,ColLoop,ColNameDown)
        next ColLoop

        if Direction = "-" then StorePos = StorePos + 1
        if Direction = "+" then StorePos = StorePos - 1

        CONTROLCMD WinIn,LV,@LVSETSELECTED,StorePos
        SendMessage(WinIn,@LVM_ENSUREVISIBLE,StorePos,0,LV)
        setfocus WinIn,LV

return StorePos
endsub

And I agree with you Bill, this is why I love the site. I might ask many questions but there is always someone to help out.

I always like to share code that I think may come in useful to someone (as well as me).