Click here to Skip to main content
15,885,366 members
Articles / Programming Languages / C#

A .NET Wizard control

Rate me:
Please Sign up or sign in to vote.
4.86/5 (89 votes)
24 Apr 2003CPOL7 min read 660.3K   8.7K   216  
A .NET Wizard control for the VS.IDE and client apps
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.ComponentModel;

using UtilityLibrary.Win32;


namespace UtilityLibrary.Dialogs
{
  [ ToolboxItem( true ),
  ToolboxBitmap( typeof( UtilityLibrary.Dialogs.FolderSelectDialog ), 
    "UtilityLibrary.Dialogs.FolderSelectDialog.bmp" ) ]
  public class FolderSelectDialog : CommonDialog
  {
    #region Class constants
    private const string DEF_TITLE_TEXT = "Please Select Folder";
    #endregion

    #region Class members
    private bool m_bBrowseForComputer;
    private bool m_bBrowseForPrinter;
    private bool m_bIncludeFiles;
    private bool m_bIncludeUrls;
    private bool m_bDontGoBelowDomain;
    private bool m_bEditBox;
    private bool m_bNewDialogStyle;
    private bool m_bNoNewFolderButton;
    private bool m_bNoTranslateTargets;
    private bool m_bReturnOnlyFileSystemAncestors;
    private bool m_bReturnOnlyFileSystemDirs;
    private bool m_bShareable;
    private bool m_bStatusText;
    private bool m_bUsageHint;
    private bool m_bUseNewUI;
    private bool m_bValidate;

    private string m_sTitle = DEF_TITLE_TEXT;
    private string m_sFullName;
    #endregion
    
    #region Class Properties
    /// <summary>
    /// Path, that was selected
    /// </summary>
    [Browsable( false )]
    public string ResultPath
    {
      get
      {
        return m_sFullName;
      }
    }
    
    /// <summary>
    /// Title of the window, that will be shown
    /// </summary>
    [ Category( "Appearance" ), 
    DefaultValue( DEF_TITLE_TEXT ), 
    Description( "GET/SET Dialog`s title text." ) ]
    public string Title
    {
      get
      {
        return m_sTitle;
      }
      set
      {
        if ( value != m_sTitle )
        {
          m_sTitle = value;
        }
      }
    }
    
    /// <summary> 
    ///Only return computers. If the user selects anything other than a computer,
    /// the OK button is grayed. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Only return computers. If the user selects anything other than a computer, the OK button is grayed." ) ]
    public bool BrowseForComputer
    {
      get
      {
        return m_bBrowseForComputer;
      }
      set
      {
        if ( value != m_bBrowseForComputer )
        {
          m_bBrowseForComputer = value;
        }
      }
    }

    /// <summary> 
    ///Only return printers. If the user selects anything other than a printer, the
    /// OK button is grayed.</summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Only return printers. If the user selects anything other than a printer, the OK button is grayed." ) ]
    public bool BrowseForPrinter
    {
      get
      {
        return m_bBrowseForPrinter;
      }
      set
      {
        if ( value!= m_bBrowseForPrinter)
        {
          m_bBrowseForPrinter = value;
        }
      }
    }

    /// <summary> The browse dialog box will display files as well as folders.
    /// </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "The browse dialog box will display files as well as folders." ) ]
    public bool IncludeFiles
    {
      get
      {
        return m_bIncludeFiles;
      }
      set
      {
        if ( value != m_bIncludeFiles )
        {
          m_bIncludeFiles = value;
        }
      }
    }

    /// <summary> 
    /// The browse dialog box can display URLs. The BIF_USENEWUI and
    /// BIF_BROWSEINCLUDEFILES flags must also be set. If these three flags are not
    /// set, the browser dialog box will reject URLs. Even when these flags are set,
    /// the browse dialog box will only display URLs if the folder that contains the 
    /// selected item supports them. When the folder's IShellFolder::GetAttributesOf
    /// method is called to request the selected item's attributes, the folder must
    /// set the SFGAO_FOLDER attribute flag. Otherwise, the browse dialog box will
    /// not display the URL. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "The browse folder dialog box can display URLs." ) ]
    public bool IncludeUrls
    {
      get
      {
        return m_bIncludeUrls;
      }
      set
      {
        if ( value != m_bIncludeUrls )
        {
          m_bIncludeUrls = value;
        }
      }
    }

