[VB6] IPreviewHandler: Show non-image file previews from all reg'd preview handlers
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.
Project Updated: 03 Dec 2015
-With the original version of this project, font previews showed all black boxes. This is a bug in the Windows font previewer, and can be fixed by resetting the background with the IPreviewHandlerVisuals interface. NOTE: It's very hard to deal with installed fonts; they can't be selected via the open dialog, and can't be expressed as a shell item like even objects like the control panel or my computer can, so: To preview installed fonts, you'll have to manually enter the path to the font file (C:\Windows\Fonts\whatever.ttf) and click preview. Font files not located in \Windows\Fonts can be selected and previewed normally.
-The update also adds an icon preview function, just to show how to make a comprehensive previewer (like the existing image previews in the original, IPreviewHandler isn't used unless your system has a custom one installed).
-Reference to oleexp, v4.0 or higher. oleexp.tlb is required for the IDE only, you do not need to distribute it with a compiled program.
-oleexp addon mIID.bas - Found in the oleexp zip.
-Recently an issue was discovered where some preview handlers may require a manifest for Common Controls 6.0. So far only Outlook 2007 .msg files have this issue (probably related to their also being the only ones using the more modern IInitializeWithItem), but there may be others. See LaVolpe's excellent project for making manifests for your app.
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 and IPreviewHandlerVisuals interfaces was available in XP.
-------------------------------
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, objpic As Object, Optional sFileIn As String = "")
Dim iif As IInitializeWithFile
Dim iis As IInitializeWithStream
Dim iisi As IInitializeWithItem
Dim pVis As IPreviewHandlerVisuals
Dim pUnk As oleexp.IUnknown
Dim hr As Long
Dim sFile As String, sExt As String
Dim lp As Long
Dim tHandler As UUID
On Error GoTo e0
If (isi Is Nothing) Then
Debug.Print "no isi"
If sFileIn <> "" Then
sFile = sFileIn
End If
Else
Debug.Print "using isi"
isi.GetDisplayName SIGDN_FILESYSPATH, lp
sFile = BStrFromLPWStr(lp)
End If
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
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
' Set iif = 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"
' Set iis = ipv
Set pUnk = ipv
hr = pUnk.QueryInterface(IID_IInitializeWithStream, iis)
If (iis Is Nothing) Then
Debug.Print "IInitializeWithStream not supported."
Set pUnk = ipv
If pUnk.QueryInterface(IID_IInitializeWithItem, iisi) = S_OK Then
Debug.Print "IInitializeWithItem supported."
If (isi Is Nothing) = False Then
hr = iisi.Initialize(isi, STGM_READ)
GoTo gpvh
Else
Debug.Print "Don't have needed IShellItem."
End If
Else
Debug.Print "IInitializeWithItem not supported. No more initializers."
GoTo out
End If
Else
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)
hr = iis.Initialize(pstrm, STGM_READ)
End If
Call CloseHandle(hFile)
End If
End If
gpvh:
hr = ipv.SetWindow(hWnd, rc)
Debug.Print "SetWindow hr=" & hr
hr = ipv.DoPreview()
Debug.Print "DoPreview hr=" & hr
Dim piunk As oleexp.IUnknown
Set piunk = ipv
hr = piunk.QueryInterface(IID_IPreviewHandlerVisuals, pVis)
If (pVis Is Nothing) = False Then
Debug.Print "Handler implements IPreviewHandlerVisuals; setting bk color to white"
pVis.SetBackgroundColor &HFFFFFF
End If
If (isi Is Nothing) = False Then
isi.GetDisplayName SIGDN_NORMALDISPLAY, lp
sFile = BStrFromLPWStr(lp)
End If
Label1.Caption = "DoPreview called for " & sFile
Else
'images and videos aren't handled that way normally, so we'll do it another way
Debug.Print "No registered handler; trying alternate method for images..."
Dim lPcv As Long
lPcv = FilePtypeL(sExt)
Debug.Print "Perceived type=" & lPcv
If lPcv = PERCEIVED_TYPE_IMAGE Then
If Right$(sFile, 4) = ".ico" Then
'the below methods don't properly render icons transparent
'so we'll use a different method that does
If DoIcoPreview(sFile, objpic.hDC, 32) = -1 Then
GoTo gfthm
End If
objpic.Refresh
Label1.Caption = "Manually generated preview for icon."
GoTo out
Else
gfthm:
Dim hbm As Long
hbm = GetFileThumbnail(sFile, 0, objpic.ScaleWidth, objpic.ScaleHeight)
Debug.Print "hbm=" & hbm
objpic.Cls
hBitmapToPictureBox objpic, hbm
objpic.Refresh
Label1.Caption = "Manually generated preview for image."
End If
Else
Label1.Caption = "Could not find registered preview handler for file type."
End If
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.
UPDATE: The image file preview in the sample project won't work on XP, here's an alternative that will:
Code:
Public Declare Function SHCreateShellItem Lib "shell32" (ByVal pidlParent As Long, ByVal psfParent As Long, ByVal pidl As Long, ppsi As IShellItem) As Long
Public Function GetFileThumbnail2(sFile As String, pidlFQ As Long, CX As Long, CY As Long) As Long
'alternate method
Dim isi As IShellItem
Dim pidl As Long
Dim iei As IExtractImage
Dim hBmp As Long
Dim uThumbSize As oleexp.SIZE
uThumbSize.CX = CX
uThumbSize.CY = CY
Dim sRet As String
Dim uThumbFlags As IEIFlags
On Error GoTo e0
If pidlFQ Then
Call SHCreateShellItem(0&, 0&, pidlFQ, isi)
Else
pidl = ILCreateFromPathW(StrPtr(sFile))
Call SHCreateShellItem(0&, 0&, pidl, isi)
Call CoTaskMemFree(pidl) 'also a change that should have been made, had originally used ILFree, which shouldn't be used on Win2k+
End If
isi.BindToHandler ByVal 0&, BHID_ThumbnailHandler, IID_IExtractImage, iei
If (iei Is Nothing) Then
Debug.Print "GetFileThumbnail2.Failed to create IExtractImage"
Exit Function
End If
uThumbFlags = IEIFLAG_ORIGSIZE
sRet = String$(MAX_PATH, 0)
iei.GetLocation StrPtr(sRet), MAX_PATH, 0&, uThumbSize, 32, uThumbFlags
hBmp = iei.Extract()
GetFileThumbnail2 = hBmp
Set iei = Nothing
On Error GoTo 0
Exit Function
e0:
Debug.Print "GetFileThumbnail2.Error->" & Err.Description & " (" & Err.Number & ")"
End Function
'NOTE: The below are not needed if your project includes oleexp's mIID.bas
Public Function BHID_ThumbnailHandler() As UUID
'{0x7B2E650A, 0x8E20, 0x4F4A, 0xB0,0x9E, 0x65,0x97,0xAF,0xC7,0x2F,0xB0}
Static iid As UUID
If (iid.Data1 = 0) Then Call DEFINE_UUID(iid, &H7B2E650A, &H8E20, &H4F4A, &HB0, &H9E, &H65, &H97, &HAF, &HC7, &H2F, &HB0)
BHID_ThumbnailHandler = iid
End Function
Public Function IID_IExtractImage() As UUID
'{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}
Static iid As UUID
If (iid.Data1 = 0) Then Call DEFINE_UUID(iid, &HBB2E617C, CInt(&H920), CInt(&H11D1), &H9A, &HB, &H0, &HC0, &H4F, &HC2, &HD6, &HC1)
IID_IExtractImage = iid
End Function
UPDATE 1 July 2016 - As was pointed out below by Steve-N, SHCreateItemFromIDList is actually Vista+ too, image preview code in this post has been changed to use SHCreateShellItem instead, which MSDN states in available as of XP SP1.
UPDATE 24 Nov 2016 - Attached project and code in post updated to reference oleexp.tlb v4.0 or higher. Updates in post incorporated into project.
There's now a 64-bit compatible version of this project for twinBASIC!
In addition to 64bit support, I updated the code to work better with the crappy Adobe PDF handler while not breaking the crappy MS TXT Preview handler, and additionally fixed an issue where local server created objects escape the automatic DPI scaling applied to your dpi unaware app.These changes can be backported to VB6 with a little effort, but I haven't done so yet.
Last edited by fafalone; Jan 16th, 2024 at 10:02 AM.
Reason: Attached project updated to reference oleexp.tlb 4.0 or higher
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Tested your iPreviewHandler sample, by trying to preview truetype fonts. IPreviewHandler gets TTF filetype viewer CLSID OK, creates IPREVIEWHandler ok as well, but areas drawn by font, shows as totally black retangles.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
I'll look into it.. not sure what's going on. It's returning the correct CLSID that corresponds to Windows Font Previewer, and no errors are being raised. Might be tough to trace since it's a problem with drawing that's done by the preview handler rather than the host app, but I'll give it a shot.
Font Previewer (fontview.exe) draws the preview itself, and appears to be where the handler is hosted; it's not just hosting an instance of IPreviewHandler.
Just in case it was the VB picturebox's problem, I tried on a CreateWindowExW-created window in a manifested app and had the same problem.
Last edited by fafalone; Nov 27th, 2015 at 06:45 PM.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Maybe a CLS needed. CLS copy picture to image. Image is the showing buffer.So if we get black view then image not show the proper bitmap. I am writing from a tablet, I can't check the code above...here.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
I added a .Cls statement, with and without a following .Refresh, to no avail; the thing is it's not standard graphics drawing. All you do is specify an hWnd to the external handler. It doesn't even have to be a picturebox; you can specify your forms hwnd, a frame's hwnd, etc, and it will be drawn onto that.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
As for PDFs, the preview handler for that is notoriously unstable; people can't seem to get it to work in other languages either. There's not even much to work with, since it's the initial creation of IPreviewHandler that fails, with the oh-so-helpful 0x80004005 'Unspecific error' message.
Edit: For fonts, IPreviewHandlerVisuals did the trick, thanks for pointing me in that direction. It's a little odd as to why, but simply using its SetBackgroundColor method (set to white) makes the fonts show up; for ttf, otf, and fon files that I tested, both installed in \Windows\Fonts and not installed ones. Haven't a clue why this works, since the background already was white, and changing the text color isn't needed (although you can change that too if you want). I'll update the project in a little bit; need to see if there's any ramifications to calling it with other file types (and will have to update the main tlb since this interface wasn't already defined).
Last edited by fafalone; Dec 3rd, 2015 at 01:28 AM.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Project updated with font preview fix (must update tlb too).
Added after ipv.DoPreview()
Code:
Dim pVis As IPreviewHandlerVisuals
Dim piunk As oleexp3.IUnknown
Set piunk = ipv
hr = piunk.QueryInterface(IID_IPreviewHandlerVisuals, pVis)
If (pVis Is Nothing) = False Then
Debug.Print "Handler implements IPreviewHandlerVisuals; setting bk color to white"
pVis.SetBackgroundColor &HFFFFFF
End If
Last edited by fafalone; Dec 3rd, 2015 at 07:28 AM.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
ShowPreviewForFile subroutine throws an 'Object variable or With block variable not set 91' (error) in some computers (W7-64). Error does not happen all W7-64 machines, but only couple of.
Shows preview window and font face rendering in it OK, but throws an error. Not yet known what is causing that.
Tested running your sample in few machines. Running compiled executable, worked ok - also runs ok in computer which is used to compile source.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Throws an error after rendering the font? Or when you do something else afterwards? Or on different file?
If it's an IDE error you should be able to just comment out the On Error Goto e0 statement and get the line where it's occuring.
..I think I do recall an unusual bug like you described; but not after a successful preview. I remember something was returning S_OK for pUnk.QueryInterface(IID_IInitializeWithItem, iisi), but then right after that throwing an error saying iisi wasn't set. Actually, in production apps I've commented out the whole IInitializeWithItem section, as it's so rare that no other sample I've seen uses it, and no file I've seen actually supports it but not one of the others. Edit: Turns out Outlook .msg files actually do only support IInitializeWithItem. So leave it in, but put if after IStream; and don't validate with the hr; check if Is Nothing.
If it is after showing a font, refer to the installed fonts issue descibed in the main text. If you've selected an installed font, you can't get a valid IShellItem for it, and isi.GetDisplayName SIGDN_NORMALDISPLAY, lp could cause that error... there should be an Is Nothing check before that statement really; I'll update it tomorrow. To confirm that's the case, is it when dealing with fonts from \Windows\Fonts\, and if it works sometimes, is it possible not all machines have the underlying issue to begin with? (I'm on Win7x64 as well; will fire up a VM with 8 later too). And if the error is immediately after the font preview shows the correct preview without boxes, regardless of the cause that isi.GetDisplayName line is the only possible statement that could trigger that error, so the Is Nothing check will resolve it.
Last edited by fafalone; Dec 4th, 2015 at 11:17 PM.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Originally Posted by fafalone
As for PDFs, the preview handler for that is notoriously unstable; people can't seem to get it to work in other languages either. There's not even much to work with, since it's the initial creation of IPreviewHandler that fails, with the oh-so-helpful 0x80004005 'Unspecific error' message.
I don't see that error here, but still get crashes on various systems after PDF preview. One system uses the Adobe preview handler, the other the PDF-XChange preview handler. The crash happens after calling IPV.Unload, but not immediately but at the point when the handler's DLL gets unloaded, which is one or two minutes later (no idea what triggers this unloading, it just happens by itself -- you can watch it happen in Process Explorer).
So, something is wrong here. A notorious issue with PDF previews has always been the focus stealing. I tried to control the focus with IPV.QueryFocus() but to no avail. Currently out of ideas.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
I can't load the Adobe preview handler at all.. but are you saying both of those work, but just later crash when unloaded? Is it only if you manually invoke unload; what if you just let IPV go out of context/set it to nothing?
There's .SetFocus() too, and SetWindow... what if you set the window to 0 after the preview is already displayed? That might help with the crash too.
Will try PDF-XChange viewer on my system and see if I can reproduce the issue.
Edit: I'm unable to reproduce the error with PDF-XChange. That handler works without issue. So; OS version, product version, and if applicable more specific steps? (i previewed a pdf then exited the program; then also previewed a pdf then loaded a new file that used a different handler; then in a 3rd run previewed a pdf then previewed another pdf.. nothing caused a crash on Win7x64)
Edit2: The font black boxes were certainly a bizarre issue with an even more bizarre solution. Setting the bk color triggered something it shouldn't have. PDF-XChange's handler implements IPreviewHandlerVisuals as well; are you using the updated code that calls the SetBackgroundColor function, even if you want to keep it white? I have no idea how this might be preventing the crashes and it wouldn't make sense; but after it preventing black boxes it wouldn't surprise me if it helped here too
(and speaking of the new version; it forgoes using ANY GlobalFree call... that may be an issue as well in the older version since PDF-XChange's handler uses the IStream method)
Last edited by fafalone; Dec 4th, 2015 at 08:35 AM.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
OK, this is Win8.1. Here is the steps.
- Install PDF-Viewer 2.5.214.2 from PDF-XChange. (well, this is mine, probably other versions do as well)
- Compile your latest sample project IPreviewHandlerSampleV2 (native code, optimized for speed)
- Run Project1.exe and preview *one* PDF file.
- Now close the EXE (click X-button).
- In Task Manager you will see that it did not unload. This is a symptom of the problem.
- Now, when you do the same thing, but preview *two* (or more) PDF files, you can close the EXE and it will unload completely.
Note that I was not able to crash Project1.exe before unloading it. (Something in my own project is probably responsible for this crash; but I also get the crash-on-unload in my own project. I think it's all the same bug.)
Does this tell you anything? (I hope you can reproduce it.)
voxy
PS: I don't use the SetBackgroundColor code. No GlobalFree calls anywhere.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Now I was able to crash your sample project (compiled to EXE) just the same way as my own project.
- preview *one* PDF
- unload that preview using this code (you see the "Unload IPV" button I added to your sample in the screenshot):
Code:
Private Sub Command3_Click()
If (ipv Is Nothing) = False Then
ipv.Unload
Set ipv = Nothing
End If
End Sub
- finally put any other window to the foreground! The crash only happens if Project1.exe is a background window. (another hint that focus plays a role here)
- now wait 1-3 minutes doing nothing. At some point the window will become unresponsive and look like this:
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Originally Posted by fafalone
Throws an error after rendering the font?
After rendering font, visually all seems fine ie. renders font OK, but throws an error. Tried previewing non installed fonts, residing in network share, but able to reproduce also with installed fonts in same machine throwing error.
I will report back when some tests are made, with compiled program added some feedback to pinpoint code line causing error.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
@Tech99: Did you add the check to make sure it's not the isi.GetDisplayName line? No object code executes between that statement and a subsequent user action.
@voxy: Still not getting a crash or lingering processes. To me this suggests either the problem is elsewhere, or the same magic that resolved font black boxes is working here and you should add the IPreviewHandlerVisuals call (this was also available in XP so would not break that compatibility if that was a concern). I haven't tried with the older version you're using yet either though, theoretically could have been solved between your 2.5.214 and my 2.5.315.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Originally Posted by fafalone
@Tech99: Did you add the check to make sure it's not the isi.GetDisplayName line? No object code executes between that statement and a subsequent user action.
Not sure yet. I haven't been able to reproduce error since, in that user workstation. Rebooted that machine, in the beginning of testing and no error since.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
It's still a good idea to add the check; even if it's not the cause of your crashes, in case of unforseen issues that cause it to not be set.
You're using the default Windows Font Previewer right, not a 3rd party preview handler? Did you ever get the crash with a different file type?
Edit:
NOTE: I had to withdraw my earlier statement about removing IInitializeWithItem. Found out that Outlook .msg files support it, but not either of the other IInitialize's. I'm working on a general bugfix update that will do this, but in the mean time I recommend checking for it after both the others, and validating it If iisi Is Nothing instead of If hr = S_OK (as per the bug I described with it).
Last edited by fafalone; Dec 4th, 2015 at 11:31 PM.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Originally Posted by fafalone
@voxy: Still not getting a crash or lingering processes. To me this suggests either the problem is elsewhere, or the same magic that resolved font black boxes is working here and you should add the IPreviewHandlerVisuals call (this was also available in XP so would not break that compatibility if that was a concern). I haven't tried with the older version you're using yet either though, theoretically could have been solved between your 2.5.214 and my 2.5.315.
Bingo!!! Upgrading to 2.5.315 fixed it! Wonderful, thanks!
(And I don't care so much for bugs with Adobe. They are known to be buggy.)
Just for completeness: Before upgrading PDF-XChange I tried your suggestion with IPreviewHandlerVisuals, but it did not change anything.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Originally Posted by fafalone
It's still a good idea to add the check; even if it's not the cause of your crashes, in case of unforseen issues that cause it to not be set.
You're using the default Windows Font Previewer right, not a 3rd party preview handler? Did you ever get the crash with a different file type?
Yes, using standard Windows Font Previewer app (fontview.exe), tried couple of other filetypes - mostly bitmap formats (png, jpg, tif) seems to work ok.
However i changed your sample a bit, by adding resizing. Needed to remove frame1, for dynamic resizing to work.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Originally Posted by fafalone
I can't load the Adobe preview handler at all...
Same here.
Got handler CLSID; attempting to create IPreviewHandler
IInitializeWithFile not supported.
IInitializeWithItem not supported.
Attempting to use IStream
hr = pUnk.QueryInterface(IID_IInitializeWithStream, iis) returns -2147467259 as hr value.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Yup that's the base-10 of the 80004005 'unspecific error' code. I like the 3rd party previewer solution, Adobe sux anyway. There's FoxIt or somesuch too that has a preview handler that should work.
Wait.. if that's on QueryInterface, your call to CoCreateInstance succeeded in creating the preview handler at least then?
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Originally Posted by fafalone
Wait.. if that's on QueryInterface, your call to CoCreateInstance succeeded in creating the preview handler at least then?
Actually no, that was from machine where Adobe full featured Acrobat package was installed. Plain Adobe Reader DC (latest version) fails in CoCreateInstance.
GetHandlerCLSID succeeds for .pdf extension tHandler(CLSID/GUID) returned {DC6EFB56-9CFA-464D-8880-44885D7DC193} for Adobe Reader DC, but the CoCreateInstance fails with hresult -2147467259 value.
Code:
Public Function IID_IPreviewHandler() As UUID
'{8895b1c6-b41f-4c1c-a562-0d564250836f}
Static iid As UUID
If (iid.Data1 = 0) Then Call DEFINE_UUID(iid, &H8895B1C6, CInt(&HB41F), CInt(&H4C1C), &HA5, &H62, &HD, &H56, &H42, &H50, &H83, &H6F)
IID_IPreviewHandler = iid '<- this line takes quite long time to execute.
End Function
This is from Adobe staff from this April "Sorry for the trouble. We had to remove the thumbnail preview functionality from Acrobat and Reader DC for technical reasons. We know there are users who value it but certain design considerations forced us to make this change."
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
DC is what is on my system too, that appears to be the problem. I get that for whatever reason they removed the previewer from it, but it's just terrible programming to still register the handler and just fling errors instead of a message it's been removed or just removing the registration entirely. No wonder their products are gaping security holes with the World's Worst Updater.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
The PDF-XChange viewer me and voxy were talking about is free (have to grab just the viewer, the editor and others are just trials) and works well. There's also one called Foxit thats free and widely used. Both of these support IPreviewHandler well.
Last edited by fafalone; Dec 6th, 2015 at 08:46 AM.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Originally Posted by fafalone
The PDF-XChange viewer me and voxy were talking about is free (have to grab just the viewer, the editor and others are just trials) and works well. There's also one called Foxit thats free and widely used. Both of these support IPreviewHandler well.
I tested Foxit Reader PDF Printer. It produces poor quality of pdf file (Alpha lost). PDF Creator produces normal good quality pdf.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Using iPreviewHandlerSampleV2 and oleexp v3.3 on Windows 7 with Office 2007 I see an issue with saved Outlook email .msg files.
Previewing .msg files doesn't show any message body text. The message header is shown (Title, From, To and Date Sent) but not the actual message. No error occurs.
But when looking at Windows Explorer preview pane the full message text shows also.
It doesn't make any difference if the internal format of the .msg file is Plain Text, Rich Text or HTML.
I assume Windows Explorer uses iPreviewHandler, so I would have expected the same results.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Windows does it's own thing. IPreviewHandler is implemented and registered by the application, but Windows does a bunch of extra stuff, and there's little documentation about what to do. For example, there was zero documentation about the necessity of IPreviewHandlerVisuals to render fonts.
Can you post a sample file? I can plug it into a version with far more extensive debug output, since the problem doesn't appear with newer versions.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
I'll post a sample file when I am back in the office.
Meanwhile here is the debug output:-
Got handler CLSID; attempting to create IPreviewHandler
IInitializeWithFile not supported.
iisi.init hr=0
SetWindow hr=0
DoPreview hr=-2147467259
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
That's odd, DoPreview is throwing an error that's usually a crash (the hr should be 0 [S_OK] if successful), but then it's still showing a partial preview? And are you running the sample straight, or integrated into a project-- perhaps the preview rect is just cutting it off? Definitely need a sample file.. although I am concerned that even if the message was created by 2007, it would still be rendered by my newer version (2010).
Last edited by fafalone; Feb 10th, 2016 at 07:14 PM.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Yeah that makes sense.. I'll make a note about it in the requirements section, thanks for the report. I've been kinda presuming anyone modernizing their app with this kinda stuff would already be manifested, but I've never seen it required except for one other (IImageList/IImageList2)-- but MSDN documented that. But yet another undocumented requirement for IPreviewHandler.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
You mean from a FileListBox right? You could do something similar to what the 'Preview' button does, just with the file list instead of the textbox:
Code:
Dim psi As IShellItem
Dim rc As RECT
Dim pidl As Long
Dim sFile As String
sFile = Dir1.Path & "\" & File1.List(File1.ListIndex)
pidl = ILCreateFromPathW(StrPtr(sFile))
Call SHCreateItemFromIDList(pidl, IID_IShellItem, psi)
rc.Top = 16
rc.Bottom = (Picture1.Height / Screen.TwipsPerPixelY) - 16
rc.Left = 16
rc.Right = (Picture1.Width / Screen.TwipsPerPixelX) - 16
ShowPreviewForFile psi, Picture1.hWnd, rc, Picture1, sFile
Also in your picture you're selecting a JPG, which may not by default have an IPreviewHandler; the sample project has code that manually draws image file previews, so you'd have to make sure you had that part too.
Re: [VB6] IPreviewHandler: Show non-image file previews from any reg'd preview handle
Ah apparently so, good catch I thought it just required 6.0.
Fortunately it can be easily replaced with SHCreateShellItem, which MSDN says: "Minimum supported client Windows XP with SP1 [desktop apps only]"
Public Declare Function SHCreateShellItem Lib "shell32" (ByVal pidlParent As Long, ByVal psfParent As Long, ByVal pidl As Long, ppsi As IShellItem) As Long
I'll update it with the minor change:
Code:
If pidlFQ Then
Call SHCreateShellItem(0&, 0&, pidlFQ, isi)
Else
pidl = ILCreateFromPathW(StrPtr(sFile))
Call SHCreateShellItem(0&, 0&, pidl, isi)
Call CoTaskMemFree(pidl) 'also a change that should have been made
End If
Sorry I didn't find out about this earlier my XP diehards, and thanks for pointing this out Steve
Last edited by fafalone; Jul 1st, 2016 at 05:35 PM.
Admittedly this isn't a common configuration, but I don't have control over this. It isn't possible to change this in the short term.
The debug output from the sample program is as follows:
Code:
using isi
sFile=C:\Test\00000017.PDF
sExt=.PDF
Got handler CLSID; attempting to create IPreviewHandler
...and after a delay of over 1 minute...
Failed to create IPreviewHandler interface, hr=-2147467259
The configuration works fine in File Explorer and Outlook, PDFs can be previewed. In File Explorer you even get thumbnails of the first page of the PDF.
If I install say PDF-XChange viewer I can then preview PDFs, but unfortunately this isn't allowed.
I accept this is largely a problem created by Adobe, but because Explorer and Outlook can work with this configuration it should be possible to get the iPreviewHandler to work too.