List Box Drag items and edit item text example.WIN

BlitzMax Forums/BlitzMax GUI Programming/List Box Drag items and edit item text example.WIN

I have figured out how to drag items from one listbox to another and how to edit listbox items.

As it was a little tricky, I thought others may find this code handy.

I use windows subclasses to get access to the windows messages I needed. With Subclasses you can also modify the behavour of a gadget before it is drawn. e.g A textbox that only allows hex 0-9 A-F.

This code is for Windows only.

This code works with BlitzMax 1.22

Note:
The example shows a directory list and all pics in that directory.
If you click on a selected item (A picture filename), the changed text does not really rename the file on your drive. So you can do no harm testing out the editing feature!

You can only drag a single item at a time. (at this point!)

Strict

' Listbox Item edit Text and Drag 'n Drop example.
' Ziltch 29 August 2006.
' You can use this code if you credit Ziltch!

Extern "win32"
	Function GetSysColor(index)
	Function UpdateWindow(Hwd)
	Function GetLogicalDriveStringsA(nBufferLength, lpBuffer:Byte Ptr)
	Function SHGetSpecialFolderLocation(hwndOwner, nFolder, pIdl:Byte  Ptr)
	Function SHGetPathFromIDList( pidList ,lpBuffer:Byte  Ptr)
	Function GetWindowLong :Int(hWnd ,nIndex)= "GetWindowLongA@8"
	Function GetActiveWindow :Int()= "GetActiveWindow@0"
	Function SetWindowLongPtr :Int(hWnd ,nIndex,lNewLong:Byte Ptr )= "SetWindowLongA@12"
	Function CallWindowProc:Int(lpPrevWndFunc,hWnd,uMsg,wParam,lParam) = "CallWindowProcA@20"
	Function	ImageList_BeginDrag(  himlTrack,     iTrack,   dxHotspot,   dyHotspot)
	Function	ImageList_DragShowNolock(fShow)
	Function	ImageList_DragMove(x,y)
	Function  SetCapture(GadgetHwd)
	Function ChildWindowFromPoint(GadgetHwd, X, Y)
	Function  ReleaseCapture()
	Function  ImageList_EndDrag()
	Function  ImageList_Destroy(DragImageHwd:Byte Ptr)
EndExtern

Const HDN_ITEMCLICK = -302
Const GWL_WNDPROC    = -4
Const WM_USER = $400
Const WM_NOTIFY = 78
Const IDCOMBOBOX       = WM_USER + 102
Const GENERIC_READ     = $80000000
Const GENERIC_WRITE    = $40000000
Const FILE_SHARE_READ  = 1
Const FILE_SHARE_WRITE = 2
Const OPEN_EXISTING    = 3

Const WS_BORDER	       = $800000
Const WS_CAPTION	   = $c00000
Const WS_CHILD	       = $40000000
Const WS_CHILDWINDOW   = $40000000
Const WS_CLIPCHILDREN  = $2000000
Const WS_CLIPSIBLINGS  = $4000000
Const WS_DISABLED	   = $8000000
Const WS_DLGFRAME	   = $400000
Const WS_GROUP	       = $20000
Const WS_HSCROLL	   = $100000
Const WS_ICONIC	       = $20000000
Const WS_MAXIMIZE	   = $1000000
Const WS_MAXIMIZEBOX   = $10000
Const WS_MINIMIZE	   = $20000000
Const WS_MINIMIZEBOX   = $20000
Const WS_OVERLAPPED	   = 0
Const WS_OVERLAPPEDWINDOW = $cf0000
Const WS_POPUP	       = $80000000
Const WS_POPUPWINDOW   = $80880000
Const WS_SIZEBOX	   = $40000
Const WS_SYSMENU	   = $80000
Const WS_TABSTOP	   = $10000
Const WS_THICKFRAME	   = $40000
Const WS_TILED	       = 0
Const WS_TILEDWINDOW   = $cf0000
Const WS_VISIBLE	   = $10000000
Const WS_VSCROLL	   = $200000

Const LBS_DISABLENOSCROLL   = 4096
Const LBS_EXTENDEDSEL       = $800
Const LBS_HASSTRINGS        = 64
Const LBS_MULTICOLUMN       = 512
Const LBS_MULTIPLESEL       = 8
Const LBS_NODATA	        = $2000
Const LBS_NOINTEGRALHEIGHT  = 256
Const LBS_NOREDRAW          = 4
Const LBS_NOSEL             = $4000
Const LBS_NOTIFY            = 1
Const LBS_OWNERDRAWFIXED    = 16
Const LBS_OWNERDRAWVARIABLE = 32
Const LBS_SORT              = 2
Const LBS_STANDARD          = $a00003
Const LBS_USETABSTOPS       = 128
Const LBS_WANTKEYBOARDINPUT = $400

Const LVM_FIRST          = $1000
Const LVM_GETCOLUMNA	 = (LVM_FIRST+25)
Const LVM_GETCOLUMNW	 = (LVM_FIRST+95)
Const LVM_SETCOLUMNA	 = (LVM_FIRST+26)
Const LVM_SETCOLUMNW	 = (LVM_FIRST+96)
Const LVM_INSERTCOLUMNA	 = (LVM_FIRST+27)
Const LVM_INSERTCOLUMNW	 = (LVM_FIRST+97)
Const LVM_DELETECOLUMN	 = (LVM_FIRST+28)
Const LVM_GETCOLUMNWIDTH = (LVM_FIRST+29)
Const LVM_GETITEMA	     = (LVM_FIRST+5)
Const LVM_GETITEMW	     = (LVM_FIRST+75)
Const LVM_SETITEMA	     = (LVM_FIRST+6)
Const LVM_SETITEMW	     = (LVM_FIRST+76)
Const LVM_INSERTITEMA	 = (LVM_FIRST+7)
Const LVM_INSERTITEMW	 = (LVM_FIRST+77)
Const LVM_DELETEITEM	 = (LVM_FIRST+8)
Const LVM_DELETEALLITEMS = (LVM_FIRST+9)
Const LVM_GETCALLBACKMASK= (LVM_FIRST+10)
Const LVM_SETCALLBACKMASK= (LVM_FIRST+11)
Const LVM_SETCOLUMNWIDTH = (LVM_FIRST+30)
Const LVM_GETTEXTCOLOR	 = (LVM_FIRST+35)
'Const LVM_SETTEXTCOLOR	 = (LVM_FIRST+36)
Const LVM_GETTEXTBKCOLOR = (LVM_FIRST+37)
'Const LVM_SETTEXTBKCOLOR = (LVM_FIRST+38)
Const LVM_SORTITEMS      = (LVM_FIRST+48)
Const LVM_ARRANGE	=(LVM_FIRST+22)
Const LVM_EDITLABELA	=(LVM_FIRST+23)
Const LVM_EDITLABELW	=(LVM_FIRST+118)
Const LVM_GETEDITCONTROL	=(LVM_FIRST+24)
Const LVM_CREATEDRAGIMAGE = (LVM_FIRST + 33)
Const LVM_HITTEST = (LVM_FIRST + 18)

Const LVCF_FMT	=1
Const LVCF_WIDTH	=2
Const LVCF_TEXT	=4
Const LVCF_SUBITEM	=8
'	#define LVCF_IMAGE 16
'	#define LVCF_ORDER =32
'	#define LVCFMT_LEFT	=0
Const LVCFMT_RIGHT	=1
Const LVCFMT_CENTER	=2
Const LVCFMT_JUSTIFYMASK	=3