    /// <summary> Do not include network folders below the domain level in the 
    /// dialog box's tree view control. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Do not include network folders below the domain level in the dialog box's tree view control." ) ]
    public bool DontGoBelowDomain
    {
      get
      {
        return m_bDontGoBelowDomain;
      }
      set
      {
        if ( value != m_bDontGoBelowDomain )
        {
          m_bDontGoBelowDomain = value;

        }
      }
    }

    /// <summary> Include an edit control in the browse dialog box that allows the 
    /// user to type the name of an item. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Include an edit control in the browse dialog box that allows the user to type the name of an item." ) ]
    public bool EditBox
    {
      get
      {
        return m_bEditBox;
      }
      set
      {
        if ( value != m_bEditBox )
        {
          m_bEditBox = value;
        }
      }
    }

    /// <summary> Use the new user interface. Setting this flag provides the user 
    /// with a larger dialog box that can be resized. The dialog box has several new 
    /// capabilities including: drag and drop capability within the dialog box, 
    /// reordering, shortcut menus, new folders, delete, and other shortcut menu 
    /// commands. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Use the new user interface." ) ]
    public bool NewDialogStyle
    {
      get
      {
        return m_bNewDialogStyle;
      }
      set
      {
        if ( value != m_bNewDialogStyle )
        {
          m_bNewDialogStyle = value;
        }
      }
    }

    /// <summary> Do not include the New Folder button in the browse dialog box.
    /// </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Do not include the New Folder button in the browse dialog box." ) ]
    public bool NoNewFolderButton
    {
      get
      {
        return m_bNoNewFolderButton;
      }
      set
      {
        if ( value != m_bNoNewFolderButton )
        {
          m_bNoNewFolderButton = value;
        }
      }
    }

    /// <summary> When the selected item is a shortcut, return the PIDL of the 
    /// shortcut itself rather than its target. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "When the selected item is a shortcut, return the PIDL of the shortcut itself rather than its target." ) ]
    public bool NoTranslateTargets
    {
      get
      {
        return m_bNoTranslateTargets;
      }
      set
      {
        if ( value != m_bNoTranslateTargets )
        {
          m_bNoTranslateTargets = value;
        }
      }
    }

    /// <summary> Only return file system ancestors. An ancestor is a subfolder that 
    /// is beneath the root folder in the namespace hierarchy. If the user selects an 
    /// ancestor of the root folder that is not part of the file system, the OK button 
    /// is grayed. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Only return file system ancestors." ) ]
    public bool ReturnOnlyFileSystemAncestors
    {
      get
      {
        return m_bReturnOnlyFileSystemAncestors;

      }
      set
      {
        if ( value != m_bReturnOnlyFileSystemAncestors ) 
        {
          m_bReturnOnlyFileSystemAncestors = value;
        }
      }
    }

    /// <summary> Only return file system directories. If the user selects folders 
    /// that are not part of the file system, the OK button is grayed. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Only return file system directories." ) ]
    public bool ReturnOnlyFileSystemDirs
    {
      get
      {
        return m_bReturnOnlyFileSystemDirs;
      }
      set
      {
        if ( value != m_bReturnOnlyFileSystemDirs )
        {
          m_bReturnOnlyFileSystemDirs = value;
        }
      }
    }

    /// <summary> The browse dialog box can display shareable resources on remote 
    /// systems. It is intended for applications that want to expose remote shares on a 
    /// local system. The BIF_USENEWUI flag must also be set. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "The browse dialog box can display shareable resources on remote systems." ) ]
    public bool Shareable
    {
      get
      {
        return m_bShareable;
      }
      set
      {
        if ( value != m_bShareable )
        {
          m_bShareable = value;
        }
      }
    }

    /// <summary> Include a status area in the dialog box. The callback function can 
    /// set the status text by sending messages to the dialog box. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Include a status area in the dialog box." ) ]
    public bool StatusText
    {
      get
      {
        return m_bStatusText;
      }
      set
      {
        if ( value != m_bStatusText )
        {
          m_bStatusText = value;
        }
      }
    }

    /// <summary> When combined with BIF_NEWDIALOGSTYLE, adds a usage hint to the 
    /// dialog box in place of the edit box. BIF_EDITBOX overrides this flag. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Show usage hint." ) ]
    public bool UsageHint
    {
      get
      {
        return m_bUsageHint;
      }
      set
      {
        if ( value != m_bUsageHint )
        {
          m_bUsageHint = value;
        }
      }
    }

