April 18, 2024, 09:47:09 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Easy way to move list view items up or down.

Started by Andy, May 26, 2019, 01:47:43 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Andy

May 26, 2019, 01:47:43 AM Last Edit: May 26, 2019, 04:17:36 AM by Andy
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.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

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.
 :)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

billhsln

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
When all else fails, get a bigger hammer.

Andy

June 01, 2019, 04:44:28 AM #3 Last Edit: June 01, 2019, 04:48:23 AM by Andy
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).
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.