Get the Shell Thumbnail for files
Posted: Wed Mar 29, 2006 10:14 pm
This is just a little something i played around with. Maybe it is usefull to somebody.
It allows to easily get a preview image from the shell like the ones explorer displays.
This requires PB4 beta8 to run.
It behaves just like CreateImage(). Supports #PB_Any as well as static numbers.
The function fails (returns 0) if there is no preview supported for the file type.
Here is the procedure:
A simple example:
Here is a more complex example. It uses SHGetFileInfo_() to get an Icon for the file
if no preview is available to create a nice folder preview:
It allows to easily get a preview image from the shell like the ones explorer displays.
This requires PB4 beta8 to run.
It behaves just like CreateImage(). Supports #PB_Any as well as static numbers.
The function fails (returns 0) if there is no preview supported for the file type.
Here is the procedure:
Code: Select all
Procedure GetShellThumbnail(FileName$, Image, Width, Height, Depth = #PB_Image_DisplayFormat)
Protected Result = 0, ImageResult
Protected Desktop.IShellFolder, Folder.IShellFolder
Protected Extract.IExtractImage
Protected *pidlFolder.ITEMIDLIST, *pidlFile.ITEMIDLIST
Protected Priority, Flags, Bitmap = 0, size.SIZE
If SHGetDesktopFolder_(@Desktop) >= 0
If Desktop\ParseDisplayName(#Null, #Null, GetPathPart(FileName$), #Null, @*pidlFolder, #Null) = #S_OK
If Desktop\BindToObject(*pidlFolder, #Null, ?IID_IShellFolder, @Folder) = #S_OK
If Folder\ParseDisplayName(#Null, #Null, GetFilePart(FileName$) , #Null, @*pidlFile, #Null) = #S_OK
If Folder\GetUIObjectOf(#Null, 1, @*pidlFile, ?IID_IExtractImage, 0, @Extract) = #S_OK
ImageResult = CreateImage(Image, Width, Height, Depth)
If ImageResult
If Image = #PB_Any
Image = ImageResult
EndIf
If Depth = #PB_Image_DisplayFormat
Depth = ImageDepth(Image)
EndIf
size\cx = Width
size\cy = Height
If Extract\GetLocation(Space(#MAX_PATH), #MAX_PATH, @Priority, @size, Depth, @Flags) >= 0
If Extract\Extract(@Bitmap) >= 0 And Bitmap
If StartDrawing(ImageOutput(Image))
DrawImage(Bitmap, 0, 0)
StopDrawing()
Result = ImageResult
EndIf
DeleteObject_(Bitmap)
EndIf
EndIf
Extract\Release()
EndIf
If Result = 0
FreeImage(Image)
EndIf
EndIf
CoTaskMemFree_(*pidlFile)
EndIf
Folder\Release()
EndIf
CoTaskMemFree_(*pidlFolder)
EndIf
Desktop\Release()
EndIf
ProcedureReturn Result
DataSection
IID_IShellFolder: ; {000214E6-0000-0000-C000-000000000046}
Data.l $000214E6
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
IID_IExtractImage: ; {BB2E617C-0920-11D1-9A0B-00C04FC2D6C1}
Data.l $BB2E617C
Data.w $0920, $11D1
Data.b $9A, $0B, $00, $C0, $4F, $C2, $D6, $C1
EndDataSection
EndProcedure
Code: Select all
#ExplorerGadget = 0
#ImageGadget = 1
#Image = 0
If OpenWindow(0, 0, 0, 500, 400, "Shell Thumbnails", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
ExplorerTreeGadget(#ExplorerGadget, 5, 5, 190, 390, "C:\")
ImageGadget(#ImageGadget, 225, 100, 250, 200, 0, #PB_Image_Border)
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Gadget And EventGadget() = #ExplorerGadget And EventType() = #PB_EventType_Change
If GetShellThumbnail(GetGadgetText(#ExplorerGadget), #Image, 250, 200)
SetGadgetState(#ImageGadget, ImageID(#Image))
Else
SetGadgetState(#ImageGadget, 0)
EndIf
EndIf
Until Event = #PB_Event_CloseWindow
EndIf
End
if no preview is available to create a nice folder preview:
Code: Select all
#ExplorerGadget = 0
#ScrollGadget = 1
#ProgressGadget = 2
Structure File
FileName$
Text$
Image.l
Gadget.l ; Its a ContainerGadget, so the others inside are freed as well
EndStructure
NewList File.File()
If OpenWindow(0, 0, 0, 800, 600, "Shell Thumbnails", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
ExplorerTreeGadget(#ExplorerGadget, 5, 5, 240, 590, "C:\", #PB_Explorer_NoFiles)
ScrollAreaGadget(#ScrollGadget, 250, 5, 545, 570, 520, 10, 10)
CloseGadgetList()
ProgressBarGadget(#ProgressGadget, 250, 580, 545, 15, 0, 100)
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Gadget And EventGadget() = #ExplorerGadget And EventType() = #PB_EventType_Change
; Clear the old content of the display
;
ForEach File()
FreeGadget(File()\Gadget)
FreeImage(File()\Image)
Next File()
ClearList(File())
; Creating the thumbnail may take a little time for certain file types
; (for example big PowerPoint presentations), especially when there are lots
; of files in a folder. So the text information is read first (which is quite fast)
; and the images are created later with a progressbar to indicate the progress
;
Count = 0
If ExamineDirectory(0, GetGadgetText(#ExplorerGadget), "*.*")
While NextDirectoryEntry(0)
If DirectoryEntryType(0) = #PB_DirectoryEntry_File
AddElement(File())
File()\FileName$ = GetGadgetText(#ExplorerGadget) + DirectoryEntryName(0)
File()\Text$ = "Name: " + File()\FileName$ + Chr(13)
File()\Text$ + "Size: " + Str(DirectoryEntrySize(0)) + " Bytes" + Chr(13)
File()\Text$ + FormatDate("Created: %mm/%dd/%yyyy", DirectoryEntryDate(0, #PB_Date_Created)) + Chr(13)
File()\Text$ + FormatDate("Modified: %mm/%dd/%yyyy", DirectoryEntryDate(0, #PB_Date_Modified)) + Chr(13)
File()\Text$ + FormatDate("Accessed: %mm/%dd/%yyyy", DirectoryEntryDate(0, #PB_Date_Accessed))
Count + 1
EndIf
Wend
EndIf
If Count > 0
OpenGadgetList(#ScrollGadget)
SetGadgetState(#ProgressGadget, 0)
While WindowEvent(): Wend ; Refresh the display so it looks better
ForEach File()
index = ListIndex(File())
; Create the thumbnail
File()\Image = GetShellThumbnail(File()\FileName$, #PB_Any, 100, 80)
; If no image could be created, we try to read the Icon for the file type and
; show that
;
If File()\Image = 0
File()\Image = CreateImage(#PB_Any, 100, 80)
If File()\Image And StartDrawing(ImageOutput(File()\Image))
Box(0, 0, 100, 80, $FFFFFF)
If SHGetFileInfo_(@File()\FileName$, 0, @info.SHFILEINFO, SizeOf(SHFILEINFO), #SHGFI_ICON|#SHGFI_LARGEICON)
DrawImage(info\hIcon, 34, 24)
DestroyIcon_(info\hIcon)
EndIf
StopDrawing()
EndIf
EndIf
File()\Gadget = ContainerGadget(#PB_Any, 5, 5+index*90, 510, 80, #PB_Container_Flat)
ImageGadget(#PB_Any, 0, 0, 100, 80, ImageID(File()\Image))
TextGadget(#PB_Any, 105, 5, 400, 70, File()\Text$)
CloseGadgetList()
; Update the Gadget states and refresh the display
;
SetGadgetState(#ProgressGadget, (index * 100)/Count)
SetGadgetAttribute(#ScrollGadget, #PB_ScrollArea_InnerHeight, (index+1)*90 + 10)
While WindowEvent(): Wend
Next File()
CloseGadgetList()
EndIf
SetGadgetState(#ProgressGadget, 100)
SetGadgetAttribute(#ScrollGadget, #PB_ScrollArea_InnerHeight, Count*90 + 10)
EndIf
Until Event = #PB_Event_CloseWindow
EndIf
End