FolderBrowserDialog.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / FolderBrowserDialog.cs / 1305376 / FolderBrowserDialog.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Windows.Forms 
{ 
    using System;
    using System.IO; 
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing;
    using System.Drawing.Design; 
    using System.Diagnostics;
    using System.Runtime.InteropServices; 
    using System.Security.Permissions; 
    using System.Diagnostics.CodeAnalysis;
 
    /// 
    /// 
    ///    
    ///       Represents a common dialog box that allows the user to specify options for 
    ///       selecting a folder. This class cannot be inherited.
    ///     
    ///  
    [
    DefaultEvent("HelpRequest"), 
    DefaultProperty("SelectedPath"),
    Designer("System.Windows.Forms.Design.FolderBrowserDialogDesigner, " + AssemblyRef.SystemDesign),
    SRDescription(SR.DescriptionFolderBrowserDialog)
    ] 
    public sealed class FolderBrowserDialog : CommonDialog
    { 
        // Root node of the tree view. 
        private Environment.SpecialFolder rootFolder;
 
        // Description text to show.
        private string descriptionText;

        // Folder picked by the user. 
        private string selectedPath;
 
        // Show the 'New Folder' button? 
        private bool showNewFolderButton;
 
        // set to True when selectedPath is set after the dialog box returns
        // set to False when selectedPath is set via the SelectedPath property.
        // Warning! Be careful about race conditions when touching this variable.
        // This variable is determining if the PathDiscovery security check should 
        // be bypassed or not.
        private bool selectedPathNeedsCheck; 
 
        // Callback function for the folder browser dialog (see VSWhidbey 551866)
        private UnsafeNativeMethods.BrowseCallbackProc callback; 

        /// 
        /// 
        ///     
        ///       Initializes a new instance of the  class.
        ///     
        ///  
        public FolderBrowserDialog()
        { 
            Reset();
        }

        ///  
        /// 
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
        public new event EventHandler HelpRequest 
        {
            add 
            {
                base.HelpRequest += value;
            }
            remove 
            {
                base.HelpRequest -= value; 
            } 
        }
 
        /// 
        /// 
        ///     Determines if the 'New Folder' button should be exposed.
        ///  
        [
        Browsable(true), 
        DefaultValue(true), 
        Localizable(false),
        SRCategory(SR.CatFolderBrowsing), 
        SRDescription(SR.FolderBrowserDialogShowNewFolderButton)
        ]
        public bool ShowNewFolderButton
        { 
            get
            { 
                return showNewFolderButton; 
            }
            set 
            {
                showNewFolderButton = value;
            }
        } 

        ///  
        ///  
        ///     Gets the directory path of the folder the user picked.
        ///     Sets the directory path of the initial folder shown in the dialog box. 
        /// 
        [
        Browsable(true),
        DefaultValue(""), 
        Editor("System.Windows.Forms.Design.SelectedPathEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        Localizable(true), 
        SRCategory(SR.CatFolderBrowsing), 
        SRDescription(SR.FolderBrowserDialogSelectedPath)
        ] 
        /// SECREVIEW: ReviewImperativeSecurity
        ///   vulnerability to watch out for: A method uses imperative security and might be constructing the permission using state information or return values that can change while the demand is active.
        ///   reason for exclude: we want to protect when the dialog has been set by the user - this is directly set when in RunDialog
        [SuppressMessage("Microsoft.Security", "CA2103:ReviewImperativeSecurity")] 
        public string SelectedPath
        { 
            get 
            {
                if (selectedPath == null || selectedPath.Length == 0) 
                {
                    return selectedPath;
                }
 
                if (selectedPathNeedsCheck)
                { 
                    Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileIO(" + selectedPath + ") Demanded"); 
                    new FileIOPermission(FileIOPermissionAccess.PathDiscovery, selectedPath).Demand();
                } 
                return selectedPath;
            }
            set
            { 
                selectedPath = (value == null) ? String.Empty : value;
                selectedPathNeedsCheck = false; 
            } 
        }
 
        /// 
        /// 
        ///     Gets/sets the root node of the directory tree.
        ///  
        [
        Browsable(true), 
        DefaultValue(System.Environment.SpecialFolder.Desktop), 
        Localizable(false),
        SRCategory(SR.CatFolderBrowsing), 
        SRDescription(SR.FolderBrowserDialogRootFolder),
        TypeConverter(typeof(SpecialFolderEnumConverter))
        ]
        public System.Environment.SpecialFolder RootFolder 
        {
            get 
            { 
                return rootFolder;
            } 
            [SuppressMessage("Microsoft.Performance", "CA1803:AvoidCostlyCallsWherePossible")]
            set
            {
                // FXCop: 
                // leaving in Enum.IsDefined because this Enum is likely to grow and we dont own it.
                if (!Enum.IsDefined(typeof(System.Environment.SpecialFolder), value)) 
                { 
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(System.Environment.SpecialFolder));
                } 
                rootFolder = value;
            }
        }
 
        /// 
        ///  
        ///     
        ///       Gets or sets a description to show above the folders. Here you can provide instructions for
        ///       selecting a folder. 
        ///    
        /// 
        [
        Browsable(true), 
        DefaultValue(""),
        Localizable(true), 
        SRCategory(SR.CatFolderBrowsing), 
        SRDescription(SR.FolderBrowserDialogDescription)
        ] 
        public string Description
        {
            get
            { 
                return descriptionText;
            } 
            set 
            {
                descriptionText = (value == null) ? String.Empty : value; 
            }
        }

        ///  
        ///     Helper function that returns the IMalloc interface used by the shell.
        ///  
        private static UnsafeNativeMethods.IMalloc GetSHMalloc() 
        {
            UnsafeNativeMethods.IMalloc[] malloc = new UnsafeNativeMethods.IMalloc[1]; 
            UnsafeNativeMethods.Shell32.SHGetMalloc(malloc);
            return malloc[0];
        }
 
        /// 
        ///  
        ///     
        ///       Resets all properties to their default values.
        ///     
        /// 
        public override void Reset()
        {
            rootFolder = System.Environment.SpecialFolder.Desktop; 
            descriptionText = String.Empty;
            selectedPath = String.Empty; 
            selectedPathNeedsCheck = false; 
            showNewFolderButton = true;
        } 

        /// 
        /// 
        ///    Implements running of a folder browser dialog. 
        /// 
        protected override bool RunDialog(IntPtr hWndOwner) 
        { 
            IntPtr pidlRoot = IntPtr.Zero;
            bool returnValue = false; 

            UnsafeNativeMethods.Shell32.SHGetSpecialFolderLocation(hWndOwner, (int) rootFolder, ref pidlRoot);
            if (pidlRoot == IntPtr.Zero)
            { 
                UnsafeNativeMethods.Shell32.SHGetSpecialFolderLocation(hWndOwner, NativeMethods.CSIDL_DESKTOP, ref pidlRoot);
                if (pidlRoot == IntPtr.Zero) 
                { 
                    throw new InvalidOperationException(SR.GetString(SR.FolderBrowserDialogNoRootFolder));
                } 
            }

            int mergedOptions = unchecked( (int) (long)UnsafeNativeMethods.BrowseInfos.NewDialogStyle);
            if (!showNewFolderButton) 
            {
                mergedOptions += unchecked( (int) (long)UnsafeNativeMethods.BrowseInfos.HideNewFolderButton); 
            } 

            // The SHBrowserForFolder dialog is OLE/COM based, and documented as only being safe to use under the STA 
            // threading model if the BIF_NEWDIALOGSTYLE flag has been requested (which we always do in mergedOptions
            // above). So make sure OLE is initialized, and throw an exception if caller attempts to invoke dialog
            // under the MTA threading model (...dialog does appear under MTA, but is totally non-functional).
            if (Control.CheckForIllegalCrossThreadCalls && Application.OleRequired() != System.Threading.ApartmentState.STA) 
            {
                throw new System.Threading.ThreadStateException(SR.GetString(SR.DebuggingExceptionOnly, SR.GetString(SR.ThreadMustBeSTA))); 
            } 

            IntPtr pidlRet = IntPtr.Zero; 
            IntPtr pszDisplayName = IntPtr.Zero;
            IntPtr pszSelectedPath = IntPtr.Zero;

            try 
            {
                // Construct a BROWSEINFO 
                UnsafeNativeMethods.BROWSEINFO bi = new UnsafeNativeMethods.BROWSEINFO(); 

                pszDisplayName = Marshal.AllocHGlobal(NativeMethods.MAX_PATH * Marshal.SystemDefaultCharSize); 
                pszSelectedPath = Marshal.AllocHGlobal(NativeMethods.MAX_PATH * Marshal.SystemDefaultCharSize);
                this.callback = new UnsafeNativeMethods.BrowseCallbackProc(this.FolderBrowserDialog_BrowseCallbackProc);

                bi.pidlRoot = pidlRoot; 
                bi.hwndOwner = hWndOwner;
                bi.pszDisplayName = pszDisplayName; 
                bi.lpszTitle = descriptionText; 
                bi.ulFlags = mergedOptions;
                bi.lpfn = callback; 
                bi.lParam = IntPtr.Zero;
                bi.iImage = 0;

                // And show the dialog 
                pidlRet = UnsafeNativeMethods.Shell32.SHBrowseForFolder(bi);
 
                if (pidlRet != IntPtr.Zero) 
                {
                    // Then retrieve the path from the IDList 
                    UnsafeNativeMethods.Shell32.SHGetPathFromIDList(pidlRet, pszSelectedPath);

                    // set the flag to True before selectedPath is set to
                    // assure security check and avoid bogus race condition 
                    selectedPathNeedsCheck = true;
 
                    // Convert to a string 
                    selectedPath = Marshal.PtrToStringAuto(pszSelectedPath);
 
                    returnValue = true;
                }
            }
            finally 
            {
                UnsafeNativeMethods.CoTaskMemFree(pidlRoot); 
                if (pidlRet != IntPtr.Zero) 
                {
                    UnsafeNativeMethods.CoTaskMemFree(pidlRet); 
                }

                // Then free all the stuff we've allocated or the SH API gave us
                if (pszSelectedPath != IntPtr.Zero) 
                {
                    Marshal.FreeHGlobal(pszSelectedPath); 
                } 
                if (pszDisplayName != IntPtr.Zero)
                { 
                    Marshal.FreeHGlobal(pszDisplayName);
                }

                this.callback = null; 
            }
            return returnValue; 
        } 

        ///  
        ///    Callback function used to enable/disable the OK button,
        ///    and select the initial folder.
        /// 
        private int FolderBrowserDialog_BrowseCallbackProc(IntPtr hwnd, 
                                                           int msg,
                                                           IntPtr lParam, 
                                                           IntPtr lpData) 
        {
            switch (msg) 
            {
                case NativeMethods.BFFM_INITIALIZED:
                    // Indicates the browse dialog box has finished initializing. The lpData value is zero.
                    if (selectedPath.Length != 0) 
                    {
                        // Try to select the folder specified by selectedPath 
                        UnsafeNativeMethods.SendMessage(new HandleRef(null, hwnd), (int) NativeMethods.BFFM_SETSELECTION, 1, selectedPath); 
                    }
                    break; 
                case NativeMethods.BFFM_SELCHANGED:
                    // Indicates the selection has changed. The lpData parameter points to the item identifier list for the newly selected item.
                    IntPtr selectedPidl = lParam;
                    if (selectedPidl != IntPtr.Zero) 
                    {
                        IntPtr pszSelectedPath = Marshal.AllocHGlobal(NativeMethods.MAX_PATH * Marshal.SystemDefaultCharSize); 
                        // Try to retrieve the path from the IDList 
                        bool isFileSystemFolder = UnsafeNativeMethods.Shell32.SHGetPathFromIDList(selectedPidl, pszSelectedPath);
                        Marshal.FreeHGlobal(pszSelectedPath); 
                        UnsafeNativeMethods.SendMessage(new HandleRef(null, hwnd), (int) NativeMethods.BFFM_ENABLEOK, 0, isFileSystemFolder ? 1 : 0);
                    }
                    break;
            } 
            return 0;
        } 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK