How to implement a managed component that wraps the Browse For Folder common dialog box by using Visual Basic .NET or Visual Basic 2005 (811004)
The information in this article applies to:
- Microsoft Visual Basic .NET (2002)
- Microsoft Visual Basic .NET (2003)
- Microsoft Visual Basic 2005
For a Microsoft Visual C# .NET version of this
article, see
306285. This article refers to the following
Microsoft .NET Framework Class Library namespaces:
- System.Runtime.InteropServices
- System.Text
- System.Security.Permissions
The
following file is available for download from the Microsoft Download
Center: Release Date:
12-12-2002 For additional information about how to download Microsoft
Support files, click the following article number to view the article in the
Microsoft Knowledge Base: 119591 How to Obtain Microsoft Support Files from Online Services
Microsoft scanned this file for viruses. Microsoft used the most
current virus-detection software that was available on the date that the file
was posted. The file is stored on security-enhanced servers that help to
prevent any unauthorized changes to the file.
Microsoft scanned this file for viruses. Microsoft
used the most current virus-detection software that was available on the date
that the file was posted. The file is stored on secure servers that prevent any
unauthorized changes to the file. IN THIS TASKSUMMARYThis
step-by-step article describes how to write a design time component that wraps
the Browse For Folder common dialog box. Implement the Design-Time Component- Generate an empty project. To do this, create a new blank
solution and name it BrowseForFolder. Add a new Visual
Basic .NET or Visual Basic 2005 Class Library project to the newly-created solution, and name the
project WinFormsExtras.
- Modify the wizard-generated code. To do this, rename the
Class1.vb file from the project FolderBrowser.vb, and
then delete the Class1 class that the wizard adds to this
file. Rename the namespace from WinFormsExtra.cs
(WinFormsExtras) to Microsoft.Samples.WinForms.Extras.
On the project's Properties pages, rename the default namespace from
WinFormsExtras to
Microsoft.Samples.WinForms.Extras. Change the assembly
name from WinFormsExtras to
Microsoft.Samples.WinForms.Extras.
- Add the declarations for P/Invoke and
ComInterop. Make sure that
System.Runtime.InteropServices and System.Text
are referenced, and then provide declarations for the functions and
interfaces, as follows:
Imports System.Runtime.InteropServices
Imports System.Text
Class Win32API
'Visual Basic representation of the IMalloc interface.
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000002-0000-0000-C000-000000000046")> _
Interface IMalloc
<PreserveSig()> Function Alloc(ByVal cb As Integer) As IntPtr
<PreserveSig()> Function Realloc(ByVal pv As IntPtr, ByVal cb As Integer) As IntPtr
<PreserveSig()> Sub Free(ByVal pv As IntPtr)
<PreserveSig()> Function GetSize(ByVal pv As IntPtr) As Integer
<PreserveSig()> Function DidAlloc(ByVal pv As IntPtr) As Integer
<PreserveSig()> Sub HeapMinimize()
End Interface
Public Declare Function GetActiveWindow Lib "user32" Alias "GetActiveWindow" () As IntPtr
Public Class Shell32
'Styles used in the BROWSEINFO.ulFlags field.
<Flags()> Public Enum BffStyles As Integer
RestrictToFilesystem = &H1 ' BIF_RETURNONLYFSDIRS
RestrictToDomain = &H2 ' BIF_DONTGOBELOWDOMAIN
RestrictToSubfolders = &H8 ' BIF_RETURNFSANCESTORS
ShowTextBox = &H10 ' BIF_EDITBOX
ValidateSelection = &H20 ' BIF_VALIDATE
NewDialogStyle = &H40 ' BIF_NEWDIALOGSTYLE
BrowseForComputer = &H1000 ' BIF_BROWSEFORCOMPUTER
BrowseForPrinter = &H2000 ' BIF_BROWSEFORPRINTER
BrowseForEverything = &H4000 ' BIF_BROWSEINCLUDEFILES
End Enum
'Delegate type used in BROWSEINFO.lpfn field.
Public Delegate Function BFFCALLBACK(ByVal hwnd As IntPtr, ByVal uMsg As UInt32, ByVal lParam As IntPtr, ByVal lpData As IntPtr) As Integer
<StructLayout(LayoutKind.Sequential, Pack:=8)> _
Public Structure BROWSEINFO
Public hwndOwner As IntPtr
Public pidlRoot As IntPtr
Public pszDisplayName As IntPtr
<MarshalAs(UnmanagedType.LPStr)> _
Public lpszTitle As String
Public ulFlags As Integer
<MarshalAs(UnmanagedType.FunctionPtr)> _
Public lpfn As BFFCALLBACK
Public lParam As IntPtr
Public iImage As Integer
End Structure
Public Declare Function SHGetMalloc Lib "shell32" Alias "SHGetMalloc" (ByRef ppMalloc As IMalloc) As Integer
Public Declare Function SHGetSpecialFolderLocation Lib "shell32" Alias "SHGetSpecialFolderLocation" (ByVal hwndOwner As IntPtr, ByVal nFolder As Integer, ByRef ppidl As IntPtr) As Integer
Public Declare Function SHGetPathFromIDList Lib "shell32" Alias "SHGetPathFromIDList" (ByVal pidl As IntPtr, ByVal Path As StringBuilder) As Integer
Public Declare Function SHBrowseForFolder Lib "shell32" Alias "SHBrowseForFolder" (ByRef bi As BROWSEINFO) As IntPtr
End Class 'End of Class Shell32.
End Class ' End of Class win32api.
- Create the FolderBrowser component class.
To do this, add references to the System.Drawing and
System.Windows.Forms .NET assemblies. Make sure to identify
the namespaces that are used in the implementation of the component, and then
establish the internal data structures of the component, as follows:
Imports System.Drawing
Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.Security.Permissions
'<summary>
'Component wrapping access to the Browse For Folder common dialog box.
'Call the ShowDialog() method to show the dialog box.
'</summary>
Public NotInheritable Class FolderBrowser
Inherits Component
Private Shared ReadOnly MAX_PATH As Integer = 260
' Root node of the tree view.
Private m_startLocation As FolderID = FolderID.Desktop
' Browse info options.
Private publicOptions As Integer = Win32API.Shell32.BffStyles.RestrictToFilesystem Or Win32API.Shell32.BffStyles.RestrictToDomain
Private privateOptions As Integer = Win32API.Shell32.BffStyles.NewDialogStyle
' Description text to show.
Private descriptionText As String = "Please select a folder below:"
'Folder chosen by the user.
Private m_directoryPath As String = String.Empty
' <summary>
' Enum of CSIDLs identifying standard shell folders.
' </summary>
Public Enum FolderID
Desktop = &H0
Printers = &H4
MyDocuments = &H5
Favorites = &H6
Recent = &H8
SendTo = &H9
StartMenu = &HB
MyComputer = &H11
NetworkNeighborhood = &H12
Templates = &H15
MyPictures = &H27
NetAndDialUpConnections = &H31
End Enum
End Class - Implement the ShowDialog method on the
FolderBrowser class, as follows:
' <summary>
' Helper function that returns the IMalloc interface used by the shell.
'</summary>
Private Shared Function GetSHMalloc() As Win32API.IMalloc
Dim malloc As Win32API.IMalloc
Win32API.Shell32.SHGetMalloc(malloc)
Return malloc
End Function
'<summary>
'Shows the folder browser dialog box.
'</summary>
Public Function ShowDialog() As DialogResult
Return ShowDialog(Nothing)
End Function
' <summary>
' Shows the folder browser dialog box with the specified owner window.
' </summary>
Public Function ShowDialog(ByVal owner As IWin32Window) As DialogResult
Dim pidlRoot As IntPtr = IntPtr.Zero
'Get/find an owner HWND for this dialog
Dim hWndOwner As IntPtr
If (Not (owner Is Nothing)) Then
hWndOwner = owner.Handle
Else
hWndOwner = Win32API.GetActiveWindow()
End If
'Get the IDL for the specific startLocation.
Win32API.Shell32.SHGetSpecialFolderLocation(hWndOwner, m_startLocation, pidlRoot)
If (pidlRoot.Equals(IntPtr.Zero) = True) Then
Return DialogResult.Cancel
End If
Dim mergedOptions As Integer = publicOptions Or privateOptions
If ((mergedOptions And Win32API.Shell32.BffStyles.NewDialogStyle) <> 0) Then
Application.OleRequired()
End If
Dim pidlRet As IntPtr = IntPtr.Zero
Try
' Construct a BROWSEINFO.
Dim bi As Win32API.Shell32.BROWSEINFO = New Win32API.Shell32.BROWSEINFO()
Dim buffer As IntPtr = Marshal.AllocHGlobal(MAX_PATH)
bi.pidlRoot = pidlRoot
bi.hwndOwner = hWndOwner
bi.pszDisplayName = buffer
bi.lpszTitle = descriptionText
bi.ulFlags = mergedOptions
'Rest of the fields are initialized to zero by constructor.
'bi.lpfn = null; bi.lParam = IntPtr.Zero; bi.iImage = 0;
'Show the dialog.
pidlRet = Win32API.Shell32.SHBrowseForFolder(bi)
' Free the buffer that you have allocated on the global heap.
Marshal.FreeHGlobal(buffer)
If (pidlRet.Equals(IntPtr.Zero) = True) Then
'User pressed Cancel
Return DialogResult.Cancel
End If
'Then retrieve the path from the IDList.
Dim sb As StringBuilder = New StringBuilder(MAX_PATH)
If (0 = Win32API.Shell32.SHGetPathFromIDList(pidlRet, sb)) Then
Return DialogResult.Cancel
End If
' Convert to a string.
m_directoryPath = sb.ToString()
Finally
Dim malloc As Win32API.IMalloc = GetSHMalloc()
malloc.Free(pidlRoot)
If (pidlRet.Equals(IntPtr.Zero) = False) Then
malloc.Free(pidlRet)
End If
End Try
Return DialogResult.OK
End Function
- Add convenience properties to allow dialog box
customization. To do this, add a number of Boolean properties that allow the
user to set and reset flags in the publicOptions field of the
dialog box. The following properties are implemented:
- OnlyFilesystem
- ShowNetworkFolders
- OnlySubfolders
- ShowTextBox
- ValidateUserInput
- SelectComputer
- SelectPrinter
- SelectFiles
- DirectoryPath
- Description
In addition, implement the StartLocation property, as follows:
' <summary>
' Helper function used to set / reset bits in the publicOptions bitfield.
' </summary>
Private Sub SetOptionField(ByVal mask As Integer, ByVal turnOn As Boolean)
If (turnOn) Then
publicOptions = publicOptions Or mask
Else
publicOptions = publicOptions And (Not mask)
End If
End Sub
' <summary>
'Only return file system directories. If the user selects folders
'that are not part of the file system, the OK button is dimmed.
'</summary>
<Category("Navigation"), _
Description("Only return file system directories. If the user selects folders " + "that are not part of the file system, the OK button is grayed."), _
DefaultValue(True)> _
Public Property OnlyFilesystem() As Boolean
Get
Return ((publicOptions And Win32API.Shell32.BffStyles.RestrictToFilesystem) <> 0)
End Get
Set(ByVal Value As Boolean)
SetOptionField(Win32API.Shell32.BffStyles.RestrictToFilesystem, Value)
End Set
End Property
' <summary>
' Location of the root folder to start browsing from. Only the specified
' folder and any subfolders under it in the namespace hierarchy will appear
' in the dialog box.
' </summary>
<Category("Navigation"), _
Description("Location of the root folder to start browsing from. Only the specified " + _
"folder and any subfolders under it in the namespace hierarchy will appear " + _
"in the dialog box."), _
DefaultValue(GetType(FolderID), "0")> _
Public Property StartLocation() As FolderID
Get
Return m_startLocation
End Get
Set(ByVal Value As FolderID)
Dim Obj As New UIPermission(UIPermissionWindow.AllWindows)
Obj.Demand()
m_startLocation = Value
End Set
End Property
' <summary>
' Gets the directory path of the folder the user picked.
' </summary>
<Description("Contains the directory path of the folder the user picked.")> _
Public ReadOnly Property DirectoryPath() As String
Get
Dim Obj As New FileIOPermission(FileIOPermissionAccess.PathDiscovery, m_directoryPath)
Obj.Demand()
Return m_directoryPath
End Get
End Property
- Provide a toolbox icon for the component. To do this,
right-click the project in Solution Explorer, click Add, click
New Item, click Resources, and then click
Bitmap File. Name the new bitmap file
FolderBrowser.bmp, and then resize it to be 16 x 16
pixels. Edit the bitmap. In Solution Explorer, click to select the
FolderBrowser.bmp file, open the property grid, and then set
Build Action to Embedded Resource. Next,
associate this bitmap with your component by adding an attribute to the FolderBrowser class, as follows:
<ToolboxBitmap(GetType(FolderBrowser))> _
Public NotInheritable Class FolderBrowser
Inherits Component
' ....
End Class
- Build the project.
back to the topImplement the Test Project- Generate an empty project. To do this, add a new Visual
Basic .NET or Visual Basic 2005 Windows Application project named VbClient to the
BrowseForFolder solution. Add a reference to the
Microsoft.Samples.WinForms.Extras assembly that you just
created.
- Add a component to the toolbox. To do this, open the
Toolbox window, right-click the window, and then click to select
Customize Toolbox. On the .NET Framework
Components tab, click Browse, and then visit the
Microsoft.Samples.WinForms.Extras.dll file that you just
created. Click to select the FolderBrowser component when it
appears in the list, and then close the dialog box.
- Customize the form. To do this, open Form1 in design mode,
open the Toolbox window, and then drag a button and a
FolderBrowser component to your design area.
- Customize the FolderBrowser component. To
do this, click the folderBrowser1 icon. Notice all the
properties that you can customize in the Properties window. Customize these
properties.
- Add code to display the dialog box. To do this,
double-click the button that you dragged onto the form, and then add the
following code to the button handler:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If DialogResult.OK = folderBrowser1.ShowDialog() Then
MessageBox.Show(folderBrowser1.DirectoryPath)
End If
End Sub - Build the solution, and then run the
VbClient project.
back to the
top
Modification Type: | Minor | Last Reviewed: | 10/3/2006 |
---|
Keywords: | kbvs2005swept kbvs2005applies kbdownload kbAPI kbfile kbWindowsForms kbBrowse kbHOWTOmaster kbhowto KB811004 kbAudDeveloper |
---|
|
|
©2004 Microsoft Corporation. All rights reserved.
|
|