public unsafe Task <string?> ShowFolderDialogAsync(OpenFolderDialog dialog, Window parent)
        {
            return(Task.Run(() =>
            {
                string?result = default;
                try
                {
                    var hWnd = parent?.PlatformImpl?.Handle?.Handle ?? IntPtr.Zero;
                    var clsid = UnmanagedMethods.ShellIds.OpenFileDialog;
                    var iid = UnmanagedMethods.ShellIds.IFileDialog;
                    var frm = UnmanagedMethods.CreateInstance <IFileDialog>(ref clsid, ref iid);

                    var options = frm.Options;
                    options = FILEOPENDIALOGOPTIONS.FOS_PICKFOLDERS | DefaultDialogOptions;
                    frm.SetOptions(options);

                    var title = dialog.Title ?? "";
                    fixed(char *tExt = title)
                    {
                        frm.SetTitle(tExt);
                    }

                    if (dialog.Directory != null)
                    {
                        var riid = UnmanagedMethods.ShellIds.IShellItem;
                        if (UnmanagedMethods.SHCreateItemFromParsingName(dialog.Directory, IntPtr.Zero, ref riid, out var directoryShellItem)
                            == (uint)UnmanagedMethods.HRESULT.S_OK)
                        {
                            var proxy = MicroComRuntime.CreateProxyFor <IShellItem>(directoryShellItem, true);
                            frm.SetFolder(proxy);
                            frm.SetDefaultFolder(proxy);
                        }
                    }

                    var showResult = frm.Show(hWnd);

                    if ((uint)showResult == (uint)UnmanagedMethods.HRESULT.E_CANCELLED)
                    {
                        return result;
                    }
                    else if ((uint)showResult != (uint)UnmanagedMethods.HRESULT.S_OK)
                    {
                        throw new Win32Exception(showResult);
                    }

                    if (frm.Result is not null)
                    {
                        result = GetAbsoluteFilePath(frm.Result);
                    }

                    return result;
                }
                catch (COMException ex)
                {
                    throw new Win32Exception(ex.HResult);
                }
            }));
        }
