OpenFileDialog Component with preselect Thumbnails view, Details view etc.
An enhanced OpenFileDialog you can put into your Toolbox
If you're a graphics nut like me, the standard OpenFileDialog can be pretty irritating because it always opens in List view, when really you want Thumbnails view. So I wanted to make an OpenFileDialog where you can set the opening view to Thumbnails, Icons, Details or whatever, instead of having to change it every time you open it.
How it was made
It isn't possible to subclass the standard OpenFileDialog because it's NonInheritable. But I found an article on the Code Project where the author, Robert Rohde, had a clever idea. He found a way to intercept a message that the dialog passes to its owner form, and used information form that message to set the view mode. The snag is that you had to code everything on the Form itself, because the message concerned, WM_ENTERIDLE, is only detected by the WndProc sub on the form itself (and not by an IMessageFilter, for instance). This seemed rule out putting the method into a simple component you could just drag onto your form. But I found a way to do it.
My solution consists of two main parts. Firstly, there is a Class which inherits from IComponent. The component exposes its own version of the OpenFileDialog properties which you can set in the Forms Designer. It has an additional DefaultView property, which you use to set the opening view of the dialog. Like the original OpenFileDialog component, it also has ShowDialog method which returns a DialogResult.
The OFDForm is the second part. It's a Form which is called from the component's ShowDialog and it does most of the work. It has its own copy of the standard OpenFileDialog, which it displays, collects the results and then closes. At the same time, the form has a WndProc sub which picks up the WM_ENTERIDLE message and uses it to set the view to Thumbnails, Icons or whatever you chose using SendMessage. The OFD form is itself invisible: all you see is the Dialog. I made the form's Opacity = 0% and its size to 1*1 pixels because just hiding it wouldn't work (WndProc wouldn't fire).
The attachments contain the above two parts plus a toolbox icon.
How to build the project in Visual Studio
Use this if you want to study the code or modify it. I'll see if I can post the DLL to the Utilities forum so you can skip these steps.
1. Download the attachments below to a convenient folder.
2. Start a new Control Library project in Visual Studio.
3. Right-click on the project name in Solution Explorer, and select Add Existing Item ... Use this to add all the downloaded items.
4. Delete the default empty class.
5. Right-click on the project name in Solution Explorer and select Properties.
5a. On the Compile tab, browse for a folder where you want to store the DLL. That's where it will live if you put it in the Toolbox.
5b. On the References tab, make sure you have references to System.Drawing and System.Windows.Forms.
6. Right click on the bitmap (OpenFileDialogEx.bmpP in Solution Explorer. Check that its Build Action is set to Embedded Resource.
7. Build the Solution.
How to add the component to your toolbox
1. Open any Windows Forms project and view the Form.
2. Open the Toolbox and right click wherever you want to put the new comonent. Select Choose Items ...
3. Click the Browse button and browse to the folder where you have stored the DLL (step 5b above). Select it. The OpenFileDialogEx component should now appear in your Toolbox with the following icon: .
Now you can drag the component onto a form and set its properties in the same way as a normal OpenFileDialog. Except it now has a new DefaultView property. Alternatively you could use it in code like this, for example:
Code:
Using ofdx As New BBComponents.OpenFileDialogEx
If ofdx.ShowDialog = DialogResult.OK Then
zoomablepicturebox1.Image = Image.FromFile(ofdx.FileName)
End If
End Using
Comments and suggestions gladly received. BB
Last edited by boops boops; Jan 31st, 2011 at 08:22 PM.
Re: OpenFileDialog Component with preselect Thumbnails view, Details view etc.
Me again Paul, it's clear the article you linked to is a more sophisticated approach than mine. It's nice having a preview box, and who could complain about the lovely Sandra?
Perhaps I could provide a preview box using my presently "hidden" form. The purpose of the Native Window seems to be to provide a way of passing properties from the dialog to the form; I'll have to study that a bit.
Meanwhile, I'm not dissatisfied with my own component, even if it is a case of reinventing the wheel. I can drag the component from the Toolbox and use it exactly like a standard OpenFileDialong, but also rely on it opening in Thumbnails view. That's what I wanted. And it's pretty "lightweight" at just over 100 lines of code.
I should point out that it I have only tested the component on WinXPsp3 and that the Enum values may have to be different for Vista+. I found these values which could be added to the present Enum:
Code:
Extra Large Icons = &H704D
Large Icons = &H704F
Medium Icons = &H704E
Small Icons = &H7050
List = &H7051
Details = &H704B]
Tiles = &H704C
I dont know if Thumbnails remains unchanged at &H702D. I'd be interested to hear if anyone has the time to try these options out.
Finally, it seems the icon wasn't attached as intended. I'll try adding it to this message. Ah, there it is in preview. In Firefox you can right-click on it and choose Save As; no doubt other browsers offer something similar. Make sure the name of the file is the same as the Component Class + .bmp: OpenFileDialogEx.bmp. Also make sure you add it to the build project as an Embedded Resource (see post #1). Otherwise the icon won't appear in the toolbox, just a boring cogwheel.
BB
Last edited by boops boops; Feb 2nd, 2011 at 08:36 PM.
Reason: typos, and a catatonic ADSL connection
Re: OpenFileDialog Component with preselect Thumbnails view, Details view etc.
You seem to have all the tools I'd like to use
For this final 'nice to have' feature I'd like the thumbnail view as default in my app. So I followed the instructions and immediately after loading the .vb's I get an error message:
Originally Posted by My computer
Error 1 'DefaultView' is not a member of 'WindowsControlLibrary1.OpenFileDialogEx'.
Both files give me errors but I have to start somewhere. Seems my experience with VB.net 2008 is not enough to solve it so any help is appreciated.
ps. If you have a readymade .dll I can use, maybe I can skip all the bughunting?
Re: OpenFileDialog Component with preselect Thumbnails view, Details view etc.
I hadn't looked at this code since a year ago, since there were no reactions except from Paul who pointed out that there were more advanced equivalents elsewhere. So it took some puzzling to see what was going wrong.
In fact it's simple. I coded it in VisualBasic 2010 (Express). The only thing that won't compile properly in 2008 is the properties, because 2010 introduced a very convenient abbreviated syntax for standard properties.
For example, in VS 2010:
Code:
Public Property Filter As String
is an abbreviation for:
Code:
Private _Filter As String
Public Property Filter As String
Get
Return _Filter
End Get
Set(value As String)
_Filter = value
End Set
End Property
in 2008 and earlier.
If you want to use this component, you should replace all the single-line properties in OpenFileDialogEx.vb by full versions as above. Then it should build correctly in 2008.
Re: OpenFileDialog Component with preselect Thumbnails view, Details view etc.
Thank you, thank you, thank you.
It appeared to be my knowledge of .NET 2010 (non-existent until now) . I can't upgrade to that since it doesn't support .NET Compact Framework (which I use it mainly for).
Here's one happy chap who can now speed up the production-process with a fantastic application that can browse for images with a preview, zoom, pan, crop and combine them into one and automatically upload them to a specified server.
A few hours of intensive labour and the help from some fantastic .NET guru's a lot of time will be saved it the future.
Re: OpenFileDialog Component with preselect Thumbnails view, Details view etc.
Your Code has me inspired. I have completed your work with Events and all other propertys. And wonder it works now under Windows 7 without changes in WndProc and Interop. Its the old dialog view, but it works.
I have uploaded your old reworked code to a German Projectsite.
Re: OpenFileDialog Component with preselect Thumbnails view, Details view etc.
vb Code:
Imports System.Windows.Forms
Imports System.Drawing
Imports System.ComponentModel
'<ToolboxBitmap("OpenFileDialogEx.bmp")> _
Public Class OpenFileDialogEx
Inherits Component
''' <summary>
''' Der RückgabeWert des Dialogs
''' </summary>
''' <remarks></remarks>
Protected Friend Result As DialogResult
''' <summary>
''' Einige Punkte arbeiten nur unter Vista/Windows 7
''' </summary>
''' <remarks></remarks>
Public Enum Views
Icons = &H7029
List = &H702B
Details = &H702C
Tiles = &H702E
Thumbnails = &H702D
SmallIcons = &H7050 'Windows 7
MediumIcons = &H704E 'Windows 7
LargeIcons = &H704F 'Windows 7
ExtraLargeIcons = &H704D 'Windows 7
'List = &H7051 'Windows 7
'Details = &H704B 'Windows 7
'Tiles = &H704C 'Windows 7
End Enum
#Region "Sonstiges"
''' <summary>
''' Ruft einen Wert ab, der angibt, ob diese System.Windows.Forms.FileDialog-Instanz automatisch Darstellung und Verhalten aktualisieren soll, wenn Sie unter Windows Vista ausgeführt wird, oder legt diesen Wert fest.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks>Wenn dieses Property nicht gesetzt ist, egal ob true oder false, dann funktioniert es nicht unter Vista / Windows7</remarks>
<Description("Ruft einen Wert ab, der angibt, ob diese System.Windows.Forms.FileDialog-Instanz automatisch Darstellung und Verhalten aktualisieren soll, wenn Sie unter Windows Vista ausgeführt wird, oder legt diesen Wert fest."), _
DefaultValue(True)> _
Public Property AutoUpgradeEnabled As Boolean
#End Region
#Region "Verhalten"
<Description("Ruft einen Wert ab, der angibt, ob einem Dateinamen im Dialogfeld automatisch eine Erweiterung hinzugefügt wird, wenn der Benutzer keine Erweiterung angibt, oder legt diesen fest."), _
DefaultValue(True)> _
Public Property AddExtension As Boolean
<Description("Gibt an, ob eine Warnung angezeigt wird, wenn der Benutzer eine Datei anklickt, die nicht vorhanden ist."), _
DefaultValue(True)> _
Public Property CheckFileExist As Boolean
<Description("Überprüft ob der angegebene Pfad vorhanden ist bevor vom Dialog zurückgekehrt wird."), _
DefaultValue(True)> _
Public Property CheckPathExist As Boolean
<Description("Die Standartdateierweiterung. Wenn der Benutzer einen Dateinamen eingibt wird diese Erweiterung an die Datei angehängt sofern noch keine angegeben wurde."), _
DefaultValue("")> _
Public Property DefaultExt As String
<Description("Ruft einen Wert ab, der angibt, ob das Dialogfeld den Speicherort der Datei, auf die die Verknüpfung verweist, oder den Speicherort der Verknüpfung (.lnk) zurückgibt, oder legt diesen fest."), _
DefaultValue(True)> _
Public Property DereferenceLinks As Boolean
<Description("Steuert, ob mehrere Dateien im Dialogfeld ausgewählt werden können."), _
DefaultValue(False)> _
Public Property Multiselect As Boolean
<Description("Der Zustand des schreibgeschützten Kontrollkästchens im Dialog."), _
DefaultValue(False)> _
Public Property ReadOnlyChecked As Boolean
<Description("Steuert, ob das Dialogfeld das aktuelle Verzeichnis vor dem Schließen wiederherstellt."), _
DefaultValue(False)> _
Public Property RestoreDirectory As Boolean
<Description("Aktiviert die Schaltfläche Hilfe."), _
DefaultValue(False)> _
Public Property ShowHelp As Boolean
<Description("Steuert, ob das schreibgeschützte Kästchen im Dialogfeld angezeigt wird."), _
DefaultValue(False)> _
Public Property ShowReadOnly As Boolean
<Description("Ruft ab oder legt fest, ob das Dialogfeld Anzeige und Speichern von Dateien mit mehreren Dateinamenerweiterungen unterstützt."), _
DefaultValue(False)> _
Public Property SupportMultiDottedExtension As Boolean
<Description("Ruft einen Wert ab, der angibt, ob das Dialogfeld nur gültige Win32-Dateinamen akzeptiert, oder legt diesen fest."), _
DefaultValue(True)> _
Public Property ValidateNames As Boolean
<Description("Die im Dialogfeld angezeigten Filter z.B.: Images(*.jpg)|*.jpg|All Files|*.*"), _
DefaultValue("")> _
Public Property Filter As String
<Description("Ruft den Index des derzeit im Dateidialogfeld ausgewählten Filters ab oder legt diesen fest."), _
DefaultValue(0)> _
Public Property FilterIndex As Integer
<Description("Ruft eine Zeichenfolge ab, die den im Dateidialogfeld ausgewählten Dateinamen enthält, oder legt diese fest."), _
DefaultValue("")> _
Public Property FileName As String
'Privat
Private _FileNames As String()
<Description("Ruft die Dateinamen aller im Dialogfeld ausgewählten Dateien ab."), _
DefaultValue({""})> _
Public ReadOnly Property FileNames As String()
Get
If Multiselect Then
Return _FileNames
Else
Return {FileName}
End If
End Get
End Property
<Description("Ruft das Ausgangsverzeichnis ab, das im Dateidialogfeld angezeigt wird, oder legt dieses fest."), _
DefaultValue("")> _
Public Property InitialDirectory As String
<Description("Ruft den Titel des Dateidialogfelds ab oder legt diesen fest."), _
DefaultValue("Datei öffnen...")> _
Public Property Title As String
<Description("Standartansicht der Anzeige im Dialogfeld."), _
DefaultValue(Views.Thumbnails)> _
Public Property DefaultView As Views = Views.Thumbnails
#End Region
#Region "Events"
<Description("Tritt ein, wenn der Benutzer in einem Dateidialogfeld auf die Schaltfläche Öffnen oder Speichern klickt."), _
DefaultValue("")> _
Public Event FileOk(sender As System.Object, e As System.EventArgs)
<Description("Tritt ein, wenn der Benutzer in einem Standarddialogfeld auf die Hilfeschaltfläche klickt."), _
DefaultValue("")> _
Public Event HelpRequest(sender As System.Object, e As System.EventArgs)
#End Region
#Region "Protected Friend HelperSubs"
''' <summary>
''' Stellt eine Funktion bereit, um die schreibgeschützte Property FileNames zu füllen.
''' </summary>
''' <param name="values"></param>
''' <remarks></remarks>
Protected Friend Sub SetFileNames(values As String())
_FileNames = values
End Sub
''' <summary>
''' Auslösen des Events und durchreichen der Argumente
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Protected Friend Sub RaiseFileOK(sender As System.Object, e As System.EventArgs)
RaiseEvent FileOk(sender, e)
End Sub
''' <summary>
''' Auslösen des Events und durchreichen der Argumente
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Protected Friend Sub RaiseHelpRequest(sender As System.Object, e As System.EventArgs)
RaiseEvent HelpRequest(sender, e)
End Sub
#End Region
Public Function ShowDialog() As DialogResult
Using frm As New OFDForm(Me)
frm.ShowDialog()
End Using
Return Result
End Function
Public Function ShowDialog(value As Windows.Forms.IWin32Window) As DialogResult
Using frm As New OFDForm(Me, value)
frm.ShowDialog()
End Using
Return Result
End Function
End Class
vb Code:
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports System.Drawing
Imports System.ComponentModel
Friend Class OFDForm
Inherits Form
Private _Owner As OpenFileDialogEx
Private View As OpenFileDialogEx.Views
Private Once As Boolean
Private RealOwner As Windows.Forms.IWin32Window
Private WithEvents ofd As New OpenFileDialog
''' <summary>
''' Initialisiert eine Form und macht sie komplett unsichtbar. Zudem wird die Kommunikation mit der Elternklasse hergestellt.
Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, ByVal childAfter As IntPtr, ByVal lclassName As String, ByVal windowTitle As String) As IntPtr
Re: OpenFileDialog Component with preselect Thumbnails view, Details view etc.
Hi Sio_x,
Welcome to VB.Forums, and thank you for your kind words. You code looks like an interesting development on my initial efforts and I shall have to find time to give it the attention it deserves. I'm pleased you got it working on Win7 (which I don't have and I am not planning to get soon). I have not tried to develop my version further because it has been good enough for my own needs.
I notice that you use a NativeWindow rather than a form to handle the Windows messages, as in the CodeProject design which Paul linked to in post #2. My own idea of using a form should make it easy to add an image preview box, although I still have to try it. Adding previews of other file types e.g. docs could be a lot of work though.