Microsoft KB Archive/811004

= How to implement a managed component that wraps the Browse For Folder common dialog box by using Visual Basic .NET or Visual Basic 2005 =

Article ID: 811004

Article Last Modified on 12/6/2006

-

APPLIES TO


 * Microsoft Visual Basic .NET 2002 Standard Edition
 * Microsoft Visual Basic .NET 2003 Standard Edition
 * 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:

BffcompVb.exe

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 TASK

 * SUMMARY
 * Implement the Design-Time Component
 * Implement the Test Project



SUMMARY
This 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.  _ Interface IMalloc  Function Alloc(ByVal cb As Integer) As IntPtr  Function Realloc(ByVal pv As IntPtr, ByVal cb As Integer) As IntPtr  Sub Free(ByVal pv As IntPtr)  Function GetSize(ByVal pv As IntPtr) As Integer  Function DidAlloc(ByVal pv As IntPtr) As Integer  Sub HeapMinimize End Interface

Public Declare Function GetActiveWindow Lib &quot;user32&quot; Alias &quot;GetActiveWindow&quot; 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 &quot;shell32&quot; Alias &quot;SHGetMalloc&quot; (ByRef ppMalloc As IMalloc) As Integer

Public Declare Function SHGetSpecialFolderLocation Lib &quot;shell32&quot; Alias &quot;SHGetSpecialFolderLocation&quot; (ByVal hwndOwner As IntPtr, ByVal nFolder As Integer, ByRef ppidl As IntPtr) As Integer

Public Declare Function SHGetPathFromIDList Lib &quot;shell32&quot; Alias &quot;SHGetPathFromIDList&quot; (ByVal pidl As IntPtr, ByVal Path As StringBuilder) As Integer

Public Declare Function SHBrowseForFolder Lib &quot;shell32&quot; Alias &quot;SHBrowseForFolder&quot; (ByRef bi As BROWSEINFO) As IntPtr

End Class 'End of Class Shell32. End Class ' End of Class win32api. </li>  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

'    'Component wrapping access to the Browse For Folder common dialog box. 'Call the ShowDialog method to show the dialog box. '    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 = &quot;Please select a folder below:&quot;

'Folder chosen by the user. Private m_directoryPath As String = String.Empty

'        ' Enum of CSIDLs identifying standard shell folders. '        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 </li>  Implement the ShowDialog method on the FolderBrowser class, as follows: '        ' Helper function that returns the IMalloc interface used by the shell. '        Private Shared Function GetSHMalloc As Win32API.IMalloc Dim malloc As Win32API.IMalloc Win32API.Shell32.SHGetMalloc(malloc) Return malloc End Function

'        'Shows the folder browser dialog box. '        Public Function ShowDialog As DialogResult Return ShowDialog(Nothing) End Function

'        ' Shows the folder browser dialog box with the specified owner window. '        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 </li>  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: <ul> OnlyFilesystem</li> ShowNetworkFolders</li> OnlySubfolders</li> ShowTextBox</li> ValidateUserInput</li> SelectComputer</li> SelectPrinter</li> SelectFiles</li> DirectoryPath</li> Description</li></ul>

In addition, implement the StartLocation property, as follows: '        ' Helper function used to set / reset bits in the publicOptions bitfield. '        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

'        'Only return file system directories. If the user selects folders 'that are not part of the file system, the OK button is dimmed. '

<Category(&quot;Navigation&quot;), _ Description(&quot;Only return file system directories. If the user selects folders &quot; + &quot;that are not part of the file system, the OK button is grayed.&quot;), _ 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

'        ' 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. '

<Category(&quot;Navigation&quot;), _ Description(&quot;Location of the root folder to start browsing from. Only the specified &quot; + _         &quot;folder and any subfolders under it in the namespace hierarchy will appear &quot; + _          &quot;in the dialog box.&quot;), _ DefaultValue(GetType(FolderID), &quot;0&quot;)> _ 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

'        ' Gets the directory path of the folder the user picked. '        <Description(&quot;Contains the directory path of the folder the user picked.&quot;)> _ 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 </li>  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 </li> Build the project.</li></ol>

back to the top

Implement the Test Project
<ol> 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.</li> <li>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.</li> <li>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.</li> <li>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.</li> <li> 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 </li> <li>Build the solution, and then run the VbClient project.</li></ol>

back to the top

Additional query words: BffCompVb

Keywords: kbvs2005swept kbvs2005applies kbdownload kbapi kbfile kbwindowsforms kbbrowse kbhowtomaster kbhowto KB811004

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.