public Result <string> Ask() { IntPtr pidlRoot; IntPtr hWndOwner; if (mOwner is Window window) { var iw = new WindowInteropHelper(window); hWndOwner = iw.Handle; } else if (mOwner is IWin32Window win32Window) { hWndOwner = win32Window.Handle; } else { hWndOwner = GetActiveWindow(); } SHGetSpecialFolderLocation(hWndOwner, (int)mRoot, out pidlRoot); if (pidlRoot == IntPtr.Zero) { return(Result.CreateError <Result <string> >("Error reading the root directory of the user profile. Perhaps there are no sufficient permissions to perform this action or the user profile is corrupted.")); } var mergedOptions = mPublicOptions | mPrivateOptions; if ((mergedOptions & (int)BrowseForFolderStyles.NewDialogStyle) != 0) { if (System.Threading.ApartmentState.MTA == System.Windows.Forms.Application.OleRequired()) { mergedOptions = mergedOptions & ~(int)BrowseForFolderStyles.NewDialogStyle; } } var pidlRet = IntPtr.Zero; try { var bi = new BrowseForFolderDialogInfo(); var buffer = Marshal.AllocHGlobal(mMaxPathLength); bi.pidlRoot = pidlRoot; bi.hwndOwner = hWndOwner; bi.pszDisplayName = buffer; bi.lpszTitle = mPrompt; bi.ulFlags = mergedOptions; bi.lpfn = BrowseDialogCallback; pidlRet = SHBrowseForFolder(ref bi); Marshal.FreeHGlobal(buffer); if (pidlRet == IntPtr.Zero) { return(Result.CreateError <Result <string> >(new OperationCanceledException())); } var sb = new StringBuilder(mMaxPathLength); if (0 == SHGetPathFromIDList(pidlRet, sb)) { return(Result.CreateError <Result <string> >(new OperationCanceledException())); } mPath = sb.ToString(); } finally { IMalloc malloc; SHGetMalloc(out malloc); malloc.Free(pidlRoot); if (pidlRet != IntPtr.Zero) { malloc.Free(pidlRet); } } return(new Result <string>(mPath)); }
[DllImport("shell32.dll", CharSet = CharSet.Auto)] static extern IntPtr SHBrowseForFolder(ref BrowseForFolderDialogInfo bi);