Const LVN_FIRST = -100
Const LVN_LAST=-199
Const LVN_ITEMCHANGING=	LVN_FIRST
Const LVN_ITEMCHANGED	=(LVN_FIRST-1)
Const LVN_INSERTITEM	=(LVN_FIRST-2)
Const LVN_DELETEITEM	=(LVN_FIRST-3)
Const LVN_DELETEALLITEMS	=(LVN_FIRST-4)
Const LVN_BEGINLABELEDIT =	(LVN_FIRST-5)
Const LVN_BEGINLABELEDITW=	(LVN_FIRST-75)
Const LVN_ENDLABELEDIT=	(LVN_FIRST-6)
Const LVN_ENDLABELEDITW	=(LVN_FIRST-76)
Const LVN_COLUMNCLICK	=(LVN_FIRST-8)
Const LVN_BEGINDRAG	=(LVN_FIRST-9)
Const LVN_BEGINRDRAG	=(LVN_FIRST-11)
Const LVN_GETDISPINFOA	=(LVN_FIRST-50)
Const LVN_GETDISPINFOW	=(LVN_FIRST-77)
Const LVN_SETDISPINFOA	=(LVN_FIRST-51)
Const LVN_SETDISPINFOW	=(LVN_FIRST-78)
Const LVN_KEYDOWN	=(LVN_FIRST-55)

Const LVCF_IMAGE= 16
Const LVCF_ORDER =32
Const LVIF_TEXT = 1
Const LVIF_IMAGE =2
Const LVIF_PARAM =4
Const LVIF_STATE =8
Const LVIF_INDENT =$10 
Const LVIF_GROUPID =$100 
Const LVIF_COLUMNS =$200 
Const LVIF_NORECOMPUTE =$800  
Const LVIF_DI_SETITEM =$1000

Const LVS_ICON             =0
Const LVS_REPORT	        =1
Const LVS_SMALLICON	        =2
Const LVS_LIST	            =3
Const LVS_TYPEMASK         =3
Const LVS_SINGLESEL        =4
Const LVS_SHOWSELALWAYS    =8
Const LVS_SORTASCENDING    =16
Const LVS_SORTDESCENDING   =32
Const LVS_SHAREIMAGELISTS	=64
Const LVS_NOLABELWRAP      =128
Const LVS_AUTOARRANGE      =256
Const LVS_EDITLABELS       =512
Const LVS_NOSCROLL         =$2000
Const LVS_TYPESTYLEMASK    =$fc00
Const LVS_ALIGNTOP	        =0
Const LVS_ALIGNLEFT	       =$800
Const LVS_ALIGNMASK	       =$c00
Const LVS_OWNERDRAWFIXED  =$400
Const LVS_NOCOLUMNHEADER  =$4000
Const LVS_NOSORTHEADER	   =$8000
Const LVS_TREEVIEW  =  $4000
Const LVS_EX_GRIDLINES = $1
Const LVS_EX_SUBITEMIMAGES = $2
Const LVS_EX_CHECKBOXES = $4
Const LVS_EX_TRACKSELECT = $8
Const LVS_EX_HEADERDRAGDROP = $10
Const LVS_EX_FULLROWSELECT = $20    'applies to report mode only
Const LVS_EX_ONECLICKACTIVATE = $40
Const LVS_EX_TWOCLICKACTIVATE = $80
Const LVS_EX_FLATSB = $100          'cannot be cleared - Win32 & IE4 only
Const LVS_EX_REGIONAL = $200        'Win32 & IE4 only
Const LVS_EX_INFOTIP = $400

Const LVIS_FOCUSED = $1
Const LVIS_SELECTED = $2
Const LVIS_CUT = $4
Const LVIS_DROPHILITED = $8

Const LVIS_OVERLAYMASK = $F00
Const LVIS_STATEIMAGEMASK = $F000

Const HDN_BEGINTRACK =	-326
Const HDN_DIVIDERDBLCLICK=-325
Const HDN_ENDTRACK = -327
Const HDN_ITEMCHANGED = -321
Const HDN_ITEMCHANGING = -320
Const HDN_ITEMCLICKW = -322

Const HDN_ITEMDBLCLICK = -323
Const HDN_TRACK = -328
Const HDN_BEGINTRACKA = -306
Const HDN_DIVIDERDBLCLICKA = -305
Const HDN_ENDTRACKA = -307
Const HDN_ITEMCHANGEDA = -301
Const HDN_ITEMCHANGINGA = -300
Const HDN_ITEMCLICKA = -302
Const HDN_ITEMDBLCLICKA = -303
Const HDN_TRACKA = -308

Const ALPHABITS=$ff000000

Const GWL_STYLE      = -16
Const GWL_EXSTYLE = -20

Type  LVCOLUMN
	Field mask
	Field fmt
	Field cx
	Field pszText:Byte Ptr
	Field cchTextMax
	Field iSubItem
EndType

Type LVITEM
	Field mask
	Field iItem
	Field iSubItem
	Field iState
	Field stateMask
	Field pszText:Byte Ptr
	Field cchTextMax
	Field iImage
	Field lParam
	Field iIndent
	Field iGroupId
	Field cColumns
	Field puColumns
EndType

Type LV_HITTESTINFO
	Field ptX
	Field ptY
	Field flags
	Field iItem
EndType

Type NMHDR
	Field hwndFrom
	Field idFrom
	Field code
EndType

Type HD_NOTIFY 
'Field hdr:Byte Ptr ' NMHDR
	Field hwndFrom
	Field idFrom
	Field code
	Field iItem
	Field iButton
	Field pitem
EndType

Type tagNMLVDISPINFO
	Field hwndFrom
	Field idFrom
	Field code
	Field mask
	Field iItem
	Field iSubItem
	Field iState
	Field stateMask
	Field pszText:Byte Ptr
	Field cchTextMax
	Field iImage
	Field lParam:Byte Ptr
	Field iIndent
	Field iGroupId
	Field cColumns
	Field puColumns
EndType

Type tagLVKEYDOWN
	Field hwndFrom
	Field idFrom
	Field code
	Field  wVKey:Short
	Field  flags
EndType

Type tagNM_LISTVIEW
	Field hwndFrom
	Field idFrom
	Field code
	Field iItem
	Field iSubItem
	Field uNewState
	Field uOldState
	Field uChanged
	Field ptActionX
	Field ptActionY
	Field  lParam:Byte Ptr
EndType


Const Accessed   = 1
Const Creation     = 2
Const LastWrite   = 3	
Global FileTypes$[]=["","","(Dir)"]
Global PicSize =32 ,NewPicSize=PicSize,PicSizeIndex=2
Global ExplorerWindow:TGadget,ExplorerDriveListCombo:TGadget,ExplorerThumbnailSizeCombo:TGadget,Explorer:TGadget, ExplorerSelectedListBox:TGadget
Global ExplorerBackButton:TGadget,ExplorerHightLightAllButton:TGadget,ExplorerHightLightToggleButton:TGadget,ExplorerSelectButton:TGadget
Global ExplorerSelectedListUpButton:TGadget,ExplorerSelectedListDownButton:TGadget,ExplorerPreviewButton:TGadget,ExplorerSelectedListDeleteButton:TGadget
Global ExplorerClearButton:TGadget
Global ExplorerPanel:TGadget,ExplorerSelectedPanel:TGadget ,ExplorerSelectedOrderButton:TGadget
Global ExplorerCancelButton:TGadget,ExplorerOkButton:TGadget
Global ExplorerPreviewWindow:TGadget,ExplorerPreviewPanel:TGadget

