protected override Boolean RunDialog(IntPtr hwndOwner) { IntPtr pidlRoot = IntPtr.Zero; Boolean result = false; UnsafeNativeMethods.Shell32.SHGetSpecialFolderLocation(hwndOwner, (Int32)_rootFolder, ref pidlRoot); if (pidlRoot == IntPtr.Zero) { UnsafeNativeMethods.Shell32.SHGetSpecialFolderLocation(hwndOwner, 0, ref pidlRoot); if (pidlRoot == IntPtr.Zero) { throw new InvalidOperationException("Unable to retrieve the root folder."); } } Int32 options = NEW_DIALOG_STYLE_OPTION; if (!ShowNewFolderButton) { options += HIDE_NEW_FOLDER_BUTTON_OPTION; } IntPtr pidlRet = IntPtr.Zero; IntPtr pszDisplayName = IntPtr.Zero; IntPtr pszSelectedPath = IntPtr.Zero; UnsafeNativeMethods.BrowseCallbackProc callback; try { var browseInfo = new UnsafeNativeMethods.BrowseInfo(); pszDisplayName = Marshal.AllocHGlobal(MAX_PATH * Marshal.SystemDefaultCharSize); pszSelectedPath = Marshal.AllocHGlobal(MAX_PATH * Marshal.SystemDefaultCharSize); callback = new UnsafeNativeMethods.BrowseCallbackProc(BrowseCallbackHandler); browseInfo.pidlRoot = pidlRoot; browseInfo.hwndOwner = hwndOwner; browseInfo.pszDisplayName = pszDisplayName; browseInfo.lpszTitle = _descriptionText; browseInfo.ulFlags = options; browseInfo.lpfn = callback; browseInfo.lParam = IntPtr.Zero; browseInfo.iImage = 0; pidlRet = UnsafeNativeMethods.Shell32.SHBrowseForFolder(browseInfo); if (pidlRet != IntPtr.Zero) { UnsafeNativeMethods.Shell32.SHGetPathFromIDList(pidlRet, pszSelectedPath); _selectedPathNeedsCheck = true; _selectedPath = Marshal.PtrToStringAuto(pszSelectedPath); result = true; } } finally { UnsafeNativeMethods.Ole32.CoTaskMemFree(pidlRoot); if (pidlRet != IntPtr.Zero) { UnsafeNativeMethods.Ole32.CoTaskMemFree(pidlRet); } if (pszSelectedPath != IntPtr.Zero) { Marshal.FreeHGlobal(pszSelectedPath); } if (pszDisplayName != IntPtr.Zero) { Marshal.FreeHGlobal(pszDisplayName); } callback = null; } return(result); }
/// <include file='doc\FolderBrowserDialog.uex' path='docs/doc[@for="FolderBrowserDialog.RunDialog"]/*' /> /// <devdoc> /// Implements running of a folder browser dialog. /// </devdoc> 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 + 1) * 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.SHGetPathFromIDListLongPath(pidlRet, ref 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); }
/// <include file='doc\FolderBrowserDialog.uex' path='docs/doc[@for="FolderBrowserDialog.RunDialog"]/*' /> /// <devdoc> /// Implements running of a folder browser dialog. /// </devdoc> 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 Exception(SR.GetString(SR.FolderBrowserDialogNoRootFolder)); } } int mergedOptions = (int)UnsafeNativeMethods.BrowseInfos.NewDialogStyle; if (!showNewFolderButton) { mergedOptions += (int)UnsafeNativeMethods.BrowseInfos.HideNewFolderButton; } Application.OleRequired(); IntPtr pidlRet = IntPtr.Zero; try { // Construct a BROWSEINFO UnsafeNativeMethods.BROWSEINFO bi = new UnsafeNativeMethods.BROWSEINFO(); IntPtr pszDisplayName = Marshal.AllocHGlobal(NativeMethods.MAX_PATH); IntPtr pszSelectedPath = Marshal.AllocHGlobal(NativeMethods.MAX_PATH); UnsafeNativeMethods.BrowseCallbackProc 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); // Then free all the stuff we've allocated or the SH API gave us Marshal.FreeHGlobal(pszSelectedPath); Marshal.FreeHGlobal(pszDisplayName); returnValue = true; } } finally { UnsafeNativeMethods.IMalloc malloc = GetSHMalloc(); malloc.Free(pidlRoot); if (pidlRet != IntPtr.Zero) { malloc.Free(pidlRet); } } return(returnValue); }
/// <include file='doc\FolderBrowserDialog.uex' path='docs/doc[@for="FolderBrowserDialog.RunDialog"]/*' /> /// <devdoc> /// Implements running of a folder browser dialog. /// </devdoc> 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; }
/// <summary> /// When overridden in a derived class, specifies a common dialog box. /// </summary> /// <param name="hwndOwner">A value that represents the window handle of the owner window for the common dialog box.</param> /// <returns>true if the dialog box was successfully run; otherwise, false.</returns> protected override bool RunDialog(IntPtr hwndOwner) { IntPtr root = IntPtr.Zero; bool flag = false; UnsafeNativeMethods.Shell32.SHGetSpecialFolderLocation(hwndOwner, (int)Environment.SpecialFolder.Desktop, ref root); int browseInfoFlags = NativeMethods.BIF_NEWDIALOGSTYLE; if (!_showNewFolderButton) { browseInfoFlags += NativeMethods.BIF_NONEWFOLDERBUTTON; } IntPtr pidl = IntPtr.Zero; IntPtr hglobal = IntPtr.Zero; IntPtr pszPath = IntPtr.Zero; try { hglobal = Marshal.AllocHGlobal((int)(260 * Marshal.SystemDefaultCharSize)); pszPath = Marshal.AllocHGlobal((int)(260 * Marshal.SystemDefaultCharSize)); _callback = new UnsafeNativeMethods.BrowseCallbackProc(OnBrowseCallbackProc); UnsafeNativeMethods.BROWSEINFO lpbi = new UnsafeNativeMethods.BROWSEINFO(); lpbi.pidlRoot = root; lpbi.hwndOwner = hwndOwner; lpbi.pszDisplayName = hglobal; lpbi.lpszTitle = _descriptionText; lpbi.ulFlags = browseInfoFlags; lpbi.lpfn = _callback; lpbi.lParam = IntPtr.Zero; lpbi.iImage = 0; pidl = UnsafeNativeMethods.Shell32.SHBrowseForFolder(lpbi); if (pidl != IntPtr.Zero) { UnsafeNativeMethods.Shell32.SHGetPathFromIDList(pidl, pszPath); _selectedPathNeedsCheck = true; _selectedPath = Marshal.PtrToStringAuto(pszPath); flag = true; } } finally { UnsafeNativeMethods.IMalloc sHMalloc = GetSHMalloc(); sHMalloc.Free(root); if (pidl != IntPtr.Zero) sHMalloc.Free(pidl); if (pszPath != IntPtr.Zero) Marshal.FreeHGlobal(pszPath); if (hglobal != IntPtr.Zero) Marshal.FreeHGlobal(hglobal); _callback = null; } return flag; }