It is currently Sat Oct 31, 2020 4:46 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Get the Shell Thumbnail for files
PostPosted: Wed Mar 29, 2006 10:14 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 5:21 pm
Posts: 5815
Location: Germany
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:
Code:
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


A simple example:
Code:
#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


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:

Code:
#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

_________________
quidquid Latine dictum sit altum videtur


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Mar 29, 2006 10:34 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Jan 24, 2004 6:56 pm
Posts: 768
Danke Timo!

_________________
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Mar 30, 2006 7:45 am 
Offline
Addict
Addict
User avatar

Joined: Wed Apr 30, 2003 8:15 am
Posts: 1049
Location: Germany
Wow!! That rocks. Thank you fr34k!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Mar 30, 2006 10:10 am 
Offline
Moderator
Moderator

Joined: Sat Dec 27, 2003 3:55 am
Posts: 3321
Location: Great Southern Land
Awesome. Thank you!

_________________
@}--`--,-- A rose by any other name ..


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Mar 30, 2006 4:25 pm 
Offline
Always Here
Always Here

Joined: Mon Sep 22, 2003 6:45 pm
Posts: 7446
Location: Norway
I think there is an error somewhere, because no preview is shown for my deneba canvas files when I use the simple example, but the preview is shown in windows explorer and in the complex example.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Mar 30, 2006 4:32 pm 
Offline
Addict
Addict
User avatar

Joined: Wed Oct 15, 2003 12:40 am
Posts: 1126
Location: Sweden
Wow! Really nice! Thanks! :D

_________________
Image
(\__/)
(='.'=) This is Bunny. Copy and paste Bunny into your
(")_(") signature to help him gain world domination.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Mar 30, 2006 6:55 pm 
Offline
Addict
Addict
User avatar

Joined: Wed Apr 20, 2005 12:48 pm
Posts: 1104
fantastic *10/10 points*
great work fr34k!

_________________
va!n aka Thorsten

Intel i7-980X Extreme Edition, 12 GB DDR3, Radeon 5870 2GB, Windows7 x64,


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Mar 30, 2006 8:53 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 5:21 pm
Posts: 5815
Location: Germany
Trond: Are you sure its not just the file icon you see in the complex example ?
It works fine here for all file types.

_________________
quidquid Latine dictum sit altum videtur


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Mar 31, 2006 4:36 pm 
Offline
Always Here
Always Here

Joined: Mon Sep 22, 2003 6:45 pm
Posts: 7446
Location: Norway
freak wrote:
Trond: Are you sure its not just the file icon you see in the complex example ?
It works fine here for all file types.
Of course I am sure.
Simple example (file icon show in file list): http://img92.imageshack.us/my.php?image=blur2560mz.png
Advanced example (preview shows): http://img483.imageshack.us/my.php?image=blur2569ic.png
Windows explorer: http://img394.imageshack.us/my.php?image=blur2567yd.png


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Apr 01, 2006 9:10 pm 
Offline
PureBatMan Forever
PureBatMan Forever
User avatar

Joined: Tue Feb 10, 2004 3:07 am
Posts: 2307
Location: Ohio, USA
Very useful! Thank you freak. :)

_________________
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Jul 05, 2006 1:23 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 5:21 pm
Posts: 5815
Location: Germany
Just a quick note that this code needs a CoInitialize_(0) call (and a CoUninitialize_() at the end)
to work properly.

The ExplorerTreeGadget() does these calls automatically, thats why it works as it is,
but does not work if you take the gadget out of the code.

_________________
quidquid Latine dictum sit altum videtur


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Oct 07, 2008 4:58 pm 
Offline
New User
New User

Joined: Sun Jan 16, 2005 1:23 pm
Posts: 5
Real great work!!!

However, could anyone please give me a short hint, how can I select a thumbnail within the gadget. The idea is to pass the selected thumbnail image file name which is in the gadget list to another programme (image editor paint.net). Paint.net is missing the preview or browser function but with this snipplet I could very easy preview the files and pass them to paint.net by using the run command.


Many thanks


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Oct 08, 2008 5:45 pm 
Offline
Enthusiast
Enthusiast

Joined: Sat Apr 26, 2003 3:23 pm
Posts: 263
Excellent piece of work.

_________________
James Boyd
http://www.hi-toro.com/
Death to the Pixies!


Top
 Profile  
Reply with quote  
 Post subject: Re: Get the Shell Thumbnail for files
PostPosted: Tue Nov 30, 2010 12:06 am 
Offline
Addict
Addict

Joined: Thu Nov 01, 2007 5:37 pm
Posts: 1981
Location: Germany
Great work!

A small tip: PureBasic now supports alpha channels, so do the following to maintain it:
  • Use "32" as Depth
  • Put "| #PB_Image_Transparent" at the end of "CreateImage(Image, Width, Height, Depth)" (to create a fully transparent image)
  • Set "DrawImage()" to "DrawAlphaImage()"


I still have a small question:
How is it possible to find out the real thumbnail dimension (or the original one) using this interface stuff?

_________________
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!


Top
 Profile  
Reply with quote  
 Post subject: Re: Get the Shell Thumbnail for files
PostPosted: Tue Nov 30, 2010 1:02 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Mar 18, 2007 2:26 pm
Posts: 342
Location: Munich, Germany
Looks nice. Thanks for sharing.
But images are up-side-down (bmp and jpeg).
Thumbnails of Videos and OpenOffice Docs look fine. (second Example)

-PB 4.51 - Win7 Home Premium 32bit


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 22 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye