PavlikBender / Pickers

MIT License
3 stars 1 forks source link

Pick multiple files #3

Open MercuryVN opened 3 months ago

MercuryVN commented 3 months ago

I see no option to pick multiple files, and I know next to nothing about what is going on here, I tried to modify the project as follow: create a new file FileMultiPicker.cs

using Pickers.Classes;
using Pickers.Enums;

namespace Pickers;

/// <summary>
/// Class responsible for file pick dialog.
/// </summary>
public class FileMultiPicker
{
    // ...
    // copy from FileOpenPicker.cs
    // ...

    public List<string> Show(List<string>? typeFilters = null)
    {
        return Helper.ShowMulti(_windowHandle, FOS.FOS_ALLOWMULTISELECT | FOS.FOS_FORCEFILESYSTEM, typeFilters);
    }
}

in Helper.cs, add

    internal static List<string> ShowMulti(nint windowHandle, FOS fos, List<string>? typeFilters = null)
    {
        var dialog = new FileOpenDialog();
        try
        {
            dialog.SetOptions(fos);

            if (typeFilters != null)
            {
                typeFilters.Insert(0, string.Join("; ", typeFilters));
                var filterSpecs = typeFilters.Select(f => new COMDLG_FILTERSPEC(f)).ToArray();

                dialog.SetFileTypes((uint)filterSpecs.Length, filterSpecs);
            }

            if (dialog.Show(windowHandle) != 0)
                return new();

            dialog.GetResults(out var items);
            List<string> result = new();
            items.GetCount(out var count);
            for (uint i = 0; i < count; i++)
            {
                items.GetItemAt(i, out var item);
                item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out var path);
                result.Add(path);
            }
            return result;
        }
        catch (Exception ex)
        {
            return new();
        }
        finally
        {
#pragma warning disable CA1416 
            Marshal.ReleaseComObject(dialog);
#pragma warning restore CA1416
        }
    }

move from IFileOpenDialog.cs to IFileDialog.cs

    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
    void GetResults([MarshalAs(UnmanagedType.Interface)] out IShellItemArray ppenum);

    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
    void GetSelectedItems([MarshalAs(UnmanagedType.Interface)] out IShellItemArray ppsai);

the code run, but at dialog.GetResults(out var items);, it returns null as if no file was selected if I could get some help or pointed to a right direction I would appreciate it

MercuryVN commented 3 months ago

after a bit of digging, I think that I shouldn't move

    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
    void GetResults([MarshalAs(UnmanagedType.Interface)] out IShellItemArray ppenum);

    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
    void GetSelectedItems([MarshalAs(UnmanagedType.Interface)] out IShellItemArray ppsai);

so I reverse it and now it throw another error: Value does not fall within the expected range at dialog.GetResults(out var items);

PavlikBender commented 3 months ago

Hello @MercuryVN , look at this solution https://stackoverflow.com/questions/11624298/how-do-i-use-openfiledialog-to-select-a-folder/66187224#66187224 It's seems works fine! I've checked with folders and files.