Results 1 to 11 of 11

Thread: IExtractImage

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2008
    Location
    Argentina
    Posts
    441

    IExtractImage

    Hi, I have this function to get the thumbnails of files and folders, and it works fine, but in windows 7, it does not work with folders, the function uses "IExtractImage", in window 7 the error is when you call GetUIObjectOf (-2144927486)
    Also try to use IShellItemImageFactory but this did not even work on windows 10

    Name:  Sin título.png
Views: 1576
Size:  20.8 KB

    The strangest thing is that in a moment he walked but when he reset the project stopped working.

    ----------EDIT-----------------------------------------
    For some strange reason when compiling the project, the IDE starts working, some library is loaded in memory that makes it work but what will be the library?

    ----------------------------------------------------------
    vb Code:
    1. Public Function GetThumbnailImage(ByVal fileName As String, ByVal lWidth As Long, ByVal lHeight As Long) As Long
    2.  
    3.     Dim DesktopFolder As IShellFolder
    4.     Dim SomeFolder As IShellFolder
    5.     Dim ExtractImage As IExtractImage
    6.     Dim Pidl As Long
    7.     Dim FilePidl As Long
    8.     Dim IID_IShellFolder As UUID
    9.     Dim IID_IExtractImage As UUID
    10.     Dim ThePath As String
    11.     Dim tSize As SIZE
    12.     Dim FolderName  As String
    13.     Dim ShortFileName As String
    14.  
    15.     CLSIDFromString StrPtr("{000214E6-0000-0000-C000-000000000046}"), IID_IShellFolder
    16.     CLSIDFromString StrPtr("{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}"), IID_IExtractImage
    17.    
    18.  
    19.  
    20.     FolderName = Left$(fileName, InStrRev(fileName, "\") - 1)
    21.     ShortFileName = Mid$(fileName, InStrRev(fileName, "\") + 1)
    22.  
    23.     SHGetDesktopFolder DesktopFolder
    24.    
    25.     Call DesktopFolder.ParseDisplayName(0&, 0&, StrPtr(FolderName), 0, Pidl, 0)
    26.     Call DesktopFolder.BindToObject(Pidl, 0&, IID_IShellFolder, SomeFolder)
    27.  
    28.     Call SomeFolder.ParseDisplayName(0&, 0&, StrPtr(ShortFileName), 0, FilePidl, 0)
    29.     Call SomeFolder.GetUIObjectOf(0&, 1, FilePidl, IID_IExtractImage, 0&, ExtractImage)
    30.  
    31.  
    32.     ThePath = String$(MAX_PATH, 0)
    33.    
    34.     tSize.cx = lWidth
    35.     tSize.cy = lHeight
    36.    
    37.     ExtractImage.GetLocation StrPtr(ThePath), MAX_PATH, 0&, tSize, 32, IEIFLAG_NOBORDER Or IEIFLAG_SCREEN Or IEIFLAG_OFFLINE
    38.            
    39.     GetThumbnailImage = ExtractImage.extract
    40.    
    41.  
    42.     'Dim ISIIF As IShellItemImageFactory
    43.     'Dim IID_IShellItemImageFactory As UUID
    44.     'Dim hr As Long
    45.     'Dim hBmp As Long
    46.    
    47.     'CLSIDFromString StrPtr("{BCC18B79-BA16-442F-80C4-8A59C30C463B}"), IID_IShellItemImageFactory
    48.     'hr = SHCreateItemFromIDList(FilePidl, IID_IShellItemImageFactory, ISIIF)
    49.     'hr = ISIIF.GetImage(tSize.cx, tSize.cy, SIIGBF_THUMBNAILONLY, hBmp)
    50.        
    51.     'GetThumbnailImage = hBmp
    52.  
    53.     CoTaskMemFree (Pidl)
    54.     CoTaskMemFree (FilePidl)
    55.  
    56. End Function

    vb Code:
    1. Private Sub Command1_Click()
    2.     Dim hBmp As Long
    3.     Dim hImgList As Long
    4.    
    5.     hBmp = GetThumbnailImage(Environ("userprofile"), 120, 120)
    6.     hImgList = ImageList_Create(120, 120, ILC_COLOR32 Or ILC_MASK, 0, 0)
    7.     Call ImageList_Add(hImgList, hBmp, 0)
    8.     ImageList_Draw hImgList, 0, Me.hdc, 0, 0, ILD_TRANSPARENT
    9.    
    10.     DeleteObject hBmp
    11. End Sub

    I clarify, my intention is to obtain the thumbnails, not the icon
    Last edited by LeandroA; Jan 29th, 2017 at 10:45 PM.
    leandroascierto.com Visual Basic 6 projects

  2. #2

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2008
    Location
    Argentina
    Posts
    441

    Re: IExtractImage

    looking the Fafalone projects, I found the method used with IShellItemImageFactory by using the api ILCreateFromPathW

    vb Code:
    1. lPid = ILCreateFromPathW(StrPtr(sFilePath))
    2.     CLSIDFromString StrPtr("{BCC18B79-BA16-442F-80C4-8A59C30C463B}"), IID_IShellItemImageFactory
    3.     hr = SHCreateItemFromIDList(lPid, IID_IShellItemImageFactory, ISIIF)
    4.     hr = ISIIF.GetImage(tSize.cx, tSize.cy, SIIGBF_THUMBNAILONLY, hBmp)
    5.     ILFree lPid

    So, I guess if (GetVersion And & HFF)> 5 use IShellItemImageFactory else IExtractImage correct?
    leandroascierto.com Visual Basic 6 projects

  3. #3
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,229

    Re: IExtractImage

    I think only experimentation and testing can give you an answer. Such is the life of Windows Shell programming.

  4. #4
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,667

    Re: IExtractImage

    Never noticed that issue before, but yeah I'm getting the same problem. It returns the interface, but then errors with 80004005 (-2147467259) when calling GetLocation.

    In the case of a folder, is there ever a circumstance where the thumbnail will differ from the system image list (which will show custom folder icons)? If you wanted to maximize compatibility you could also just do that on folders.
    Otherwise I'd say yeah do a version check and user a newer call like IShellItemImageFactory for Vista+

    Note that the behavior of requesting thumbnails from folders is highly variable across OS's. For me on Windows 7, IShellItemImageFactory won't return an image if you specifiy SIIGBF_THUMBNAILONLY for regular folders and folders with custom icons (i.e. all folders except for a very few that have actual thumbnails generated). The design is that if you don't specify an xxxONLY, then it will return the thumbnail first anyway, so it's ok to omit that flag. I just tested this to confirm, and it correctly showed a thumbnailed folder without a flag specified.

    PS- Don't use ILFree; always use CoTaskMemFree instead. Sorry if that was my mistake, I used it in a few places before someone corrected me.
    Last edited by fafalone; Feb 1st, 2017 at 12:35 AM.

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2008
    Location
    Argentina
    Posts
    441

    Re: IExtractImage

    Thanks Fafalone for your suggestions, I think this topic is already solved. Tomorrow I will ask another question in another post about the bmp obtained and convert it into GDI plus Image. I have some problems some images where they are reversed

    see you tomorrow
    leandroascierto.com Visual Basic 6 projects

  6. #6
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: IExtractImage

    Hi all,

    I am running the first code posted by LeandroA on windows 10 and the code seems to work only for rendering thumbnails of folders.

    It doesn't work for rendering file thumbnails... when I pass a file path instead of a folder path , I get error E_NOTIMPL = -2147467263.

    Any advice on this ?

    Regards.

  7. #7
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: IExtractImage

    Bump!

    In other words, is the IExtractImage interface not working on Win7 and Win10 ?

    Any assistance ?

    Regards.

  8. #8
    Member Dragokas's Avatar
    Join Date
    Aug 2015
    Location
    Ukraine on fire (country of slaves)
    Posts
    750

    Re: IExtractImage

    Quote Originally Posted by fafalone View Post
    PS- Don't use ILFree; always use CoTaskMemFree instead. Sorry if that was my mistake, I used it in a few places before someone corrected me.
    Sorry, I don't understand, why do you suggest to use CoTaskMemFree instead of ILFree here, when MSDN article is directly saying to use ILFree for ILCreateFromPathW.
    Can you, please, clarify it?

    EDIT. Ahh, np, found the answer in the notice for ILFree.
    Note When using Windows 2000 or later, use CoTaskMemFree rather than ILFree. ITEMIDLIST structures are always allocated with the Component Object Model (COM) task allocator on those platforms.
    Last edited by Dragokas; Jan 18th, 2021 at 11:31 AM.

  9. #9
    Fanatic Member
    Join Date
    Mar 2023
    Posts
    976

    Red face Re: IExtractImage

    Quote Originally Posted by fafalone View Post
    Never noticed that issue before, but yeah I'm getting the same problem. It returns the interface, but then errors with 80004005 (-2147467259) when calling GetLocation.

    In the case of a folder, is there ever a circumstance where the thumbnail will differ from the system image list (which will show custom folder icons)? If you wanted to maximize compatibility you could also just do that on folders.
    Otherwise I'd say yeah do a version check and user a newer call like IShellItemImageFactory for Vista+

    Note that the behavior of requesting thumbnails from folders is highly variable across OS's. For me on Windows 7, IShellItemImageFactory won't return an image if you specifiy SIIGBF_THUMBNAILONLY for regular folders and folders with custom icons (i.e. all folders except for a very few that have actual thumbnails generated). The design is that if you don't specify an xxxONLY, then it will return the thumbnail first anyway, so it's ok to omit that flag. I just tested this to confirm, and it correctly showed a thumbnailed folder without a flag specified.

    PS- Don't use ILFree; always use CoTaskMemFree instead. Sorry if that was my mistake, I used it in a few places before someone corrected me.

    Hello everyone! My first post here ever :-) I'm an oldie in vb6 programming and I started VB programming back in VB3 in ealy 90th long before I even heard of Type Libs and I-Interfaces ...I ended up with vb6 in 2008 when .Net took much space and I didn't really want to learn a new langugae again since I felt very confortable with VB6 as a "cool" language...however this matter I don´t getting any errors at all when using this interface via GetUIObjectOf.
    Everything is nice and smooth since I shall add the hbmp image extracted to the Imagelist (existing or new created). I always got -1 as a result when try to add this hbmp image to the imagelist created or to IImagelist class imported. Same error. Something wrong with the hbmp returned from the extract method? The Extract method differs a bit from Fafalone's TypeLib and the MSDN reference...regarding Fafalone hbmp = IExtractImage.Extract
    and MSDN shows pointer IExtractImage::Extract lphbm.
    Have Fafalone maybee made a error here in his TypeLib so the hbm-pointer gives wrong value in vb6? in comparison to the MSDN C++ version?

  10. #10
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,667

    Re: IExtractImage

    Type libraries allow for rewriting a last [out] argument as the return value instead. I'm not a fan of the technique, precisely because of the confusion it causes by not matching the documentation, but oleexp was forked from olelib and I didn't change existing instances of it so as to not break apps when moving to oleexp. You'll see it in numerous interfaces of oleexp that rewrite things like this, with none of the others having problems. Note the details of the issue: It works on files and folders in some versions of Windows, but fails *on folders* for Windows 7.

    For another example look at the common IOleWindow;

    By documentation,

    Code:
    HRESULT GetWindow(
      [out] HWND *phwnd
    );
    But in oleexp rewritten as

    Code:
        HRESULT GetWindow(
            [out, retval] long *phwnd);
    So it appears in VB 6 as GetWindow() As Long. This is valid so long as the 'HRESULT' is left in place and the retval attribute is used.

    This would break it:

    long GetWindow(void);

    I've been forced onto Windows 10 since this thread was last active, I should check out how it's behaving now. But your confusion is entirely justified on this point, and that's why I never used this style of rewriting final [out]s as returns (though I still don't want to break everyone's code by changing it).

    PS- Off topic but I feel obliged to mention for any old timers looking at VB6 again or just returning to online VB6 communities so might not know, there's now a proper, backwards compatible successor: twinBASIC. It supports x64 compiling, multithreading, defining interfaces in language, and a laundry list of other new language features like overloading and generics, while still being 100% backwards compatible so you don't need to use any of that at first. It's still in beta under development so not quite to 100% yet, but it's very close and runs a lot of existing VB6 apps of significant complexity, including UserControls). We dreamt of something like for so long after MS abandoned VB6 for .NET, and after so many others failed to get off the ground it's finally happening. New releases at https://github.com/twinbasic/twinbasic/releases.
    Last edited by fafalone; Oct 8th, 2023 at 10:56 PM.

  11. #11
    Fanatic Member
    Join Date
    Mar 2023
    Posts
    976

    Re: IExtractImage

    I did take another look a this problem and I think I have found the issue for the errors reported.
    I had the same issue as reported before my modification.

    Code:
    Public Function ShGetIExtractImage(ByVal pidlFolder As Long, ByRef pIEI As IExtractImage) As Long
      Dim hr As Long
      Dim pISF As IShellFolder
      Dim sBuff As String
      Dim pidlRelative As Long
      
      If pidlFolder = 0 Then Exit Function
      
      'The solution is to use the outgoing pidlrelative (in bold and red color) from this API istead of using the ingoing pidlFolder.
      hr = SHBindToParent(pidlFolder, IID_IShellFolder, pISF, pidlRelative)
      
      If hr = S_OK Then
        hr = pISF.GetUIObjectOf(0, 1, pidlRelative, IID_IExtractImage, 0&, pIEI)
        ShGetIExtractImage = hr
      Else
        ShGetIExtractImage = hr
      End If
    End Function
    
    Private Sub Command11_Click()
      Dim pidlFolder As Long
      Dim hBmp As Long
      Dim pIEI As IExtractImage
      Dim pIRT As IRunnableTask
      Dim sBuffer As String
      Dim lpSize As SIZE
      Dim hr As Long
      Dim lpLVBKI As tagLVBKIMAGE
      Dim lpRC As RECT
      
      
      pidlFolder = m_cShell32.GetPIDLFromPath(Text1.Text)
      
      hr = m_cShell32.ShGetIExtractImage(pidlFolder, pIEI)
      
      If hr = S_OK Then
        
        sBuffer = String(MAX_PATH, 0)
        
        GetClientRect g_hWndLV, lpRC
        
        With lpSize
            .cx = lpRC.Right - lpRC.Left
            .cy = lpRC.Bottom - lpRC.Top
        End With
      
        pIEI.GetLocation StrPtr(sBuffer), LenB(sBuffer), 0, lpSize, 32, IEIFLAG_QUALITY Or IEIFLAG_REFRESH Or IEIFLAG_SCREEN
      
        Debug.Print sBuffer
        
        hBmp = pIEI.Extract()
        
        With lpLVBKI
            .ulFlags = LVBKIF_SOURCE_HBITMAP Or LVBKIF_STYLE_NORMAL
            .hbm = hBmp
        End With
        SendMessage g_hWndLV, LVM_SETBKIMAGE, 0, ByVal VarPtr(lpLVBKI)
        DeleteObject hBmp
        Set pIEI = Nothing
        CoTaskMemFree pidlFolder
      End If
      
    End Sub
    In this thread the IShellFolder's BindToObject method is used and not the SHBindToParent API which provides the correct pidl.

    So I switched to use that API instead.

    Below is the MSDN documentation link.

    https://learn.microsoft.com/en-us/wi...shbindtoparent
    Attached Images Attached Images  

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width