Local FilType ,FileExt$,LoadedImage:TPixmap
Local LoadedImageWidth,LoadedImageWidthStep:Float
Local LoadedImageHeight,LoadedImageHeightStep:Float
Global CurrentDirectory$ =  CurrentDir$() ,DirCount ,PicCnt
Global IconPixmap:TPixmap
Global PreviewPixmap:TPixmap,PreviewMode,PreviewFileName$,LastPreviewFileName$
Global Thumbs:TIconStrip, SelThumbs:TIconStrip ,SelThumbsPixmap:TPixmap
Global SelCount ,SelectedMax = 255 ,TotalPicsSelected
SelThumbsPixmap=CreatePixmap(PicSize*SelectedMax ,PicSize,PF_RGB888)
SelThumbs:TIconStrip =LoadIconStrip(SelThumbsPixmap)
Global NoDriveUpdate

Local tt,col,Gadget:TGadget ,SortOrder=1
Type ListItems
	Field Text:String
	Field OldText:String
	Field Tip:String
	Field SortKey:String
	Field icon
EndType

Const SortText=0
Const SortDate=1
Const SortSize=2
Global SortGadget:TGadget
Global SortColumn

Function PeekString:String(Bank:TBank,Offset=0,MaxLen=1024)
	Local PeekChr
	Local OffsetCount
	Local NewString:String
	Repeat
		PeekChr = PeekByte(Bank,Offset + OffsetCount)
		'	DebugLog OffsetCount +"PeekChr ="+PeekChr + "  "+Chr(PeekChr)
		If PeekChr Then NewString:+Chr(PeekChr)
		OffsetCount:+1
	Until (PeekChr =0)  Or (OffsetCount > MaxLen)
	Return NewString
EndFunction

Function HIWORD(IntIn:Int)
	Return (IntIn Shr 16)
EndFunction 
Function LOWORD(IntIn:Int)
	Return (IntIn & $FFFF)
EndFunction

Function GetFileModTime$(Filename$)

	Local ftime : Int = FileTime(Filename)
	Local pointer : Int Ptr = Int Ptr(localtime_(Varptr(ftime)))
	Local wSec=pointer[0]
	Local wMin=pointer[1]
	Local wHour=pointer[2]
	Local wDay=pointer[3]
	Local wMonth=pointer[4]+1
	Local wYear=(pointer[5]+1900)
	Local res$=( wYear+ "/" +Right("0"+wMonth,2)+ "/" +Right("0"+wDay,2)+ " " +wHour+ ":" +wMin+ ":" +wSec)'  + " :" +wMilliseconds)
	'DebugLog "Date is "+res$
	Return  res$
End Function

Function GetFileCreatedTime$(Filename$)
	Local mode,size,mtime,ctime
	FixPath Filename
	If stat_( Filename,mode,size,mtime,ctime ) Then 
		Return
	EndIf
	Local pointer : Int Ptr = Int Ptr(localtime_(Varptr(ctime)))
	Local wSec=pointer[0]
	Local wMin=pointer[1]
	Local wHour=pointer[2]
	Local wDay=pointer[3]
	Local wMonth=pointer[4]+1
	Local wYear=(pointer[5]+1900)	
	Local res$=( wYear+ "/"+Right("0"+wMonth,2)+ "/" +Right("0"+wDay,2)+  " " +wHour+ ":" +wMin+ ":" +wSec)'  + " :" +wMilliseconds)
	'DebugLog "Date is "+res$
	Return  res$
End Function

Function AddListBoxColumn(ListBox:TGadget,Column,HeadingText$,width,Style=0)
	Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
	Local col:LVCOLUMN = New LVCOLUMN	
	Col.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_FMT
	Col.fmt = Style
	Col.cx = width
	col.pszText = HeadingText$.ToCString()
	Local ListBoxstyle = GetWindowLongA(ListboxHwnd , GWL_STYLE)
	If (ListBoxstyle &  LBS_MULTICOLUMN ) <> ( LBS_MULTICOLUMN ) Then
		ListBoxstyle  = ListBoxstyle  | LBS_MULTICOLUMN
		SetWindowLongA(ListboxHwnd , GWL_STYLE,  ListBoxstyle   ) 'change the style so that we have headings
	EndIf
	SendMessageA(ListboxHwnd,LVM_INSERTCOLUMNA,Column,Int(Byte Ptr Col))
End Function

Function AddListBoxItem(ListBox:TGadget,Text$,Row,Column)
	Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
	Local ColItem:LVITEM  = New LVITEM
	ColItem.mask = LVIF_TEXT
	ColItem.iSubItem = Column
	ColItem.iItem = Row
	ColItem.pszText = Text$.ToCString()
	ColItem.cchTextMax =  Text$.Length + 1
	SendMessageA( ListboxHwnd,LVM_SETITEMA,0,Int(Byte Ptr ColItem))
	ColItem=Null
End Function


Function GetListBoxItem:String(ListBox:TGadget,Row,Column)
	Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
	If ListboxHwnd Then
		Local Ans$
		Local TextBank:TBank=CreateBank(1024)
		'Local Text:Byte[256]
		Local ColItem:LVITEM  = New LVITEM
		ColItem.mask = LVIF_TEXT
		ColItem.iSubItem = Column
		ColItem.iItem = Row
		ColItem.pszText = BankBuf(TextBank)
		ColItem.cchTextMax =  255 
		SendMessageA( ListboxHwnd,LVM_GETITEMA,0,Int(Byte Ptr ColItem))
		If ColItem.pszText <> Null
			Ans$=Ans$.fromcstring(ColItem.pszText)
			ColItem=Null
		EndIf
		Return Trim(Ans$)
	EndIf
End Function

Function SetListBoxItem(ListBox:TGadget,Text:String,Row,Column=0)
	Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
	If Column=0 Then
		ListBox.items[Row].Text = text
		DebugLog  "ListBox:TGadget text "+text
	EndIf
	If ListboxHwnd Then
		Local ColItem:LVITEM  = New LVITEM
		ColItem.mask = LVIF_TEXT
		ColItem.iSubItem = Column
		ColItem.iItem = Row
		ColItem.pszText = Text.Tocstring()
		ColItem.cchTextMax =  Len(Text) 
		Return SendMessageA( ListboxHwnd,LVM_SETITEMA,0,Int(Byte Ptr ColItem))
	EndIf
End Function

Function ListBoxHeading(ListBox:TGadget,Column,Text$,width=0)
	Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
	Local col:LVCOLUMN = New LVCOLUMN	
	If width = 0 Then
		Col.mask = LVCF_TEXT| LVCF_FMT 
	Else
		Col.mask = LVCF_TEXT| LVCF_FMT | LVCF_WIDTH
		col.cx   = width
	EndIf
	col.pszText = Text$.ToCString()
	Local ListBoxstyle = GetWindowLongA(ListboxHwnd , GWL_STYLE)
	If (ListBoxstyle &  LVS_NOCOLUMNHEADER ) Then
		ListBoxstyle  = ListBoxstyle  ~LVS_NOCOLUMNHEADER 
		If ListBoxstyle & LVS_EDITLABELS=0 Then ListBoxstyle  = ListBoxstyle  | LVS_EDITLABELS
		SetWindowLongA(ListboxHwnd , GWL_STYLE,  ListBoxstyle )  'change the style so that we have headings
	EndIf
	SendMessageA(ListboxHwnd,LVM_SETCOLUMNA,Column,Int(Byte Ptr Col))
End Function

Function ListBoxColumnWidth(ListBox:TGadget,Column,width)
	Local ListboxHwnd=QueryGadget(ListBox,QUERY_HWND)
	Local col:LVCOLUMN = New LVCOLUMN	
	Col.mask = LVCF_WIDTH
	col.cx   = width
	SendMessageA(ListboxHwnd,LVM_SETCOLUMNA,Column,Int(Byte Ptr Col))
End Function

Function ListBoxGadgetMultiSelect(ListBox:TGadget)
	Local ListboxHwnd = QueryGadget(ListBox,QUERY_HWND)
	Local ListBoxstyle = GetWindowLongA(ListboxHwnd , GWL_STYLE)
	If  (ListBoxstyle & LVS_SINGLESEL) = LVS_SINGLESEL Then
		Return SetWindowLongA(ListboxHwnd , GWL_STYLE,  ListBoxstyle  ~ LVS_SINGLESEL )  'change the style 		
	EndIf
End Function

Function RGB(Rcolor,Gcolor,Bcolor)
	Return((Rcolor Shl 16) | (Gcolor Shl 8) | Bcolor)
EndFunction

Function Red(RGBcolor)
	Return  ((RGBcolor Shr 16) & 255)
EndFunction

Function Green(RGBcolor)
	Return (RGBcolor Shr 8) & 255
EndFunction

Function Alpha(RGBcolor)
	Return (RGBcolor Shr 24) & 255
EndFunction

Function Blue(RGBcolor)
	Return RGBcolor & 255
EndFunction

Function RGB2BGR(RGBcolor)
	Local Bcolor = Red(RGBcolor)
	Local Gcolor = Green(RGBcolor)
	Local Rcolor =  Blue(RGBcolor)
	Return ((Rcolor Shl 16) | (Gcolor Shl 8) | Bcolor)
EndFunction

Const WM_SETTEXT  = 12
Const WM_GETTEXT = 13
Const WM_GETTEXTLENGTH = 14
Function ComboBoxText:String(Gadget:TGadget)
	Local StrLen= SendMessageA( QueryGadget(Gadget,QUERY_HWND),WM_GETTEXTLENGTH,0,0 )+1
	Local char_buff:TBank=CreateBank(StrLen)
	
	SendMessageA( QueryGadget(Gadget,QUERY_HWND),WM_GETTEXT,StrLen,Int(BankBuf(Char_buff )));
	
	Local Res$
	For Local index = 0 To StrLen-2
		Res$:+Chr(PeekByte(Char_buff,index))
	Next
	'DebugLog "cb text is "+Res
	Return Res$
EndFunction

Function SetComboBoxText:String(Gadget:TGadget,Text:String)
	Local StrLen= Text.Length
	'DebugLog Text + " Len = "+Text.Length
	Return SendMessageA( QueryGadget(Gadget,QUERY_HWND),WM_SETTEXT,Text.Length,Int(Text.ToCstring()));
EndFunction


Function FormatFileSize:String(Size)
	Local SizeString:String = String(size)
	Local SizeLen = Len(SizeString)
	Local FormatedSize:String
	Local AfterDecimalPoint:String
	Local Scale:String
	' DebugStop
	If SizeLen  > 6 Then
		SizeString = String(size/1048576)'1024*1024
		SizeLen = Len(SizeString)
		AfterDecimalPoint=String(Abs(size/1048576)-(size/1048576.0))[2..5]
		Scale = " Mb"
	ElseIf SizeLen  > 3 Then
		SizeString = String(size/1024)
		SizeLen = Len(SizeString)
		AfterDecimalPoint=String(Abs(Int(size/1024.0))-(size/1024.0))[2..5]
		Scale = " Kb"
	Else
	
		Scale = " b"
	EndIf
	If SizeLen  > 3 Then
		For Local count = Sizelen -1 To 0 Step -1
			FormatedSize:+ SizeString[count]
			If count/3.0 = Int(count/3.0) Then FormatedSize:+","
		Next
	Else
		FormatedSize = SizeString
	EndIf
	FormatedSize:+AfterDecimalPoint
	FormatedSize:+Scale
	'DebugLog "FormatedSize = "+FormatedSize
	Return FormatedSize
	
EndFunction

Function SetComboGadgetDriveList(Gadget:TGadget)
	Local DriveStringBank:TBank = CreateBank(2048)
	Local DriveStringLen = GetLogicalDriveStringsA(2048,BankBuf(DriveStringBank))
	Local DriveString:String 
	Local PeekChr
	Local OffsetCount
	
	Repeat
		PeekChr = PeekByte(DriveStringBank,OffsetCount)
		'	DebugLog OffsetCount +"PeekChr ="+PeekChr + "  "+Chr(PeekChr)
		If PeekChr Then 
			DriveString:+Chr(PeekChr)
		ElseIf PeekChr =0
			AddGadgetItem(Gadget,Left(DriveString,2))
			DriveString=""
		EndIf
		OffsetCount:+1
	Until  (OffsetCount > DriveStringLen )
	'DebugLog "DriveString "+DriveString
EndFunction


Function CreateExplorerWindow()
	ExplorerWindow:TGadget=CreateWindow("Pic Explorer Window",100,100,700,470,Null,WINDOW_TITLEBAR|WINDOW_CLIENTCOORDS|WINDOW_STATUS)
	
	CreateLabel("Drives",15,9,30,20,ExplorerWindow)
	ExplorerDriveListCombo:TGadget           = CreateComboBox(50,5,50,20,ExplorerWindow,COMBOBOX_EDITABLE)
	CreateLabel("Thumbnail Size",105,9,80,20,ExplorerWindow)
	ExplorerThumbnailSizeCombo:TGadget  = CreateComboBox(185,5,50,22,ExplorerWindow,COMBOBOX_EDITABLE)
	ExplorerPanel                     		   = CreatePanel(5,35,545,430,ExplorerWindow,PANEL_ACTIVE|PANEL_BORDER)
	Explorer                              		   = CreateListBox(2,2,537,394,ExplorerPanel)
	ExplorerBackButton:TGadget		   = CreateButton("Back",5,400,45,22,ExplorerPanel)
	ExplorerHightLightAllButton:TGadget      = CreateButton("All",55,400,45,22,ExplorerPanel)
	ExplorerHightLightToggleButton:TGadget= CreateButton("Toggle",105,400,45,22,ExplorerPanel)
	ExplorerPreviewButton:TGadget		   = CreateButton("Preview",155,400,45,22,ExplorerPanel)		
	ExplorerSelectButton:TGadget		   = CreateButton("Select",205,400,45,22,ExplorerPanel)	
	ExplorerSelectedPanel           		   = CreatePanel(555,35,140,398,ExplorerWindow,PANEL_ACTIVE|PANEL_BORDER)
	ExplorerSelectedOrderButton     		   = CreateButton("Selected Pics",2,4,132,16,ExplorerSelectedPanel,LABEL_CENTER | LABEL_FRAME)
	ExplorerSelectedListBox         		   = CreateListBox(2,24,132,342,ExplorerSelectedPanel)
	ExplorerSelectedListUpButton   		   = CreateButton("Up",2,370,40,22,ExplorerSelectedPanel)
	ExplorerSelectedListDownButton  	   = CreateButton("Down",46,370,40,22,ExplorerSelectedPanel)
	ExplorerSelectedListDeleteButton 	   = CreateButton("Delete",90,370,45,22,ExplorerSelectedPanel)
	ExplorerClearButton           		   = CreateButton("Clear",555,440,42,22,ExplorerWindow )
	ExplorerCancelButton           		   = CreateButton("Cancel",603,440,40,22,ExplorerWindow )
	ExplorerOkButton               		   = CreateButton("Ok",650,440,45,22,ExplorerWindow )
	
	
	ListBoxHeading(Explorer,0,"Name")
	AddListBoxColumn(Explorer,1,"Type",40,0)
	AddListBoxColumn(Explorer,2,"Modified",110,0)
	AddListBoxColumn(Explorer,3,"Created",110,0)
	AddListBoxColumn(Explorer,4,"Size",89,0)
	ListBoxGadgetMultiSelect(Explorer)
	ListBoxGadgetMultiSelect(ExplorerSelectedListBox)
	RedrawGadget(ExplorerSelectedListBox)
	
	AddGadgetItem(ExplorerThumbnailSizeCombo,"8")
	AddGadgetItem(ExplorerThumbnailSizeCombo,"16")
	AddGadgetItem(ExplorerThumbnailSizeCombo,"32")
	AddGadgetItem(ExplorerThumbnailSizeCombo,"64")
	AddGadgetItem(ExplorerThumbnailSizeCombo,"128")	
	SetGadgetText(ExplorerThumbnailSizeCombo,PicSize)
	
	SetComboGadgetDriveList(ExplorerDriveListCombo)
	
	ExplorerPreviewWindow:TGadget = CreateWindow("Preview",255,135,400,400,ExplorerWindow,WINDOW_TITLEBAR | WINDOW_HIDDEN|WINDOW_RESIZABLE)'|WINDOW_STATUS
	ExplorerPreviewPanel:TGadget  = CreatePanel(5,5,385,365,ExplorerPreviewWindow,PANEL_BORDER)
	SetGadgetLayout( ExplorerPreviewPanel,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED)
EndFunction

Function UpdateIconStrip(IconIndex,SelIndex)
	'DebugLog Thumbs.Pixmap.width+ " Thumbs.Pixmap.width-PicSize "+(Thumbs.Pixmap.width-PicSize)
	'DebugLog SelIndex +" SelIndex*PicSize "+(SelIndex*PicSize)
	'DebugLog "PicSize ="+PicSize
	If Thumbs.Pixmap.width-PicSize < SelIndex*PicSize Then
		DebugLog "ERROR: UpdateIconStrip  is out of range"
		'DebugStop
	Else
		Local SelIcon:TPixmap = PixmapWindow:TPixmap( Thumbs.Pixmap, SelIndex*PicSize,0,PicSize,PicSize)
		If SelIcon Then
			SelThumbsPixmap.Paste(SelIcon,IconIndex*PicSize,0 )	
			SelThumbs = LoadIconStrip(SelThumbsPixmap)
			SetGadgetIconStrip(ExplorerSelectedListBox,SelThumbs)
		EndIf
	EndIf
EndFunction


Const CSIDL_FONTS = $14
Function GetSpecialFolder:String(FolderId) 
	Local  IdBank:TBank = CreateBank(8) 
	Local  PathBank:TBank = CreateBank(1024) 
	If SHGetSpecialFolderLocation(0,FolderId,BankBuf(IdBank)) = 0		
		SHGetPathFromIDList( PeekInt( IdBank,0), BankBuf(PathBank))
		'DebugLog "font dir = "+PeekString(PathBank)
		Return (PeekString(PathBank) + "")
	EndIf
End Function

Global DirectoryIcon:TPixmap[5]

Function MakeDirectoryIcons()
	Local IconSize 
	Local TempCanvas:TGadget =CreateCanvas:TGadget(2048,2048,130,130,ExplorerWindow)
	Local DirFont:TImageFont ' CamCanvas '
	Local FontX,FontY
	SetGraphics CanvasGraphics(TempCanvas)
	Local col = RGB2BGR(GetSysColor(5))
	IconSize =4
	For Local c = 1  To 5
		IconSize = IconSize*2
		SetViewport 0,0,GraphicsWidth(),GraphicsHeight()
		SetBlend SOLIDBLEND
		SetHandle 0,0
		SetRotation 0
		SetScale 1,1
		SetColor Red(col ),Green(col ),Blue(col )
		DrawRect(0,0,IconSize+1,IconSize+1)
		SetBlend ALPHABLEND
		DirFont:TImageFont = LoadImageFont:TImageFont(GetSpecialFolder(CSIDL_FONTS)+"ariblk.ttf",IconSize/2-1,BOLDFONT | SMOOTHFONT )
		SetImageFont( DirFont)
		FontX = IconSize/2-TextWidth("DIR")/2
		FontY = IconSize/2-TextHeight("DIR")/2-1
		SetColor 210,10,210			
		'DrawOval(0,0,IconSize,IconSize)
		SetColor 10,10,10			
		DrawText("DIR",FontX ,FontY+1)
		SetColor 130,130,160	
		DrawText("DIR",FontX ,FontY)
		DirectoryIcon[c-1] = GrabPixmap(0,0,IconSize,IconSize)
		'SavePixmapPNG(DirectoryIcon[c-1],("icon"+(c-1)+"-"+iconSize+".png"))
		DirFont:TImageFont = Null
		Cls
	Next
EndFunction

