[VB6] API Open With Dialog with enhanced functionality
All the methods I've seen for bringing up the Open With dialog use rundll32. But Windows Vista and above has a better option: the SHOpenWithDialog API call. This allows a number of different options in addition to modality. After searching, it seems no one has posted a VB6 implementation yet, so I thought others might like the idea of using this as much as I did.
*UPDATE: Flags were declared incorrectly; forgot &H.
Requirements: The API call is only available on Vista or higher.
Code:
Option Explicit
'Module: mOpenWith
'Version: 0.1
'Author: fafalone
'Purpose: Vista and above provides an API call for the Open With dialog, which offers more options
' than the previous typical method of using rundll
Public Declare Function SHOpenWithDialog Lib "shell32" (ByVal hWnd As Long, poainfo As OPENASINFO) As Long
Public Enum OPEN_AS_INFO_FLAGS
OAIF_ALLOW_REGISTRATION = &H1 'Enable the "always use this program" checkbox. If not passed, it will be disabled.
OAIF_REGISTER_EXT = &H2 'Do the registration after the user hits the OK button.
OAIF_EXEC = &H4 'Execute file after registering.
OAIF_FORCE_REGISTRATION = &H8 'Force the Always use this program checkbox to be checked. Typically, you won't use the OAIF_ALLOW_REGISTRATION flag when you pass this value.
OAIF_HIDE_REGISTRATION = &H20 'Introduced in Windows Vista. Hide the Always use this program checkbox. If this flag is specified, the OAIF_ALLOW_REGISTRATION and OAIF_FORCE_REGISTRATION flags will be ignored.
OAIF_URL_PROTOCOL = &H40 'Introduced in Windows Vista. The value for the extension that is passed is actually a protocol, so the Open With dialog box should show applications that are registered as capable of handling that protocol.
OAIF_FILE_IS_URI = &H80 'Introduced in Windows 8. The location pointed to by the pcszFile parameter is given as a URI.
End Enum
Public Type OPENASINFO
pcszFile As Long
pcszClass As Long 'file type description for registering the type with 'always open', if not set uses extension, as in 'XYZ File'
oafInFlags As OPEN_AS_INFO_FLAGS
End Type
Public Function OpenWith(sFile As String, lFlags As OPEN_AS_INFO_FLAGS, Optional hWndParent As Long, Optional sClass As String) As Long
Dim oai As OPENASINFO
oai.pcszFile = StrPtr(sFile)
oai.oafInFlags = lFlags
If sClass <> "" Then oai.pcszClass = StrPtr(sClass)
OpenWith = SHOpenWithDialog(hWndParent, oai)
End Function
The sample project attached contains a form that calls the OpenWith function.
OpenWith(sFile As String, lFlags As OPEN_AS_INFO_FLAGS, Optional hWndParent As Long, Optional sClass As String)
sFile - The file to be opened
lFlags - See the descriptions in the BAS; you'll usually want to include OAIF_EXEC to open the file afterwards, and OAIF_ALLOW_REGISTRATION to enable the 'always use this program' box.
hWndParent - You can specify an owner window (e.g. Form1.hWnd) and the dialog will be modal to that form (you can't click on anything on the form until the dialog closes).
sClass - You can optionally specify a file type description for registering the type for always open. If not specified, the file extension would be used (e.g. XYZ File).
Note: Since this is a Unicode function (it takes lpcwstr's, hence the need for strptr()), it should handle unicode file names and unicode path lengths without issue.
Last edited by fafalone; Oct 23rd, 2014 at 04:05 PM.
Re: [VB6] API Open With Dialog with enhanced functionality
I'm not sure why a program would ever need to do this since it is part of the Shell UI meant to be driven by the end user. Even then it's only for advanced users since you can easily break file associations pretty seriously by innocently interacting with it.
Your "implementation" appears to do nothing but call the function.
Re: [VB6] API Open With Dialog with enhanced functionality
Originally Posted by dilettante
I'm not sure why a program would ever need to do this since it is part of the Shell UI meant to be driven by the end user. Even then it's only for advanced users since you can easily break file associations pretty seriously by innocently interacting with it.
On this function you can pass flags that the registration will not be touched. So no harms in that case.
Re: [VB6] API Open With Dialog with enhanced functionality
Originally Posted by dilettante
What situations do you find this useful for?
In some projects of mine, I use ShellExecute to try to open a file with registered association, if any. If that API fails, then I launch an "Open With" dialog via run32dll.
Insomnia is just a byproduct of, "It can't be done"
Re: [VB6] API Open With Dialog with enhanced functionality
Originally Posted by dilettante
I'm not sure why a program would ever need to do this since it is part of the Shell UI meant to be driven by the end user. Even then it's only for advanced users since you can easily break file associations pretty seriously by innocently interacting with it.
Your "implementation" appears to do nothing but call the function.
What am I missing?
What situations do you find this useful for?
I despise the built-in file search, so I wrote my own search program. And sometimes I want to open a file with something other than the default program. Last night I was searching through the SDK for a particular IDL, and did the normal open, and realized VC 2010 had the default association whereas I wanted to open it with VC 2008 (I only have 2010 express, and 2008 is full edition) that particular time. Media files are another point. I almost always want the default associated player for MKV files; but for MKV's with untouched blurays I have to use a player I like less but can better handle a 30-40GB file. Regarding breaking things; that is why this method is superior: the rundll32 method not only has the box to permanently change the association enabled, but it's checked by default. The API allows it to be unchecked by default AND totally disabled or completely hidden.
And I apologize if "implementation" is the wrong word for what my code does. why don't I just delete it if it's so terrible.
Last edited by fafalone; Oct 13th, 2014 at 09:10 PM.
Re: [VB6] API Open With Dialog with enhanced functionality
Hey fafalone,
I think it's a great little call. You should probably but something like a bFileExists check in it though. It crashes my IDE if I call it with a non-existent file. I still think it's cool and can see some uses for it. Specifically, I have an application that does a great deal of manipulation and moving around of PDF and Movie files. I have the MPUI (with portable SMPlayer) embedded in my app for playing the movies. But occasionally, they want to actually edit them rather than just play them. Or occasionally, someone will want to play them with Windows Media Player rather than the built-in MPUI player.
In these cases, I usually pop out to a Windows Explorer that's already in the folder they're using (and there are 1000s of folders), and let them double-click whatever Movie they want. Or, some know how to right-click and then "Open With..." (possibly opening a movie with Camtasia or whatever). However, if I could pull that functionality back into my program (rather than opening Windows Explorer), they'd like it.
So again, Cool Beans.
EDIT: Just in case you'd like it, here's my bFileExists function:
Code:
Public Function bFileExists(fle As String) As Boolean
On Error GoTo FileExistsError
' If no error then something existed.
bFileExists = (GetAttr(fle) And vbDirectory) = 0
Exit Function
FileExistsError:
bFileExists = False
Exit Function
End Function
Re: [VB6] API Open With Dialog with enhanced functionality
I use the PathFileExistsW API; but my thinking was validating whether the file existed was something that would be done long before opening the dialog about it.
If all you need is Open With then this will work- but you might want to look into IContextMenu, that lets you bring up the full Explorer right-click menu right in your application. It's pretty cool; it even sends a WM_MENUSELECT message and a GetCommandString function so you can show the tips like in Explorer.
Last edited by fafalone; Oct 23rd, 2014 at 12:32 PM.
Re: [VB6] API Open With Dialog with enhanced functionality
What you mean the icon displayed for a document in the dialog? Yes, there's many, many different ways to get the icon for a file type, search for e.g. SHGetFileInfo, you can pass just an extension rather than a specific file.