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.
:)
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.
:)
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
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).