Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1448

[VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handler

$
0
0
IPreviewHandler Example

Many file types have registered preview handlers, not just images. Typically documents, videos, fonts, music, even registry files, all have a preview handler that you can put on your application with little effort.

Compatibility
The current sample project won't run on XP, but if you replace the IFileDialog file selection dialog and possibly a few other things, the core IPreviewHandler interface was available in XP.

Requirements
Requires a reference to oleexp3.tlb or higher.

-------------------------------

The registry holds registered preview handlers in the HKEY_CLASSES_ROOT\filetype\ShellEx\{8895b1c6-b41f-4c1c-a562-0d564250836f} key, but as a shortcut you can also use the AssocQueryString API with ASSOCSTR_SHELLEXTENSION as the sample project shows.

Here's the basic code to show a preview:
Code:

Private Sub ShowPreviewForFile(isi As IShellItem, hWnd As Long, rc As RECT)
'isi - an IShellItem representing the file (in example loaded from IFileDialog)
'hWnd - hWnd to show the preview on, typically a form, frame, or picturebox
'rc - A rectangle representing the area within the window to show the preview;
'      client-based so starts at 0
Dim iif As IInitializeWithFile
Dim iis As IInitializeWithStream
Dim iisi As IInitializeWithItem
Dim pUnk As oleexp3.IUnknown
Dim hr As Long
Dim sFile As String, sExt As String
Dim lp As Long
Dim tHandler As UUID
On Error GoTo e0

    isi.GetDisplayName SIGDN_FILESYSPATH, lp
    sFile = BStrFromLPWStr(lp)
    Debug.Print "sFile=" & sFile
    sExt = Right$(sFile, (Len(sFile) - InStrRev(sFile, ".")) + 1)
    Debug.Print "sExt=" & sExt

If sExt = "" Then Exit Sub

If (ipv Is Nothing) = False Then
    ipv.Unload
    Set ipv = Nothing
End If
If hGlobal Then GlobalFree hGlobal

hr = GetHandlerCLSID(sExt, tHandler)
If hr = 1 Then
    Debug.Print "Got handler CLSID; attempting to create IPreviewHandler"
    hr = CoCreateInstance(tHandler, 0, CLSCTX_INPROC_SERVER Or CLSCTX_LOCAL_SERVER, IID_IPreviewHandler, ipv)
    If (ipv Is Nothing) Then
        Debug.Print "Failed to create IPreviewHandler interface, hr=" & hr
        Exit Sub
    End If
    'Set iisi = ipv 'this normally can be used in place of Set pUnk / .QueryInterface, but we need the HRESULT
    Set pUnk = ipv
    If pUnk.QueryInterface(IID_IInitializeWithItem, iisi) = S_OK Then
        hr = iisi.Initialize(isi, STGM_READ)
        Debug.Print "iisi.init hr=" & hr
        GoTo gpvh
    Else
        Debug.Print "IInitializeWithItem not supported."
    End If
'    Set iif = ipv
    Set pUnk = ipv
    If pUnk.QueryInterface(IID_IInitializeWithFile, iif) = S_OK Then
        hr = iif.Initialize(sFile, STGM_READ)
        GoTo gpvh
    Else
        Debug.Print "IInitializeWithFile not supported."
    End If

        'use IStream
        Dim hFile As Long
        Dim pstrm As IStream
        Dim lpGlobal As Long
        Dim dwSize As Long
        Debug.Print "Attempting to use IStream"
        hFile = CreateFile(sFile, FILE_READ_DATA, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, 0, 0)
        If hFile Then
            dwSize = GetFileSize(hFile, ByVal 0&)
            Debug.Print "Got file size=" & dwSize
            If dwSize = 0 Then Exit Sub
            hGlobal = GlobalAlloc(GPTR, dwSize)
            lpGlobal = GlobalLock(hGlobal)
            If lpGlobal Then
                Call ReadFile(hFile, ByVal lpGlobal, dwSize, dwSize, ByVal 0&)
                Call GlobalUnlock(hGlobal)
                Call CreateStreamOnHGlobal(hGlobal, 1, pstrm)
'                Set iis = ipv
                Set pUnk = ipv
                hr = pUnk.QueryInterface(IID_IInitializeWithStream, iis)
                Debug.Print "QI.hr=" & hr
                If (iis Is Nothing) Then
                    Debug.Print "IInitializeWithStream not supported."
                    Call CloseHandle(hFile)
                    GoTo out
                Else
                    hr = iis.Initialize(pstrm, STGM_READ)
                End If
            End If
           
            Call CloseHandle(hFile)

    End If
gpvh:
    hr = ipv.SetWindow(hWnd, rc)
    Debug.Print "SetWindow hr=" & hr
    hr = ipv.DoPreview()
    Debug.Print "DoPreview hr=" & hr
    isi.GetDisplayName SIGDN_NORMALDISPLAY, lp
    sFile = BStrFromLPWStr(lp)
    Label1.Caption = "DoPreview called for " & sFile
Else
    Label1.Caption = "Could not find registered preview handler for file type."
End If
out:

Set iisi = Nothing
Set iif = Nothing
Set iis = Nothing

On Error GoTo 0
Exit Sub

e0:
Debug.Print "ShowPreviewForFile.Error->" & Err.Description & " (" & Err.Number & ")"
End Sub

It's really simpler than it looks; the hard part it the initialization, a preview handler typically only supports 1 out of the 3 IInitialize__ interfaces, so we have to go through all of them, and IStream ones are too common to omit, and that's the only complex part.

It may vary from system to system, but plain images generally aren't supported with this method, but there's a large variety of ways to preview them.

----------------
Project based on Using Preview Handlers in Windows Vista
Attached Files

Viewing all articles
Browse latest Browse all 1448

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>