Function CreateIconDirectory$(PicDirectory$)
	Local LastDir$=CurrentDir()
	ChangeDir(PicDirectory$)
	Local files$[]=LoadDir(PicDirectory$,False)
	Local DirSize=1,TotalPics,FilType,FileExt$,file$
	DirCount=0
	PicCnt = 0
	'Count Number of Directoris and pictures to display
	For file$=EachIn files
		FilType = FileType( file$)
		FileExt$=Lower(ExtractExt(file$))
		If (FileExt="jpg" Or FileExt="bmp" Or FileExt="png" ) Then
			DirSize:+1
		ElseIf FilType =2 And  file$ <> "." 'directory
			DirSize:+1
			DirCount:+1
		EndIf
	Next
	If (Dirsize*PicSize*PicSize*4)>16777216 Then
		Confirm("Thumbnail size is too large for "+DirSize+" files.~n Please decrease the thumbnail size and try again. ")
		ChangeDir(LastDir$)				
		Return LastDir$
	EndIf
	NoDriveUpdate = True
	SetGadgetText(ExplorerDriveListCombo,Upper(PicDirectory[0..2]))
	ClearGadgetItems(Explorer)
	
	' Make Thumbnail icons for pictures and directory icons if needed
	If DirSize => 1 Or DirCount => 1 Then
	
		IconPixmap:TPixmap=CreatePixmap(Dirsize*PicSize,PicSize,PF_RGB888)
		DebugLog "PicSizeIndex "+PicSizeIndex
		If DirectoryIcon[PicSizeIndex]=Null Then
		
			MakeDirectoryIcons()
		EndIf
		IconPixmap.Paste(DirectoryIcon[PicSizeIndex],0,0 )
		Local LoadedImage:TPixmap ,StartTime ,TimeTaken
		StartTime= MilliSecs()
		For  file$=EachIn files
			file$=RealPath$(file$)
			FilType = FileType(file$)
			FileExt$=Lower(ExtractExt(file$))
			If file$ <> "." Then
				If  (FileExt="jpg" Or FileExt="bmp" Or FileExt="png" )Then
					LoadedImage=LoadPixmap(file$)
					PicCnt:+1
					If LoadedImage Then 
						Local LoadedImageWidth = PixmapWidth(LoadedImage)
						Local LoadedImageWidthStep#= LoadedImageWidth/Float(PicSize)
						Local LoadedImageHeight = PixmapHeight(LoadedImage)
						Local LoadedImageHeightStep#= LoadedImageHeight/Float(PicSize)
						'LoadedImage = ResizePixmap(LoadedImage ,PicSize,PicSize) <- slow
						'Pixmap.Paste( LoadedImage ,PicCnt*PicSize,0 ) <- slow
						For Local PosX = 0 To PicSize-1 ' Copy pixels from each picture into smaller strip of pictures
							For Local PosY = 0 To PicSize-1
								WritePixel(IconPixmap,Posx+(PicCnt*PicSize),PosY,ReadPixel(LoadedImage,PosX*LoadedImageWidthStep,PosY*LoadedImageHeightStep))
							Next
						Next
					EndIf
					SetStatusText( ExplorerWindow,"File "+PicCnt+"/"+DirSize)
				EndIf
			EndIf
		Next
		
		TimeTaken = MilliSecs() - StartTime
		DirSize:-1
		Thumbs:TIconStrip =  LoadIconStrip(IconPixmap)
		SetGadgetIconStrip(Explorer,Thumbs)
		
		PicCnt=1
		DirCount=0
		Local FileCnt = 0
		For  file$=EachIn files
			FilType = FileType( file$)
			FileExt$=Lower(ExtractExt(file$))
			If file$ <> "." Then
				If  (FileExt="jpg"  Or FileExt="bmp" Or FileExt="png" ) Then
					AddGadgetItem (Explorer, file$+"    " ,0,PicCnt,RealPath$(file$))  
					AddListBoxItem(Explorer,FileTypes$[FilType],DirCount+PicCnt-1,1)
					AddListBoxItem(Explorer,GetFileModTime( file$),DirCount+PicCnt-1,2)
					AddListBoxItem(Explorer,GetFileCreatedTime( file$),DirCount+PicCnt-1,3)
					AddListBoxItem(Explorer,FormatFileSize(FileSize( file$)),DirCount+PicCnt-1,4)
					PicCnt:+1	
				ElseIf FilType =2 'directory
					InsertGadgetItem(Explorer,DirCount,file$,0,0,RealPath$(file$))
					AddListBoxItem(Explorer,FileTypes$[FilType],DirCount,1)
					DirCount:+1
				EndIf
			EndIf
			SetStatusText( ExplorerWindow,"File "+PicCnt+"/"+DirSize)	
		Next
		ListBoxColumnWidth(Explorer,0,180)
		SetStatusText( ExplorerWindow,(PicCnt-1)+" Picture Files  TimeTaken "+Int(TimeTaken/1000 )+String(Abs(Int(TimeTaken/1000.0))-(TimeTaken/1000.0))[2..5]+ " seconds." )
		DirCount:-1
	EndIf
	Return PicDirectory$
EndFunction

Function PreviewFile(PreviewFileName$)	
	If PreviewFileName$ Then
		PreviewPixmap = LoadPixmap(CurrentDirectory+"/"+PreviewFileName$)
		PreviewMode = PANELPIXMAP_FIT
		If PreviewPixmap Then 				 
			ShowGadget ExplorerPreviewWindow
			LastPreviewFileName$=PreviewFileName$
			SetPanelColor( ExplorerPreviewPanel,0,0,0 )
			SetPanelPixmap(ExplorerPreviewPanel,PreviewPixmap,PreviewMode)
			SetGadgetText( ExplorerPreviewWindow,CurrentDirectory+"/"+PreviewFileName)
			'SetStatusText( ExplorerPreviewWindow,"Size "+PixmapWidth(PreviewPixmap)+" x "+Pixmapheight(PreviewPixmap))
		EndIf
	EndIf
EndFunction

Function DragDrop:Int(hWnd:Int,Msg:Int,wParam:Int,lParam)
	Local MX = LOWORD(lParam)+GadgetX(ExplorerWindow)-PicSize/2
	Local MY = HIWORD(lParam)+GadgetY(ExplorerWindow)+PicSize/2
	ImageList_DragMove(MX, MY)
	ImageList_DragShowNolock(False)
	Local ExplorerSelectedListBoxHwd=QueryGadget(ExplorerSelectedListBox,QUERY_HWND)
	Local ExplorerSelectedPanelHwd=QueryGadget(ExplorerSelectedPanel,QUERY_HWND)
	
	If TargetGadget  Then
		TargItem:LVITEM = New LVITEM
		TargItem.mask = LVIF_STATE
		TargItem.iItem =TargetItem
		TargItem.istate = 0
		TargItem.stateMask = LVIS_DROPHILITED
		SendMessageA(ExplorerSelectedListBoxHwd, LVM_SETITEMA, 0,Int(Varptr((TargItem.mask))))
		RedrawGadget(ExplorerSelectedListBox)		
	EndIf
	MX=MX-GadgetX(ExplorerSelectedPanel)-GadgetX(ExplorerWindow)+PicSize/2
	MY=MY-GadgetY( ExplorerSelectedPanel)-GadgetY(ExplorerWindow)+PicSize/2
	Local TargetGadgetID = ChildWindowFromPoint(ExplorerSelectedPanelHwd, MX, MY)
	
	If TargetGadgetID = ExplorerSelectedListBoxHwd
		TargetGadget = ExplorerSelectedListBox
	Else
		TargetGadget = Null
		ImageList_DragShowNolock(True)
		Return
	EndIf
	
	Local HitTestInfo:LV_HITTESTINFO = New LV_HITTESTINFO
	HitTestInfo.ptX = MX
	HitTestInfo.ptY = MY -GadgetY(ExplorerSelectedListBox)
	TargetItem = SendMessageA(ExplorerSelectedListBoxHwd, LVM_HITTEST, 0, Int(Varptr((hittestinfo.ptX))))
	
	If TargetItem = -1 Then 
		TargetItem=SelCount
	EndIf
	TargItem:LVITEM = New LVITEM
	TargItem.mask = LVIF_STATE
	TargItem.iItem =TargetItem
	TargItem.istate =LVIS_DROPHILITED
	TargItem.stateMask = LVIS_DROPHILITED
	SendMessageA(ExplorerSelectedListBoxHwd, LVM_SETITEMA, 0,Int(Varptr((TargItem.mask))))
	ImageList_DragShowNolock(True)
	
	
EndFunction

Function NewWinProc:Int(hWnd:Int,Msg:Int,wParam:Int,lParam) "win32"
	Local Tstr$
	
	LVEditHandle =SetWindowLongA( QueryGadget(Explorer,QUERY_HWND), LVM_GETEDITCONTROL,0)
	If LVEditHandle
		DebugLog "LVEditHandle  "+LVEditHandle
	EndIf
	If Msg = WM_NOTIFY Then
		Local NotifyMess:HD_NOTIFY = New HD_NOTIFY
		Local Tstr$
		MemCopy( Byte Ptr(NotifyMess),Byte Ptr( lParam), SizeOf(HD_NOTIFY) )
		
		' Listbox text item editing
		'  The listboxes labeledit messages are sent to its parent 
		' Look for message to tell us editing has finished.
		If NotifyMess.code = LVN_ENDLABELEDIT Then
			Local DispInfo:tagNMLVDISPINFO = New tagNMLVDISPINFO
			MemCopy( Byte Ptr(DispInfo),Byte Ptr( lParam), SizeOf(tagNMLVDISPINFO) )
			
			Local NewText$ = Trim(Tstr$.fromcstring(DispInfo.pszText))
			If NewText > "" Then 
				SetListBoxItem(Explorer,NewText,DispInfo.iItem)
			EndIf
		EndIf
		
		' Draging of a listbox item has begun
		If (NotifyMess.code = LVN_BEGINDRAG) Or (NotifyMess.code = LVN_BEGINRDRAG) Then
			Local NotifyInfo:tagNM_LISTVIEW = New tagNM_LISTVIEW
			MemCopy( Byte Ptr(NotifyInfo),Byte Ptr( lParam), SizeOf(tagNM_LISTVIEW) )
			DebugLog "LVN_BEGINDRAG from "+NotifyInfo. idFrom +" iItem "+NotifyInfo.iItem + " x,y "+NotifyInfo.ptActionX+","+NotifyInfo.ptActionY
			Local DragImage1 = (SendMessageA(QueryGadget(Explorer,QUERY_HWND), LVM_CREATEDRAGIMAGE, NotifyInfo.iItem, Int(Varptr(NotifyInfo.ptActionX))))
			If DragImage1 Then
				DragImage = Byte Ptr(DragImage1)
				
				If ImageList_BeginDrag(Int(DragImage) , 0,0, 0)
					ImageList_DragShowNolock(True)
					' SetCapture to parent of listbox you wish to drop item in
					SetCapture(QueryGadget(ExplorerPanel,QUERY_HWND))
					DragingImageNow = True
					SourceItem = NotifyInfo.iItem
				EndIf
			Else 
				DragingImageNow = False
			EndIf
		EndIf
		
	' Draw Litsbox item as it is being draged
	ElseIf Msg = WM_MOUSEMOVE And DragingImageNow Then
		DragDrop(hWnd,Msg,wParam,lParam)
		
	' Drop the Draged item
	ElseIf Msg = WM_LBUTTONUP And DragingImageNow Then
		ImageList_DragShowNolock(False)
		If TargetGadget Then
			UpdateIconStrip(SelCount,SourceItem-DirCount)
			InsertGadgetItem(ExplorerSelectedListBox,TargetItem,Explorer.items[SourceItem].text ,0,SelCount,CurrentDirectory$+"/"+Explorer.items[SourceItem].text) 
			SelCount:+1
			SetGadgetText(ExplorerSelectedOrderButton,"Selected Pics "+SelCount)
		EndIf
		
		ReleaseCapture()
		ImageList_EndDrag()
		ImageList_Destroy(DragImage)
		DragingImageNow = False
		TargItem:LVITEM = New LVITEM
		TargItem.mask = LVIF_STATE
		TargItem.iItem =TargetItem+1
		TargItem.istate = 0
		TargItem.stateMask = LVIS_DROPHILITED
		SendMessageA(QueryGadget(ExplorerSelectedListBox,QUERY_HWND), LVM_SETITEMA, 0,Int(Varptr((TargItem.mask))))
	EndIf
	
	If oldWinProc <>0 Then Return CallWindowProc(oldWinProc, hWnd, Msg, wParam,Int(Byte Ptr( lParam)))
EndFunction

Function NewListProc:Int(hWnd:Int,Msg:Int,wParam:Int,lParam) "win32"

	If Msg = WM_NOTIFY Then
		Local NotifyMess:HD_NOTIFY = New HD_NOTIFY
		Local Tstr$
		
		MemCopy( Byte Ptr(NotifyMess),Byte Ptr( lParam), SizeOf(HD_NOTIFY) )
		'DebugLog "hwndFrom  "+NotifyMess.hwndFrom
		'DebugLog "idFrom  "+NotifyMess.idFrom
		'DebugLog "code "+NotifyMess.code
		'DebugLog "iItem "+NotifyMess.iitem
		'DebugLog "iButton  "+NotifyMess.iButton
		'DebugLog "pitem  "+NotifyMess.pitem
		
		If NotifyMess.code = HDN_ITEMCLICKW Then
			SetStatusText(ExplorerWindow, "Column heading "+NotifyMess.iitem + " has been clicked.")
		EndIf
	EndIf
	
	If oldListProc <>0 Then Return CallWindowProc(oldListProc, hWnd, Msg, wParam,Int(Byte Ptr( lParam)))
EndFunction

'
'------------------------------------------------------------------------
'


CreateExplorerWindow()

' Use subclassing To look For labeledit And drag/drop windows messages

Local ExplorerHwnd = QueryGadget(Explorer,QUERY_HWND)
Global oldListProc,oldWinProc,LVEditHandle ,DragingImageNow,DragImage:Byte Ptr
Global TargetGadget:TGadget, TargetItem ,TargItem:LVITEM ,SourceItem

oldWinProc =SetWindowLongA(QueryGadget(ExplorerPanel,QUERY_HWND), GWL_WNDPROC,Int(Byte Ptr(NewWinProc)))
oldListProc =SetWindowLongA(QueryGadget(Explorer,QUERY_HWND), GWL_WNDPROC,Int(Byte Ptr(NewListProc)))
SetGadgetIconStrip(ExplorerSelectedListBox,SelThumbs)
CreateIconDirectory(CurrentDirectory)
SetGadgetText(ExplorerWindow, CurrentDirectory)

'DebugStop
'Main Loop

Repeat
	WaitEvent()
	
	Gadget= TGadget(EventSource())
	
	Select EventID()
	
		Case EVENT_GADGETACTION	
		
			Select Gadget 
			
				Case Explorer
				
					Local index[]= SelectedGadgetItems(Explorer)
					For Local SelIndex =EachIn Index
					
						If Selindex > -1
						
							Local SelFileType$ = GetListBoxItem(Explorer,Selindex,1)
							If SelFileType$ Then ' it is a dir=FileTypes$[2]
								Local NewDir$=GadgetItemText(Explorer,Selindex)
								
								If NewDir = ".." Then
									Local SlashPos =CurrentDirectory$.FindLast( "/" )
									CurrentDirectory$=CurrentDirectory$[..(SlashPos)]
								Else
									CurrentDirectory$=CurrentDirectory$+"/"+NewDir
								EndIf
								CurrentDirectory = CreateIconDirectory(CurrentDirectory)
								SetGadgetText(ExplorerWindow,CurrentDirectory)
								SetGadgetText(ExplorerDriveListCombo,CurrentDirectory[..Instr(CurrentDirectory,":")])
								NoDriveUpdate = True
								Exit
							EndIf						
						EndIf						
					Next
					
				Case ExplorerDriveListCombo
					If NoDriveUpdate Then
						NoDriveUpdate = False
					Else
						CurrentDirectory$=ComboBoxText(ExplorerDriveListCombo)
						CreateIconDirectory(CurrentDirectory)
						SetGadgetText(ExplorerWindow,CurrentDirectory)
						ActivateGadget(Explorer)
					EndIf
					
				Case ExplorerThumbnailSizeCombo				
					NewPicSize = Int(ComboBoxText(ExplorerThumbnailSizeCombo))
					Local PicSizeIndexRaw = SelectedGadgetItem(ExplorerThumbnailSizeCombo)
					If PicSizeIndexRaw >-1 Then
						PicSizeIndex = PicSizeIndexRaw
					EndIf
					
					If NewPicSize => 8 Then 
						If NewPicSize <> PicSize Then
							Local Ok = 1
							If  SelCount > 0 Then OK= Confirm("This will clear your current selection.",True)
							If OK Then
								PicSize = NewPicSize 
								CreateIconDirectory(CurrentDirectory)
								ClearGadgetItems(ExplorerSelectedListBox)
								SelCount = 0
								SetGadgetText(ExplorerSelectedOrderButton,"Selected Pics")							
								DebugLog "thumb size = "+PicSize*PicSize*SelectedMax*4
								SelThumbsPixmap=CreatePixmap(PicSize*SelectedMax,PicSize,PF_RGB888)
								SelThumbs:TIconStrip =LoadIconStrip(SelThumbsPixmap)' New TIconStrip 
							Else
								NewPicSize = PicSize
								SetGadgetText(ExplorerThumbnailSizeCombo,PicSize)
							EndIf
						EndIf	
					EndIf
					ActivateGadget(Explorer)
					
				Case ExplorerSelectButton					
				
					Local index[]= SelectedGadgetItems(Explorer)
					
					For Local SelIndex =EachIn Index
						If Selindex > -1 Then
							If  Selindex < SelectedMax Then
								Local SelFile$=GadgetItemText(Explorer,Selindex)
								UpdateIconStrip(SelCount,SelIndex-DirCount)
								AddGadgetItem(ExplorerSelectedListBox,Selfile,0,SelCount,CurrentDirectory$+"/"+SelFile$) 
								SelCount:+1
								SetGadgetText(ExplorerSelectedOrderButton,"Selected Pics "+SelCount)
							Else
								Notify("Selection list full")
								Exit
							EndIf
							
						EndIf
					Next
					
				Case ExplorerBackButton
					Local SlashPos =CurrentDirectory$.FindLast( "/" )
					CurrentDirectory$=CurrentDirectory$[..(SlashPos)]
					CreateIconDirectory(CurrentDirectory)
					SetGadgetText(ExplorerWindow,CurrentDirectory)
					
				Case ExplorerHightLightAllButton
					Local TotalItems = CountGadgetItems(Explorer)-1
					If TotalItems Then
						For Local count = 1  To TotalItems
							If GetListBoxItem(Explorer,count ,1) <>FileTypes$[2] Then  Explorer.SelectItem(count ,1 )
						Next
					EndIf
					
				Case ExplorerHightLightToggleButton
					DebugLog "PicCnt "+PicCnt
					If PicCnt Then
						For Local count = DirCount+1  To DirCount+PicCnt-1
							Explorer.SelectItem(count ,2 )
						Next
					EndIf
					
				Case ExplorerSelectedListUpButton
				
					Local index[]= SelectedGadgetItems(ExplorerSelectedListBox)
					If index[0] > 0
						Local Item:TGadgetItem 
						For Local SelIndex =EachIn Index						
							If Selindex > 0 Then								
								Item = ExplorerSelectedListBox.items[SelIndex-1]
								ExplorerSelectedListBox.items[SelIndex-1] = ExplorerSelectedListBox.items[SelIndex]
								ExplorerSelectedListBox.SetListItem(Selindex-1,ExplorerSelectedListBox.items[SelIndex].text,ExplorerSelectedListBox.items[SelIndex].tip,ExplorerSelectedListBox.items[SelIndex].icon,ExplorerSelectedListBox.items[SelIndex].extra)
								ExplorerSelectedListBox.items[SelIndex] = Item
								ExplorerSelectedListBox.SetListItem(Selindex,item.text,item.tip,item.icon,item.extra)
								ExplorerSelectedListBox.SelectItem(Selindex ,0)					
								ExplorerSelectedListBox.SelectItem(Selindex-1 ,1)	
							EndIf
						Next		
						
					EndIf
					
				Case ExplorerSelectedListDownButton
				
					Local index[]= SelectedGadgetItems(ExplorerSelectedListBox)
					If index
						Local Item:TGadgetItem 
						Local MaxSelIndex = index.length-1
						If Index[MaxSelIndex] < CountGadgetItems(ExplorerSelectedListBox)-1 Then
							For Local SelIndex2 = MaxSelIndex  To 0 Step -1
								Local SelIndex = Index[SelIndex2]
								
								Item = ExplorerSelectedListBox.items[SelIndex+1]
								
								ExplorerSelectedListBox.items[SelIndex+1] = ExplorerSelectedListBox.items[SelIndex]
								ExplorerSelectedListBox.items[SelIndex] = Item
								ExplorerSelectedListBox.SetListItem(Selindex,item.text,item.tip,item.icon,item.extra)
								ExplorerSelectedListBox.SetListItem(Selindex+1,ExplorerSelectedListBox.items[SelIndex+1].text,ExplorerSelectedListBox.items[SelIndex+1].tip,ExplorerSelectedListBox.items[SelIndex+1].icon,ExplorerSelectedListBox.items[SelIndex+1].extra)
								ExplorerSelectedListBox.SelectItem(Selindex ,0)		
								ExplorerSelectedListBox.SelectItem(Selindex+1 ,1)
							Next								
						EndIf						
					EndIf
					
				Case ExplorerClearButton
					ClearGadgetItems(ExplorerSelectedListBox)
					SelCount = 0
					SetGadgetText(ExplorerSelectedOrderButton,"Selected Pics")							
					
				Case ExplorerSelectedListDeleteButton
					Local DelIndex[]= SelectedGadgetItems(ExplorerSelectedListBox)		
					Local DelCount,SelIndex
					If DelIndex
						For SelIndex =EachIn DelIndex	
							RemoveGadgetItem(ExplorerSelectedListBox,SelIndex- DelCount)
							DelCount:+1
						Next		
					EndIf
					SetGadgetText(ExplorerSelectedOrderButton,"Selected Pics "+(SelIndex- DelCount+1))
					
				Case ExplorerSelectedOrderButton
				
				Case ExplorerPreviewButton
					PreviewFileName$=GadgetItemText(Explorer,SelectedGadgetItem(Explorer))
					If LastPreviewFileName$ <> PreviewFileName$ Then
						SetGadgetShape(ExplorerPreviewWindow,GadgetX( ExplorerWindow)+GadgetX( ExplorerSelectedPanel)-405,GadgetY( ExplorerWindow)+GadgetY( ExplorerPanel),400,398)
						PreviewFile(PreviewFileName$)
					Else
						HideGadget ExplorerPreviewWindow
						LastPreviewFileName$=""
					EndIf
					
				Case ExplorerCancelButton 
					DebugStop
					
				Case ExplorerOkButton
					TotalPicsSelected = CountGadgetItems(ExplorerSelectedListBox)
					' The tip contains the full path
					For Local count = 0  To TotalPicsSelected -1
						Print count +". "+ExplorerSelectedListBox.items[count].text
						Print "   Path = "+ ExplorerSelectedListBox.items[count].tip
					Next			
			EndSelect
			
		Case EVENT_GADGETMENU
			Select Gadget 
				Case Explorer
					PreviewFileName$=GadgetItemText(Explorer,SelectedGadgetItem(Explorer))
					If LastPreviewFileName$ <> PreviewFileName$ Then
						PreviewFile(PreviewFileName$)						
					Else
						HideGadget ExplorerPreviewWindow
						LastPreviewFileName$=""						
					EndIf
			EndSelect
			
		Case EVENT_WINDOWCLOSE
			Select gadget
				Case ExplorerPreviewWindow
					HideGadget ExplorerPreviewWindow
					LastPreviewFileName$=""
				Case ExplorerWindow
					Exit
			EndSelect
	End Select
Forever