using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Windows.Forms; using BizHawk.Common; namespace BizHawk.Client.EmuHawk { /// /// Component wrapping access to the Browse For Folder common dialog box. /// Call the ShowDialog() method to bring the dialog box up. /// /// /// I believe this code is from http://support.microsoft.com/kb/306285
/// The license is assumed to be effectively public domain.
/// I saw a version of it with at least one bug fixed at https://github.com/slavat/MailSystem.NET/blob/master/Queuing%20System/ActiveQLibrary/CustomControl/FolderBrowser.cs
/// --zeromus ///
public sealed class FolderBrowserEx : Component { /// is this supposed to be public? we're obviously not using it at callsites at the moment --yoshi private Win32Imports.BROWSEINFO.FLAGS publicOptions = Win32Imports.BROWSEINFO.FLAGS.RestrictToFilesystem | Win32Imports.BROWSEINFO.FLAGS.RestrictToDomain; public string Description = "Please select a folder below:"; public string SelectedPath; /// Shows the folder browser dialog box with the specified owner window. public DialogResult ShowDialog(IWin32Window owner = null) { const Win32Imports.BROWSEINFO.FLAGS privateOptions = Win32Imports.BROWSEINFO.FLAGS.NewDialogStyle | Win32Imports.BROWSEINFO.FLAGS.ShowTextBox; const int startLocation = 0; // = Desktop CSIDL int Callback(IntPtr hwnd, uint uMsg, IntPtr lParam, IntPtr lpData) { if (uMsg == 1) { var str = Marshal.StringToHGlobalUni(SelectedPath); Win32Imports.SendMessage(hwnd, 0x400 + 103, (IntPtr) 1, str); Marshal.FreeHGlobal(str); } return 0; } var hWndOwner = owner?.Handle ?? Win32Imports.GetActiveWindow(); Win32Imports.SHGetSpecialFolderLocation(hWndOwner, startLocation, out var pidlRoot); if (pidlRoot == IntPtr.Zero) return DialogResult.Cancel; var mergedOptions = publicOptions | privateOptions; if ((mergedOptions & Win32Imports.BROWSEINFO.FLAGS.NewDialogStyle) != 0 && ApartmentState.MTA == Application.OleRequired()) { mergedOptions &= ~Win32Imports.BROWSEINFO.FLAGS.NewDialogStyle; } IntPtr pidlRet = default; try { var buffer = Marshal.AllocHGlobal(Win32Imports.MAX_PATH); var bi = new Win32Imports.BROWSEINFO { hwndOwner = hWndOwner, pidlRoot = pidlRoot, pszDisplayName = buffer, lpszTitle = Description, ulFlags = mergedOptions, lpfn = Callback }; pidlRet = Win32Imports.SHBrowseForFolder(ref bi); Marshal.FreeHGlobal(buffer); if (pidlRet == IntPtr.Zero) return DialogResult.Cancel; // user clicked Cancel var sb = new StringBuilder(Win32Imports.MAX_PATH); if (Win32Imports.SHGetPathFromIDList(pidlRet, sb) == 0) return DialogResult.Cancel; SelectedPath = sb.ToString(); } finally { Win32Imports.SHGetMalloc(out var malloc); malloc.Free(pidlRoot); if (pidlRet != IntPtr.Zero) malloc.Free(pidlRet); } return DialogResult.OK; } } }