    /// <summary> Use the new user interface, including an edit box. This flag is 
    /// equivalent to BIF_EDITBOX | BIF_NEWDIALOGSTYLE. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "Use the new user interface, including an edit box." ) ]
    public bool UseNewUI
    {
      get
      {
        return m_bUseNewUI;
      }
      set
      {
        if ( value != m_bUseNewUI )
        {
          m_bUseNewUI = value;
        }
      }
    }

    /// <summary> If the user types an invalid name into the edit box, the browse 
    /// dialog box will call the application's BrowseCallbackProc with the 
    /// BFFM_VALIDATEFAILED message. This flag is ignored if BIF_EDITBOX is not 
    /// specified. </summary>
    [ Category( "Behavior" ), 
    DefaultValue( false ), 
    Description( "If the user types an invalid name into the edit box, the browse dialog box will call the application's BrowseCallbackProc with the BFFM_VALIDATEFAILED message." ) ]
    public bool Validate
    {
      get
      {
        return m_bValidate;
      }
      set
      {
        if ( value != m_bValidate )
        {
          m_bValidate = value;
        }
      }
    }
    #endregion
                                      
    #region Class Controls
    private System.ComponentModel.Container components = null;
    #endregion

    #region Class Initialization/Finalization
    public FolderSelectDialog(System.ComponentModel.IContainer container)
    {
      container.Add( this );
      InitializeComponent();
    }

    public FolderSelectDialog()
    {
      InitializeComponent();
    }
    #endregion

    #region Component Designer generated code
    private void InitializeComponent()
    {
      components = new System.ComponentModel.Container();
    }
    #endregion

    #region Class Functions
    private UInt32 GetFlagsValue()
    {
      UInt32 flags = 0;

      if( BrowseForComputer )             flags |= (uint)BrowseInfoFlag.BIF_BROWSEFORCOMPUTER;
      if( BrowseForPrinter )              flags |= (uint)BrowseInfoFlag.BIF_BROWSEFORPRINTER;
      if( IncludeFiles )                  flags |= (uint)BrowseInfoFlag.BIF_BROWSEINCLUDEFILES;
      if( IncludeUrls )                   flags |= (uint)BrowseInfoFlag.BIF_BROWSEINCLUDEURLS;
      if( DontGoBelowDomain )             flags |= (uint)BrowseInfoFlag.BIF_DONTGOBELOWDOMAIN;
      if( EditBox )                       flags |= (uint)BrowseInfoFlag.BIF_EDITBOX;
      if( NewDialogStyle )                flags |= (uint)BrowseInfoFlag.BIF_NEWDIALOGSTYLE;
      if( NoNewFolderButton )             flags |= (uint)BrowseInfoFlag.BIF_NONEWFOLDERBUTTON;
      if( NoTranslateTargets )            flags |= (uint)BrowseInfoFlag.BIF_NOTRANSLATETARGETS;
      if( ReturnOnlyFileSystemAncestors ) flags |= (uint)BrowseInfoFlag.BIF_RETURNFSANCESTORS;
      if( ReturnOnlyFileSystemDirs )      flags |= (uint)BrowseInfoFlag.BIF_RETURNONLYFSDIRS;
      if( Shareable )                     flags |= (uint)BrowseInfoFlag.BIF_SHAREABLE;
      if( StatusText )                    flags |= (uint)BrowseInfoFlag.BIF_STATUSTEXT;
      if( UsageHint )                     flags |= (uint)BrowseInfoFlag.BIF_UAHINT;
      if( UseNewUI )                      flags |= (uint)BrowseInfoFlag.BIF_USENEWUI;
      if( Validate )                      flags |= (uint)BrowseInfoFlag.BIF_VALIDATE;

      return flags;
    }
    
    private IShellFolder GetDesktopFolder()
    {
      IntPtr ptrRet;
      WindowsAPI.SHGetDesktopFolder( out ptrRet );

      System.Type shellFolderType = System.Type.GetType( "ShellLib.IShellFolder" );
      object obj = Marshal.GetTypedObjectForIUnknown( ptrRet, shellFolderType );
      IShellFolder ishellFolder = ( IShellFolder )obj;

      return ishellFolder;
    }
    