示例#2
0
        private unsafe Task <IEnumerable <string> > ShowFilePicker(
            bool isOpenFile,
            bool openFolder,
            bool allowMultiple,
            bool?showOverwritePrompt,
            string?title,
            string?suggestedFileName,
            IStorageFolder?folder,
            string?defaultExtension,
            IReadOnlyList <FilePickerFileType>?filters)
        {
            return(Task.Run(() =>
            {
                IEnumerable <string> result = Array.Empty <string>();
                try
                {
                    var clsid = isOpenFile ? UnmanagedMethods.ShellIds.OpenFileDialog : UnmanagedMethods.ShellIds.SaveFileDialog;
                    var iid = UnmanagedMethods.ShellIds.IFileDialog;
                    var frm = UnmanagedMethods.CreateInstance <IFileDialog>(ref clsid, ref iid);

                    var options = frm.Options;
                    options |= DefaultDialogOptions;
                    if (openFolder)
                    {
                        options |= FILEOPENDIALOGOPTIONS.FOS_PICKFOLDERS;
                    }
                    if (allowMultiple)
                    {
                        options |= FILEOPENDIALOGOPTIONS.FOS_ALLOWMULTISELECT;
                    }

                    if (showOverwritePrompt == false)
                    {
                        options &= ~FILEOPENDIALOGOPTIONS.FOS_OVERWRITEPROMPT;
                    }
                    frm.SetOptions(options);

                    if (defaultExtension is not null)
                    {
                        fixed(char *pExt = defaultExtension)
                        {
                            frm.SetDefaultExtension(pExt);
                        }
                    }

                    suggestedFileName ??= "";
                    fixed(char *fExt = suggestedFileName)
                    {
                        frm.SetFileName(fExt);
                    }

                    title ??= "";
                    fixed(char *tExt = title)
                    {
                        frm.SetTitle(tExt);
                    }

                    if (!openFolder)
                    {
                        fixed(void *pFilters = FiltersToPointer(filters, out var count))
                        {
                            frm.SetFileTypes((ushort)count, pFilters);
                            if (count > 0)
                            {
                                frm.SetFileTypeIndex(0);
                            }
                        }
                    }

                    if (folder?.TryGetUri(out var folderPath) == true)
                    {
                        var riid = UnmanagedMethods.ShellIds.IShellItem;
                        if (UnmanagedMethods.SHCreateItemFromParsingName(folderPath.LocalPath, IntPtr.Zero, ref riid, out var directoryShellItem)
                            == (uint)UnmanagedMethods.HRESULT.S_OK)
                        {
                            var proxy = MicroComRuntime.CreateProxyFor <IShellItem>(directoryShellItem, true);
                            frm.SetFolder(proxy);
                            frm.SetDefaultFolder(proxy);
                        }
                    }

                    var showResult = frm.Show(_windowImpl.Handle !.Handle);

                    if ((uint)showResult == (uint)UnmanagedMethods.HRESULT.E_CANCELLED)
                    {
                        return result;
                    }
                    else if ((uint)showResult != (uint)UnmanagedMethods.HRESULT.S_OK)
                    {
                        throw new Win32Exception(showResult);
                    }

                    if (allowMultiple)
                    {
                        using var fileOpenDialog = frm.QueryInterface <IFileOpenDialog>();
                        var shellItemArray = fileOpenDialog.Results;
                        var count = shellItemArray.Count;

                        var results = new List <string>();
                        for (int i = 0; i < count; i++)
                        {
                            var shellItem = shellItemArray.GetItemAt(i);
                            if (GetAbsoluteFilePath(shellItem) is { } selected)
                            {
                                results.Add(selected);
                            }
                        }

                        result = results;
                    }
                    else if (frm.Result is { } shellItem &&
                             GetAbsoluteFilePath(shellItem) is { } singleResult)
                    {
                        result = new[] { singleResult };
                    }

                    return result;
                }
                catch (COMException ex)
                {
                    var message = new Win32Exception(ex.HResult).Message;
                    throw new COMException(message, ex);
                }
            }) !);
        }
        public unsafe Task <string[]?> ShowFileDialogAsync(FileDialog dialog, Window parent)
        {
            var hWnd = parent?.PlatformImpl?.Handle?.Handle ?? IntPtr.Zero;

            return(Task.Run(() =>
            {
                string[]? result = default;
                try
                {
                    var clsid = dialog is OpenFileDialog ? UnmanagedMethods.ShellIds.OpenFileDialog : UnmanagedMethods.ShellIds.SaveFileDialog;
                    var iid = UnmanagedMethods.ShellIds.IFileDialog;
                    var frm = UnmanagedMethods.CreateInstance <IFileDialog>(ref clsid, ref iid);

                    var openDialog = dialog as OpenFileDialog;

                    var options = frm.Options;
                    options |= DefaultDialogOptions;
                    if (openDialog?.AllowMultiple == true)
                    {
                        options |= FILEOPENDIALOGOPTIONS.FOS_ALLOWMULTISELECT;
                    }

                    if (dialog is SaveFileDialog saveFileDialog)
                    {
                        var overwritePrompt = saveFileDialog.ShowOverwritePrompt ?? true;

                        if (!overwritePrompt)
                        {
                            options &= ~FILEOPENDIALOGOPTIONS.FOS_OVERWRITEPROMPT;
                        }
                    }
                    frm.SetOptions(options);

                    var defaultExtension = (dialog as SaveFileDialog)?.DefaultExtension ?? "";
                    fixed(char *pExt = defaultExtension)
                    {
                        frm.SetDefaultExtension(pExt);
                    }

                    var initialFileName = dialog.InitialFileName ?? "";
                    fixed(char *fExt = initialFileName)
                    {
                        frm.SetFileName(fExt);
                    }

                    var title = dialog.Title ?? "";
                    fixed(char *tExt = title)
                    {
                        frm.SetTitle(tExt);
                    }

                    fixed(void *pFilters = FiltersToPointer(dialog.Filters, out var count))
                    {
                        frm.SetFileTypes((ushort)count, pFilters);
                    }

                    frm.SetFileTypeIndex(0);

                    if (dialog.Directory != null)
                    {
                        var riid = UnmanagedMethods.ShellIds.IShellItem;
                        if (UnmanagedMethods.SHCreateItemFromParsingName(dialog.Directory, IntPtr.Zero, ref riid, out var directoryShellItem)
                            == (uint)UnmanagedMethods.HRESULT.S_OK)
                        {
                            var proxy = MicroComRuntime.CreateProxyFor <IShellItem>(directoryShellItem, true);
                            frm.SetFolder(proxy);
                            frm.SetDefaultFolder(proxy);
                        }
                    }

                    var showResult = frm.Show(hWnd);

                    if ((uint)showResult == (uint)UnmanagedMethods.HRESULT.E_CANCELLED)
                    {
                        return result;
                    }
                    else if ((uint)showResult != (uint)UnmanagedMethods.HRESULT.S_OK)
                    {
                        throw new Win32Exception(showResult);
                    }

                    if (openDialog?.AllowMultiple == true)
                    {
                        using var fileOpenDialog = frm.QueryInterface <IFileOpenDialog>();
                        var shellItemArray = fileOpenDialog.Results;
                        var count = shellItemArray.Count;

                        var results = new List <string>();
                        for (int i = 0; i < count; i++)
                        {
                            var shellItem = shellItemArray.GetItemAt(i);
                            if (GetAbsoluteFilePath(shellItem) is { } selected)
                            {
                                results.Add(selected);
                            }
                        }
                        result = results.ToArray();
                    }
                    else if (frm.Result is { } shellItem &&
                             GetAbsoluteFilePath(shellItem) is { } singleResult)
                    {
                        result = new[] { singleResult };
                    }

                    return result;
                }
                catch (COMException ex)
                {
                    throw new Win32Exception(ex.HResult);
                }
            }) !);
        }