'Load dialogue with image preview - Jolly Roger, June 2005 'Using code by Abel, Sean and Trondoc AUTODEFINE "OFF" '****** Global variable definitions & declaration for load dialogue ******** WINDOW imagepreviewwindow INT openbutton,cancelbutton,listview,editbox,upbutton,foldernameeditbox DIALOG loaddialogue STRING directoryname,chosenfilename openbutton=1 cancelbutton=2 listview=3 editbox=4 upbutton=5 foldernameeditbox=6 'Standard NMLISTVIEW. When a column is clicked on, Windows sends a variable of this type in @QUAL TYPE NMLISTVIEW def hwndFrom:INT def idFrom:INT def code:INT def iItem:INT def iSubItem:INT def uNewState:INT def uOldState:INT def uChanged:INT def ptActionx:INT def ptActiony:INT def lParam:INT ENDTYPE NMLISTVIEW lv 'Memory and variable to read data out of @QUAL MEMORY qualmem DECLARE IMPORT,SHGetFileInfo(Path:string,FileAttributes:int,sfi:memory,FileInfo:uint,Flags:uint),INT TYPE SHFILEINFO INT hIcon,iIcon,Attributes ISTRING DisplayName[260] ISTRING TypeName[79] ENDTYPE SHFILEINFO shfi type LV_ITEM UINT mask int iItem int iSubItem UINT state UINT stateMask pointer text int cchTextMax int iImage 'index of the list view items icon int lParam '32-bit value to associate with item endtype LV_ITEM lvi '********************************************************************* WINDOW win UINT handle ISTRING filepath[260] OPENWINDOW win,0,0,1024,768,0,0,"Image Preview Test",&mainwindowhandler BEGINMENU win MENUTITLE "&File" MENUITEM "Load Picture",0,300 SEPARATOR MENUITEM "Exit",0,301 ENDMENU WAITUNTIL IsWindowClosed(win) END SUB mainwindowhandler(),INT SELECT @MESSAGE CASE @IDCREATE CENTERWINDOW win CASE @IDCLOSEWINDOW CLOSEWINDOW win CASE @IDMENUPICK SELECT @MENUNUM CASE 300 'Set up dialogue box setuploadfiledialogue(win,GETSTARTPATH) 'Show the dialogue box and get the chosen filename filepath=chosenfilepath() handle=LOADIMAGE(filepath,@IMGSCALABLE) SHOWIMAGE win,handle,@IMGSCALABLE,0,0 DELETEIMAGE handle,@IMGSCALABLE CASE 301 CLOSEWINDOW win ENDSELECT ENDSELECT RETURN 0 ENDSUB '***************** SUBs for load dialogue ********************** SUB chosenfilepath(),STRING DOMODAL loaddialogue RETURN chosenfilename ENDSUB SUB setuploadfiledialogue(parentwindow:WINDOW,startpath:STRING) UINT dir 'Create dialogue CREATEDIALOG loaddialogue,0,0,300,375,@CAPTION,parentwindow,"Load image",&dialoguehandler CONTROL loaddialogue,@BUTTON,"Open",205,230,60,22,@TABSTOP,openbutton CONTROL loaddialogue,@BUTTON,"Cancel",205,270,60,22,@TABSTOP,cancelbutton CONTROL loaddialogue,@LISTVIEW,"",20,40,260,130,0x50000041|@LVSSMALLICON|@LVSSORTASCENDING|@BORDER,listview CONTROL loaddialogue,@EDIT,"",20,180,260,20,@TABSTOP,editbox CONTROL loaddialogue,@BUTTON,"Up",20,9,26,22,@TABSTOP,upbutton CONTROL loaddialogue,@STATIC,"",60,6,200,34,@TABSTOP,foldernameeditbox 'Start with specified path if possible dir=FINDOPEN(startpath+"\\*.*") IF dir directoryname=startpath FINDCLOSE dir ELSE 'Can't start with specified path.Start at root of drive directoryname=LEFT$(GETSTARTPATH,INSTR(GETSTARTPATH,"\\")) ENDIF chosenfilename="" ENDSUB SUB dialoguehandler(),INT DEF posn:INT DEF dir:UINT DEF aspectratio:FLOAT ISTRING filename[260],foldername[260],fileextension[260] SELECT @MESSAGE CASE @IDINITDIALOG CENTERWINDOW loaddialogue 'Set listview to use icons SetImageList() 'Add a listview column CONTROLCMD loaddialogue,listview,@LVINSERTCOLUMN,0,"" CONTROLCMD loaddialogue,listview,@LVSETCOLWIDTH,0,250 ENABLECONTROL loaddialogue,openbutton,0 updatefilelistview() 'Create window to hold preview image OPENWINDOW imagepreviewwindow,20,210,150,150,@NOCAPTION|@BORDER,loaddialogue,"",&imagepreviewwindowhandler IF INSTR(directoryname,"\\")=LEN(directoryname) 'Starting at root of drive SETCONTROLTEXT loaddialogue,foldernameeditbox,"" SETCONTROLTEXT loaddialogue,foldernameeditbox,directoryname ELSE 'Not starting at root of drive.Find foldername FOR posn=LEN(directoryname)-1 TO 1 STEP -1 IF MID$(directoryname,posn,1)="\\" foldername=MID$(directoryname,posn+1) 'Remove trailing \ foldername=LEFT$(foldername,LEN(foldername)-1) SETCONTROLTEXT loaddialogue,foldernameeditbox,"" SETCONTROLTEXT loaddialogue,foldernameeditbox,foldername posn=1 ENDIF NEXT posn ENDIF CASE @IDCONTROL IF @CONTROLID=openbutton chosenfilename=directoryname+GETCONTROLTEXT(loaddialogue,editbox) CLOSEDIALOG loaddialogue ENDIF IF @CONTROLID=cancelbutton CLOSEDIALOG loaddialogue ENDIF IF @CONTROLID=listview IF @NOTIFYCODE=@NMCLICK 'Click on listview.Find name of file/folder clicked on qualmem = @QUAL READMEM qualmem,1,lv CONTROLCMD(loaddialogue,listview,@LVGETTEXT,lv.iItem,0,filename) 'If is not a folder then display preview image dir=FINDOPEN(directoryname+filename+"\\*.*") IF dir=0 'Is a supported file type UINT imagehandle INT width,height SETCONTROLTEXT loaddialogue,editbox,filename fileextension=LCASE$(RIGHT$(filename,3)) 'Find aspect ratios of images so not distorted in preview window aspectratio=0 SELECT fileextension CASE "gif" aspectratio=gifaspectratio(directoryname+filename) CASE "bmp" imagehandle=LOADIMAGE(directoryname+filename,@IMGBITMAP) GETBITMAPSIZE(imagehandle,width,height) IF height>0 THEN aspectratio=FLT(width)/height DELETEIMAGE imagehandle,@IMGBITMAP DEFAULT aspectratio=jpegaspectratio(directoryname+filename) ENDSELECT 'Show preview of image in preview window imagehandle=LOADIMAGE(directoryname+filename,@IMGSCALABLE) RECT imagepreviewwindow,0,0,150,150,0xFFFFFF,0xFFFFFF IF aspectratio=0 'Couldn't find aspect ratio for image SHOWIMAGE imagepreviewwindow,imagehandle,@IMGSCALABLE,0,0,150,150 ELSE 'Scale image so not distorted IF aspectratio>1 SHOWIMAGE imagepreviewwindow,imagehandle,@IMGSCALABLE,0,(150-150/aspectratio)/2,150,150/aspectratio ELSE SHOWIMAGE imagepreviewwindow,imagehandle,@IMGSCALABLE,(150-150*aspectratio)/2,0,150*aspectratio,150 ENDIF ENDIF DELETEIMAGE imagehandle,@IMGSCALABLE ENABLECONTROL loaddialogue,openbutton,1 ELSE 'Item is a folder RECT imagepreviewwindow,0,0,150,150,0xFFFFFF,0xFFFFFF SETCONTROLTEXT loaddialogue,editbox,"" ENABLECONTROL loaddialogue,openbutton,0 FINDCLOSE dir ENDIF ENDIF IF @NOTIFYCODE=@NMDBLCLK 'Doubled clicked in the listview box.Find name of file/folder double clicked qualmem = @QUAL READmem qualmem,1,lv CONTROLCMD(loaddialogue,listview,@LVGETTEXT,lv.iItem,0,filename) dir=FINDOPEN (directoryname+filename+"\\*.*") IF dir 'Double clicked on a folder or drive foldername=filename directoryname=directoryname+foldername+"\\" SETCONTROLTEXT loaddialogue,foldernameeditbox,"" SETCONTROLTEXT loaddialogue,foldernameeditbox,foldername updatefilelistview() 'Enable Up button ENABLECONTROL loaddialogue,upbutton,1 FINDCLOSE dir ELSE 'Double clicked on a supported file.Get filename and close dialogue chosenfilename=directoryname+filename CLOSEDIALOG loaddialogue ENDIF ENDIF ENDIF IF @CONTROLID=upbutton 'Move up a folder IF INSTR(directoryname,"\\")=LEN(directoryname) 'At root of drive directoryname="" finddrives() 'Disable up button ENABLECONTROL loaddialogue,upbutton,0 SETCONTROLTEXT loaddialogue,foldernameeditbox,"" SETCONTROLTEXT loaddialogue,foldernameeditbox,"My Computer" ELSE 'Not at root of drive.Remove part of directory name after \ FOR posn=LEN(directoryname)-1 TO 1 STEP -1 IF MID$(directoryname,posn,1)="\\" directoryname=LEFT$(directoryname,posn) updatefilelistview() SETCONTROLTEXT loaddialogue,editbox,"" ENABLECONTROL loaddialogue,openbutton,0 RECT imagepreviewwindow,0,0,150,150,0xFFFFFF,0xFFFFFF 'Clear preview window posn=1 ENDIF NEXT posn 'Update foldername editbox IF INSTR(directoryname,"\\")=LEN(directoryname) 'At root of drive after gone up a level SETCONTROLTEXT loaddialogue,foldernameeditbox,"" SETCONTROLTEXT loaddialogue,foldernameeditbox,directoryname ELSE 'Not at root of drive after gone up a level.Find folder name FOR posn=LEN(directoryname)-1 TO 1 STEP -1 IF MID$(directoryname,posn,1)="\\" foldername=MID$(directoryname,posn+1) 'Remove trailing \ foldername=LEFT$(foldername,LEN(foldername)-1) SETCONTROLTEXT loaddialogue,foldernameeditbox,"" SETCONTROLTEXT loaddialogue,foldernameeditbox,foldername posn=1 ENDIF NEXT posn ENDIF ENDIF ENDIF ENDSELECT RETURN 0 ENDSUB SUB SetImageList() MEMORY mem UINT hListview,hSHImageList 'Get handle for listview control hListview=GETCONTROLHANDLE(loaddialogue,listview) 'Find handle for shell icon image list and assign it to the listview image list allocmem(mem,len(shfi),1) hSHImageList=SHGetFileInfo("",0,mem,len(shfi),0x4001) 'SYSICONINDEX,SMALLICON freemem mem SendMessage(hListview, 0x1003, 1, hSHImageList) 'LVM_SETIMAGELIST RETURN ENDSUB 'Subroutine to retrieve the Display Name and Icon index for the drive SUB GetFileInfo(drive:STRING) MEMORY mem ALLOCMEM(mem,len(shfi),1) SHGetFileInfo(drive,0,mem,len(shfi),0x0301) 'DISPLAYNAME,ICON,SMALLICON READMEM mem,1,shfi FREEMEM mem ENDSUB sub AddListViewItem(hWnd as window,id as int,itemnum as int,text as string,imagenum as int) lvi.mask=0x01 | 0x02 lvi.iitem=itemnum lvi.isubitem=0 lvi.text=text lvi.cchTextMax=len(text) lvi.iImage=imagenum lvi.lParam=15 SendMessage hWnd, 4103/*LVM_INSERTITEM*/, 0, &lvi, listview endsub SUB imagepreviewwindowhandler(),INT RETURN 0 ENDSUB SUB updatefilelistview() DEF numberofitemsinlistview,item:INT DEF dir,dir2:UINT ISTRING fileorfoldername[260],fileextension[32] 'Empty listview CONTROLCMD loaddialogue,listview,@LVDELETEALL numberofitemsinlistview=0 dir = FINDOPEN(directoryname+"*.*") IF dir 'Find names of all files & folders in current directory DO fileorfoldername = FINDNEXT(dir) IF fileorfoldername<>"" IF LEFT$((RIGHT$(fileorfoldername,4)),1)="." 'Item has a three character file extension fileextension=LCASE$(RIGHT$(fileorfoldername,3)) IF (fileextension="jpg")|(fileextension="bmp")|(fileextension="gif") GetFileInfo(directoryname+fileorfoldername) AddListViewItem(loaddialogue,listview,numberofitemsinlistview,fileorfoldername,shfi.iIcon) numberofitemsinlistview=numberofitemsinlistview+1 ENDIF ELSE 'Item does not have three character file extension 'Use FINDOPEN to see if it is a folder dir2=FINDOPEN(directoryname+fileorfoldername+"\*.*") IF dir2 IF fileorfoldername<>"." 'This item is a folder.Add chr$(10) to start so will be at top of list GetFileInfo(directoryname+fileorfoldername) AddListViewItem(loaddialogue,listview,numberofitemsinlistview,chr$(10)+fileorfoldername,shfi.iIcon) numberofitemsinlistview=numberofitemsinlistview+1 FINDCLOSE dir2 ENDIF ENDIF ENDIF ENDIF UNTIL fileorfoldername="" FINDCLOSE dir 'Remove CHR$(10) from folder names FOR item=0 TO numberofitemsinlistview-1 CONTROLCMD(loaddialogue,listview,@LVGETTEXT,item,0,fileorfoldername) IF ASC(fileorfoldername)=10 fileorfoldername=MID$(fileorfoldername,2) CONTROLCMD(loaddialogue,listview,@LVSETTEXT,item,0,fileorfoldername) ELSE 'No more folders item=numberofitemsinlistview-1 ENDIF NEXT item ENDIF ENDSUB SUB finddrives() DEF drive,driveavailable[26],numberofitems:INT DEF dir:UINT DEF driveletter:STRING numberofitems=0 'Check all possible drives from a:/ to z:/ FOR drive=0 TO 25 driveavailable[drive]=0 driveletter=CHR$(drive+65) dir=FINDOPEN(driveletter+":\\*.*") IF dir 'Drive is available driveavailable[drive]=1 FINDCLOSE dir ENDIF NEXT drive 'Empty listview CONTROLCMD loaddialogue,listview,@LVDELETEALL 'Fill listview with available drives FOR drive=0 TO 25 IF driveavailable[drive] GetFileInfo(CHR$(drive+65)+":\\") AddListViewItem(loaddialogue,listview,numberofitems,CHR$(drive+65)+":",shfi.iIcon) numberofitems=numberofitems+1 ENDIF NEXT drive ENDSUB SUB gifaspectratio(filename$:STRING),FLOAT 'Adapted from code by Trondoc DEF GifFile:BFILE DEF widthLO,widthHI,heightLO,heightHI:CHAR ' CHAR byte1 DEF width,height:INT DEF aspectratio:FLOAT aspectratio=0 IF(OPENFILE(GifFile,filename$,"R")=0) 'Start reading file at seventh byte SEEK GifFile,6 READ(GifFile,widthLO) READ(GifFile,widthHI) READ(GifFile,heightLO) READ(GifFile,heightHI) width=256*(widthHI&255)+(widthLO&255) height=256*(heightHI&255)+(heightLO&255) CLOSEFILE GifFile IF height>1 THEN aspectratio=FLT(width)/height ENDIF RETURN aspectratio ENDSUB SUB jpegaspectratio(imagefilename$:STRING),FLOAT 'Adapted from code by Trondoc DEF JpgFile:BFILE DEF JpgLength,segLen,FilePos,imageheight,imagewidth:INT DEF byte1,byte2,heightHI,heightLO,widthLO,widthHI,segLenHI,segLenLO:CHAR DEF aspectratio:FLOAT DEF C0,C2,D0,D9:CHAR C0=CHR$(192) C2=CHR$(194) D0=CHR$(0xD0) D9=CHR$(0xD9) imageheight=0 imagewidth=0 aspectratio=0 IF(OPENFILE(JpgFile,imagefilename$,"R") = 0) JpgLength = LEN(JpgFile) READ(JpgFile,byte1) READ(JpgFile,byte2) Do READ(JpgFile,byte1) READ(JpgFile,byte2) IF byte2=C0 | byte2=C2 'Found start of frame 'SKIP 3 BYTES (FRAME LENGTH[2] AND SAMPLE PRECISION[1]) FilePos = SEEK(JpgFile) SEEK JpgFile,(FilePos+3) READ(JpgFile,heightHI) READ(JpgFile,heightLO) READ(JpgFile,widthHI) READ(JpgFile,widthLO) imageheight=(256*(heightHI&255))+(heightLO&255) imagewidth=(256*(widthHI&255))+(widthLO&255) ELSE 'SoF0 (Start of Frame Zero) not found 'CALCULATE SEGMENT LENGTH AND POSITION FILE POINTER TO LOOK AT NEXT SEGMENT READ(JpgFile,segLenHI) READ(JpgFile,segLenLO) segLen=256*(segLenHI&255)+(segLenLO&255) FilePos = SEEK(JpgFile) 'current File Position FilePos = FilePos+segLen-2 '-2=bytes into segment we've already read SEEK JpgFile,FilePos ENDIF UNTIL imageheight>0 | FilePos>=JpgLength CLOSEFILE JpgFile ENDIF IF imageheight>0 aspectratio=FLT(imagewidth)/imageheight ENDIF RETURN aspectratio ENDSUB