    private Int32 myBrowseCallbackProc(IntPtr hwnd, UInt32 uMsg, Int32 lParam, Int32 lpData)
    {
      return 0;
    }
    #endregion

    #region Class Overrides
    protected override bool RunDialog( System.IntPtr hwndOwner )
    {
      string m_DisplayName = "";
      string sDisplay;
      IntPtr ptrRet;

      // Get IMalloc interface
      WindowsAPI.SHGetMalloc( out ptrRet );

      Type    mallocType = System.Type.GetType( "IMalloc" );
      IMalloc pMalloc = ( IMalloc )Marshal.GetTypedObjectForIUnknown( ptrRet, mallocType );
      IntPtr  pidlRoot = IntPtr.Zero;

      BROWSEINFO bi = new BROWSEINFO();
    
      bi.hwndOwner  = hwndOwner;    
      bi.pidlRoot   = pidlRoot;     //TODO: Root`s selection
      bi.pszDisplayName = new string( ' ', 256 );
      bi.lpszTitle  = Title;
      bi.ulFlags    = GetFlagsValue(); 
      bi.lParam     = 0;
      bi.lpfn       = new WindowsAPI.BrowseCallbackProc( this.HookProc );

      IntPtr pidlSelected;
      pidlSelected = WindowsAPI.SHBrowseForFolder( ref bi );
      m_DisplayName = bi.pszDisplayName.ToString();

      // if display name is whitespace then return FAIL
      if( m_DisplayName.Trim() == string.Empty ) return false;

      IShellFolder isf = GetDesktopFolder();

      STRRET ptrDisplayName;
      isf.GetDisplayNameOf( pidlSelected,
        (uint)SHGNO.SHGDN_NORMAL | (uint)SHGNO.SHGDN_FORPARSING,
        out ptrDisplayName );
    
      WindowsAPI.StrRetToBSTR( ref ptrDisplayName, pidlRoot, out sDisplay );
      m_sFullName = sDisplay;
      
      if( pidlRoot != IntPtr.Zero )
        pMalloc.Free( pidlRoot );
    
      if( pidlSelected != IntPtr.Zero )
        pMalloc.Free( pidlSelected );
    
      Marshal.ReleaseComObject( isf );
      Marshal.ReleaseComObject( pMalloc );
      
      return true;
    }

    public override void Reset()
    {
      m_bBrowseForComputer = false;
      m_bBrowseForPrinter = false;
      m_bIncludeFiles = false;
      m_bIncludeUrls = false;
      m_bDontGoBelowDomain = false;
      m_bEditBox = false;
      m_bNewDialogStyle = false;
      m_bNoNewFolderButton = false;
      m_bNoTranslateTargets = false;
      m_bReturnOnlyFileSystemAncestors = false;
      m_bReturnOnlyFileSystemDirs = false;
      m_bShareable = false;
      m_bStatusText = false;
      m_bUsageHint = false;
      m_bUseNewUI = false;
      m_bValidate = false;

      m_sTitle = DEF_TITLE_TEXT;
      m_sFullName = string.Empty;
    }
    
    #endregion

  }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
CEO ArtfulBits Inc.
Ukraine Ukraine
Name:Kucherenko Oleksandr

Born:September 20, 1979

Platforms: Win32, Linux; - well known and MS-DOS; Win16; OS/2 - old time not touched;

Hardware: IBM PC

Programming Languages: Assembler (for Intel 80386); Borland C/C++; Borland Pascal; Object Pascal; Borland C++Builder; Delphi; Perl; Java; Visual C++; Visual J++; UML; XML/XSL; C#; VB.NET; T-SQL; PL/SQL; and etc.

Development Environments: MS Visual Studio 2001-2008; MS Visual C++; Borland Delphi; Borland C++Builder; C/C++ any; Rational Rose; GDPro; Together and etc.

Libraries: STL, ATL, WTL, MFC, NuMega Driver Works, VCL; .NET 1.0, 1.1, 2.0, 3.5; and etc.

Technologies: Client/Server; COM; DirectX; DirectX Media; BDE; HTML/DHTML; ActiveX; Java Servlets; DCOM; COM+; ADO; CORBA; .NET; Windows Forms; GDI/GDI+; and etc.

Application Skills: Databases - design and maintain, support, programming; GUI Design; System Programming, Security; Business Software Development. Win/Web Services development and etc.

Comments and Discussions