Click here to Skip to main content
15,868,141 members
Articles / Desktop Programming / Windows Forms
Article

FileDialogExtender

Rate me:
Please Sign up or sign in to vote.
4.80/5 (40 votes)
4 Dec 2004CPOL3 min read 189K   1.8K   74   48
Describes an easy way to change the initial view state of the listview in the Open/SaveFileDialog.

Sample Image - article.jpg

Introduction

The .NET framework is in my opinion an impressive piece of work with many useful classes. But I think every developer has at least once faced the problem that a class or function doesn't exactly fit his needs. Normally, one would derive from it and extend the functionality. The OpenFileDialog and SaveFileDialog are sealed and thus there is no direct way of extending them. This article explains how you can extend them anyway without the need to make everything yourself.

Background

Once upon a time, in a country far far away...

... a customer had the request that in an OpenFileDialog - where he could open an image - the default view state of the contained listview should be the thumbnail view. No one in my company really thought about it, and so we just said: "No problem!".

After looking at the given dialog classes, I realized that this wasn't as easy as just setting the appropriate property. I searched the forums and several search engines, but all I could find was listings which showed how to create the dialogs directly via the Windows APIs which needed dozen of structs with dozen of fields and cryptic constants. This was just too much overhead for me just to change the initial view state. So I began to think about other solutions.

The idea which came to my mind was that the parent form somehow must get to know when and which modal dialog is displayed. So I wrote a form overriding the WndProc and traced the messages coming while opening a file dialog. After some minutes, I had the message I needed. It has the number 289 and fires in the message loop of the modal dialog. This message also contains the handle to the dialog. It is important that the dialog is fully created at this time, because otherwise the following steps wouldn't work.

Phew! No, I had the handle to the dialog and knew it was shown (I could just have looked at the screen to realize this). Now, I needed a way to change the style of the listview. So I started Spy++ and searched for the dialog (with the handle at hand, this was easy) and quickly found the child window which was containing the listview.

SampleImage - spy1.jpg

I opened the messages dialog of Spy++ and began changing the listview's view state, and after some filtering, I got the message which was changing the style. The appropriate parameters for the view types were also shown by Spy++.

SampleImage - spy2.jpg

Now, I just had to add two small API calls to change my dialog. I used FindWindowEx to search for the handle of the window holding the listview. After retrieving it, I called SendMessage to send the message delivered by Spy++ to the window.

Using the code

I tried to stuff everything into a component. The problem is that the only one who has access to WndProc of a System.Windows.Form is the form itself. Thus, the form that will show the file dialog needs to override WndProc and make a call to this component. The minimal code to show an extended dialog would be:

C#
public class TestForm : System.Windows.Forms.Form
{
    private System.Windows.Forms.Button _btnOpen;
    private FileDialogExtender _extender = 
        new FileDialogExtender();

    public TestForm()
    {
        this._btnOpen = 
            new System.Windows.Forms.Button();
        this._btnOpen.Location = 
            new System.Drawing.Point(8, 8);
        this._btnOpen.Name = "_btnOpen";
        this._btnOpen.Size = 
            new System.Drawing.Size(96, 23);
        this._btnOpen.Text = "Open";
        this._btnOpen.Click += 
            new System.EventHandler(this.ShowOpenDialog);
        this.Controls.Add(this._btnOpen);
        this.FormBorderStyle = 
            FormBorderStyle.FixedDialog;
        this.MaximizeBox = false;
        this.MinimizeBox = false;
        this.Name = "TestForm";
        this.Text = "Test";
    }

    [STAThread]
    static void Main() 
    {
        Application.Run(new TestForm());
    }

    private void ShowOpenDialog(object sender, 
        System.EventArgs e)
    {
        new OpenFileDialog().ShowDialog();
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        _extender.WndProc(ref m);
    }
}

A better sample project is included in one of the download links.

Points of Interest

I hope I could show you how you can extend system dialogs by finding the needed handles to remote control their behavior.

There is much more one could do this way without throwing away the benefits of using the managed dialog classes. As I have no further need for extensions, I will now leave it at this stage.

If anyone has an idea on how to achieve this functionality without overriding WndProc or adding other API calls or hooks, please let me know.

History

  • 2004-12-04 - Initial release.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRe: Using the FileDialog to select folders as well Pin
The_Mega_ZZTer15-Sep-05 10:09
The_Mega_ZZTer15-Sep-05 10:09 
AnswerRe: Using the FileDialog to select folders as well Pin
softplanner6-Dec-05 5:30
softplanner6-Dec-05 5:30 
GeneralRe: Using the FileDialog to select folders as well Pin
Eytan Herskovic24-Dec-05 21:21
Eytan Herskovic24-Dec-05 21:21 
GeneralRe: Using the FileDialog to select folders as well Pin
softplanner18-Oct-07 3:26
softplanner18-Oct-07 3:26 
QuestionOMG! What about using VB? Pin
DavidMLevine18-Feb-05 10:44
DavidMLevine18-Feb-05 10:44 
AnswerRe: OMG! What about using VB? Pin
Robert Rohde18-Feb-05 19:58
Robert Rohde18-Feb-05 19:58 
GeneralRe: OMG! What about using VB? Pin
tyrone hopes1-May-07 0:30
tyrone hopes1-May-07 0:30 
AnswerRe: OMG! What about using VB? Pin
Mungi4-Jun-05 1:44
Mungi4-Jun-05 1:44 
This may be some use to you. Code converted to vb.net
Imports System
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Public Class cDialogExtender
Public Enum DialogViewTypes
Icons = &H7029
List = &H702B
Details = &H702C
Thumbnails = &H7031
Tiles = &H702E
End Enum
Private Const WM_COMMAND As Integer = &H111
Private _lastDialogHandle As Integer = 0
Private _viewType As DialogViewTypes = DialogViewTypes.Thumbnails
Private _enabled As Boolean
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Integer, ByVal hWnd2 As Integer, ByVal lpsz1 As String, ByVal lpsz2 As String) As Integer

Public Sub New()
MyClass.New(DialogViewTypes.List, False)
End Sub

Public Sub New(ByVal viewType As DialogViewTypes)
MyClass.New(viewType, False)
End Sub

Public Sub New(ByVal viewType As DialogViewTypes, ByVal enabled As Boolean)
_viewType = viewType
Enabled = enabled
End Sub

Public Property DialogViewType() As DialogViewTypes
Get
Return _viewType
End Get
Set(ByVal Value As DialogViewTypes)
_viewType = value
End Set
End Property

Public Property Enabled() As Boolean
Get
Return _enabled
End Get
Set(ByVal Value As Boolean)
_enabled = value
End Set
End Property

Public Sub WndProc(ByRef m As Message)
If Not _enabled Then
Return
End If
If m.Msg = 289 Then
Dim dialogHandle As Integer = m.LParam.ToInt32
If Not (dialogHandle = _lastDialogHandle) Then
Dim listviewHandle As Integer = FindWindowEx(dialogHandle, 0, "SHELLDLL_DefView", "")
SendMessage(listviewHandle, WM_COMMAND, _viewType, 0)
_lastDialogHandle = dialogHandle
End If
End If
End Sub
End Class

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Usage
oExtender.DialogViewType = cDialogExtender.DialogViewTypes.Thumbnails
oExtender.Enabled = True
Call (New OpenFileDialog).ShowDialog()
End Sub
GeneralNew ThumbNail Code Pin
George084515-Dec-04 6:02
George084515-Dec-04 6:02 
GeneralRe: New ThumbNail Code Pin
Robert Rohde15-Dec-04 18:50
Robert Rohde15-Dec-04 18:50 
GeneralRe: New ThumbNail Code Pin
stancrm24-Apr-06 2:43
stancrm24-Apr-06 2:43 
GeneralGood , But ...Thumbnail doesn't work ! Pin
George084515-Dec-04 3:45
George084515-Dec-04 3:45 
GeneralRe: Good , But ...Thumbnail doesn't work ! Pin
stancrm25-Apr-06 0:58
stancrm25-Apr-06 0:58 
GeneralRe: Good , But ...Thumbnail doesn't work ! Pin
tianke200421-May-06 21:39
tianke200421-May-06 21:39 
GeneralRe: Good , But ...Thumbnail doesn't work ! Pin
stancrm21-May-06 21:41
stancrm21-May-06 21:41 
GeneralImpressive! Pin
Pete Goodsall9-Dec-04 6:24
Pete Goodsall9-Dec-04 6:24 
GeneralCongrats! Pin
Carl Mercier4-Dec-04 13:56
Carl Mercier4-Dec-04 13:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.