Extracting a file's thumbnail
by Richard Russell, July 2007
Several file types can have associated thumbnail images, which are displayed (for example) in Windows Explorer's Thumbnails view. Examples of such file types are image files (e.g. BMP, GIF, JPEG), PowerPoint files, Word and Excel files (when the Save preview picture option is enabled) and folders.
Displaying such thumbnails in your own program, should you want to, is quite tricky, but is made simple using the FN_thumbnail function listed in this article. This function returns a handle to the thumbnail image, which you can use as you would any other image handle. For example you can use it to display the image in a static control, either in a dialogue box or on your main output window.
The code below will display, in a static control, the thumbnail for the file CLOCK.JPG:
INSTALL @lib$+"WINLIB5" xpos% = 100 ypos% = 100 cx% = 128 cy% = 128 _WS_BORDER = &800000 _SS_BITMAP = &0E _STM_SETIMAGE = &172 file$ = "C:\Program Files\BBC BASIC for Windows\EXAMPLES\GRAPHICS\CLOCK.JPG" hsb% = FN_staticbox("", xpos%, ypos%, cx%, cy%, 0, _WS_BORDER OR _SS_BITMAP) hbm% = FN_thumbnail(file$, cx%, cy%) SYS "SendMessage", hsb%, _STM_SETIMAGE, 0, hbm%
Here xpos% and ypos% are the position where you want the static control to be displayed (pixels from the top left-hand corner) and cx% and cy% are the desired width and height in pixels. If you want to display the thumbnail for a folder don't include a trailing backslash (\) in the pathname you specify.
When you have finished with the image you should delete its handle as follows:
SYS "DeleteObject", hbm%
Don't do this whilst the image is still displayed, since it will not refresh correctly when uncovered, or when restored after being minimised.
The FN_thumbnail function is listed below. Its parameters are the file or folder whose thumbnail is wanted and the preferred width and height of the thumbnail in pixels. It returns a handle to the thumbnail image, or zero if the file does not have a thumbnail. An error will result if the file/folder does not exist or the file is an unsuitable type.
DEF FN_thumbnail(file$, cx%, cy%) LOCAL patha%, pathw%, name%, ole32%, shfroot%, shf%, pidl%, iei%, flags%, hbm% LOCAL IShellFolder{}, IExtractImage{}, IID{}, size{} DIM patha% LOCAL 260, pathw% LOCAL 521 DIM IShellFolder{QueryInterface%, AddRef%, Release%, ParseDisplayName%, \ \ EnumObjects%, BindToObject%, BindToStorage%, CompareIDs%, \ \ CreateViewObject%, GetAttributesOf%, GetUIObjectOf%, \ \ GetDisplayNameOf%, SetNameOf%} DIM IExtractImage{QueryInterface%, AddRef%, Release%, GetLocation%, Extract%} DIM IID{a%,b%,c%,d%}, size{cx%,cy%} SYS "LoadLibrary", "OLE32.DLL" TO ole32% SYS "GetProcAddress", ole32%, "CoInitialize" TO `CoInitialize` SYS "GetProcAddress", ole32%, "CoUninitialize" TO `CoUninitialize` SYS `CoInitialize`, 0 SYS "GetFullPathName", file$, 260, patha%, ^name% SYS "MultiByteToWideChar", 0, 0, patha%, -1, pathw%, 260 SYS "SHGetDesktopFolder", ^shfroot% IF shfroot%=0 ERROR 100, "SHGetDesktopFolder failed" !(^IShellFolder{}+4) = !shfroot% SYS IShellFolder.ParseDisplayName%, shfroot%, 0, 0, pathw%, 0, ^pidl%, 0 IF pidl%=0 ERROR 100, "IShellFolder::ParseDisplayName failed (1)" IID.a% = &000214E6 : REM IID_IShellFolder IID.b% = &00000000 IID.c% = &000000C0 IID.d% = &46000000 SYS "SHBindToParent", pidl%, IID{}, ^shf%, 0 IF shf%=0 ERROR 100, "SHBindToParent failed" SYS IShellFolder.Release%, shfroot% !(^IShellFolder{}+4) = !shf% SYS "MultiByteToWideChar", 0, 0, name%, -1, pathw%, 260 SYS IShellFolder.ParseDisplayName%, shf%, 0, 0, pathw%, 0, ^pidl%, 0 IF pidl%=0 ERROR 100, "IShellFolder::ParseDisplayName failed (2)" IID.a% = &BB2E617C : REM IID_IExtractImage IID.b% = &11D10920 IID.c% = &C0000B9A IID.d% = &C1D6C24F SYS IShellFolder.GetUIObjectOf%, shf%, 0, 1, ^pidl%, IID{}, 0, ^iei% IF iei%=0 ERROR 100, "IShellFolder::GetUIObjectOf failed" !(^IExtractImage{}+4) = !iei% size.cx% = cx% size.cy% = cy% _IEIFLAG_ORIGSIZE = &40 _IEIFLAG_QUALITY = &200 flags% = _IEIFLAG_ORIGSIZE OR _IEIFLAG_QUALITY SYS IExtractImage.GetLocation%, iei%, pathw%, 260, 0, size{}, 24, ^flags% SYS IExtractImage.Extract%, iei%, ^hbm% SYS IShellFolder.Release%, shf% SYS IExtractImage.Release%, iei% SYS `CoUninitialize` = hbm%