/// <summary>Shows the dialog box to let the user browse for and select a folder.</summary> /// <param name="parentWindowHandle">The HWND of the parent window.</param> /// <returns>The selected folder or <c>null</c> if no folder was selected by the user.</returns> protected override bool RunDialog(IntPtr parentWindowHandle) { // Setup BROWSEINFO.dwFlag value EnumFlagIndexer <BrowseInfoFlag> browseInfoFlag = BrowseInfoFlag.BIF_SHAREABLE; browseInfoFlag[BrowseInfoFlag.BIF_NEWDIALOGSTYLE] = Application.OleRequired() == ApartmentState.STA; browseInfoFlag[BrowseInfoFlag.BIF_DONTGOBELOWDOMAIN] = HideDomainFolders; browseInfoFlag[BrowseInfoFlag.BIF_BROWSEFILEJUNCTIONS] = ShowFileJunctions; browseInfoFlag[BrowseInfoFlag.BIF_RETURNONLYFSDIRS] = LocalFileSystemOnly; browseInfoFlag[BrowseInfoFlag.BIF_NONEWFOLDERBUTTON] = !ShowNewFolderButton; browseInfoFlag[BrowseInfoFlag.BIF_EDITBOX | BrowseInfoFlag.BIF_VALIDATE] = ShowFolderPathEditBox; switch (BrowseOption) { case FolderBrowserDialogOptions.Folders: break; case FolderBrowserDialogOptions.FoldersAndFiles: browseInfoFlag |= BrowseInfoFlag.BIF_BROWSEINCLUDEFILES; break; case FolderBrowserDialogOptions.Computers: browseInfoFlag |= BrowseInfoFlag.BIF_BROWSEFORCOMPUTER; RootFolder = defaultComputersFolder; break; case FolderBrowserDialogOptions.Printers: browseInfoFlag |= BrowseInfoFlag.BIF_BROWSEFORPRINTER; RootFolder = defaultPrintersFolder; break; default: throw new ArgumentOutOfRangeException(); } // Setup the BROWSEINFO structure var dn = new SafeCoTaskMemString(Kernel32.MAX_PATH); var bi = new BROWSEINFO(parentWindowHandle, rootPidl.DangerousGetHandle(), Description, browseInfoFlag, OnBrowseEvent, dn.DangerousGetHandle()); // Show the dialog pidl = SHBrowseForFolder(ref bi); href = default(HandleRef); if (pidl.IsInvalid) { return(false); } if (browseInfoFlag[BrowseInfoFlag.BIF_BROWSEFORPRINTER] || browseInfoFlag[BrowseInfoFlag.BIF_BROWSEFORCOMPUTER]) { SelectedItem = bi.DisplayName; } else { SelectedItem = GetNameForPidl(pidl); } return(true); }
/// <summary>Callback for Windows.</summary> /// <param name="hwnd">Window handle of the browse dialog box.</param> /// <param name="uMsg">Dialog box event that generated the statusMessage.</param> /// <param name="lParam">Value whose meaning depends on the event specified in uMsg.</param> /// <param name="lpData">Application-defined value that was specified in the lParam member of the BROWSEINFO structure used in the call to SHBrowseForFolder.</param> /// <returns> /// Returns 0 except in the case of BFFM_VALIDATEFAILED. For that flag, returns 0 to dismiss the dialog or nonzero to keep the dialog displayed. /// </returns> //[CLSCompliant(false)] private int OnBrowseEvent(IntPtr hwnd, BrowseForFolderMessages uMsg, IntPtr lParam, IntPtr lpData) { var messsage = uMsg; href = new HandleRef(this, hwnd); switch (messsage) { case BrowseForFolderMessages.BFFM_INITIALIZED: // Dialog is being initialized, so set the initial parameters if (!string.IsNullOrEmpty(Caption)) { SetWindowText(href, Caption); } if (!string.IsNullOrEmpty(SelectedItem)) { SendMessage(href, (uint)BrowseForFolderMessages.BFFM_SETSELECTIONW, (IntPtr)1, SelectedItem); } if (Expanded) { SendMessage(href, (uint)BrowseForFolderMessages.BFFM_SETEXPANDED, (IntPtr)1, rootPidl.DangerousGetHandle()); } if (!string.IsNullOrEmpty(OkText)) { SendMessage(href, (uint)BrowseForFolderMessages.BFFM_SETOKTEXT, (IntPtr)0, OkText); } Initialized?.Invoke(this, new FolderBrowserDialogInitializedEventArgs(hwnd)); initialized = true; return(0); case BrowseForFolderMessages.BFFM_SELCHANGED: try { if (!initialized || pidl?.DangerousGetHandle() == lParam) { return(0); } var tmpPidl = new PIDL(lParam, false, false); var str = GetNameForPidl(tmpPidl); if (string.IsNullOrEmpty(str)) { return(0); } SelectedItem = str; pidl = tmpPidl; } catch { return(0); } SelectedItemChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItem))); return(0); case BrowseForFolderMessages.BFFM_VALIDATEFAILEDA: case BrowseForFolderMessages.BFFM_VALIDATEFAILEDW: if (InvalidFolderSelected != null) { var folderName = messsage == BrowseForFolderMessages.BFFM_VALIDATEFAILEDA ? Marshal.PtrToStringAnsi(lParam) : Marshal.PtrToStringUni(lParam); var e = new InvalidFolderEventArgs(folderName, true); InvalidFolderSelected?.Invoke(this, e); return(e.DismissDialog ? 0 : 1); } return(0); default: return(0); } }