0
private void btn_Save_Click(object sender, RoutedEventArgs e)
    {
        string imgPath = @"C:\Temp\image.gif"; //Where file saves to

        string argument = "/select, \"" + imgPath + "\"";

        System.Diagnostics.Process.Start("explorer.exe", argument);

        MemoryStream ms = new MemoryStream();  //Memory stream :)
        FileStream fs = new FileStream(imgPath, FileMode.Create); //  File stream :)

        //rtb - the object of RenderTargetBitmap class
        RenderTargetBitmap rtb = new RenderTargetBitmap((int)InkCanvas1.Width, (int)InkCanvas1.Height, 96, 96, PixelFormats.Default);
        rtb.Render(InkCanvas1);

        GifBitmapEncoder gifEnc = new GifBitmapEncoder(); //saving a file in GIF
        gifEnc.Frames.Add(BitmapFrame.Create(rtb));
        gifEnc.Save(fs);
        fs.Close();
        MessageBox.Show("THE FILE HAS BEEN SAVED, " + imgPath);
    }

This code saves my file to the directory whichis written in imgPath and then explorer opens with no ability to choose a folder and resave this file there, how can I choose a folder???

  • 4
    You may use the WinForms FolderBrowserDialog. – Clemens Nov 24 '19 at 19:13
  • you might want to check this out: https://stackoverflow.com/questions/4547320/using-folderbrowserdialog-in-wpf-application – MarioWu Nov 25 '19 at 00:16
  • Why did you save the file in that folder to begin with? Save it in the folder you actually want. If you need to ask the user where to save, use the `Microsoft.Win32.SaveFileDialog` class. The `Process.Start` code can't be used to select foldrs, it simply opens a folder in Explorer with a file higlighted, nothing more. – Panagiotis Kanavos Nov 25 '19 at 12:27
  • You can use [SaveFileDialog.OpenFile](https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.savefiledialog.openfile?view=netframework-4.8#Microsoft_Win32_SaveFileDialog_OpenFile) to open a stream on the file the user selected and write directly to it, eg `if (dlg.ShowDialog()==true){ using(var fs=myDialog.OpenFile()){ .....` – Panagiotis Kanavos Nov 25 '19 at 12:30

2 Answers2

0

Try this code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

static class ShowSelectedInExplorer
{
    [Flags]
    internal enum SHCONT : ushort
    {
        SHCONTF_CHECKING_FOR_CHILDREN = 0x0010,
        SHCONTF_FOLDERS = 0x0020,
        SHCONTF_NONFOLDERS = 0x0040,
        SHCONTF_INCLUDEHIDDEN = 0x0080,
        SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
        SHCONTF_NETPRINTERSRCH = 0x0200,
        SHCONTF_SHAREABLE = 0x0400,
        SHCONTF_STORAGE = 0x0800,
        SHCONTF_NAVIGATION_ENUM = 0x1000,
        SHCONTF_FASTITEMS = 0x2000,
        SHCONTF_FLATLIST = 0x4000,
        SHCONTF_ENABLE_ASYNC = 0x8000
    }

    [ComImport,
    Guid("000214E6-0000-0000-C000-000000000046"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
    ComConversionLoss]
    internal interface IShellFolder
    {
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void ParseDisplayName(IntPtr hwnd, [In, MarshalAs(UnmanagedType.Interface)] IBindCtx pbc, [In, MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [Out] out uint pchEaten, [Out] out IntPtr ppidl, [In, Out] ref uint pdwAttributes);
        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int EnumObjects([In] IntPtr hwnd, [In] SHCONT grfFlags, [MarshalAs(UnmanagedType.Interface)] out IEnumIDList ppenumIDList);

        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int BindToObject([In] IntPtr pidl, [In, MarshalAs(UnmanagedType.Interface)] IBindCtx pbc, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out IShellFolder ppv);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void BindToStorage([In] ref IntPtr pidl, [In, MarshalAs(UnmanagedType.Interface)] IBindCtx pbc, [In] ref Guid riid, out IntPtr ppv);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void CompareIDs([In] IntPtr lParam, [In] ref IntPtr pidl1, [In] ref IntPtr pidl2);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void CreateViewObject([In] IntPtr hwndOwner, [In] ref Guid riid, out IntPtr ppv);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void GetAttributesOf([In] uint cidl, [In] IntPtr apidl, [In, Out] ref uint rgfInOut);


        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void GetUIObjectOf([In] IntPtr hwndOwner, [In] uint cidl, [In] IntPtr apidl, [In] ref Guid riid, [In, Out] ref uint rgfReserved, out IntPtr ppv);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void GetDisplayNameOf([In] ref IntPtr pidl, [In] uint uFlags, out IntPtr pName);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void SetNameOf([In] IntPtr hwnd, [In] ref IntPtr pidl, [In, MarshalAs(UnmanagedType.LPWStr)] string pszName, [In] uint uFlags, [Out] IntPtr ppidlOut);
    }

    [ComImport,
    Guid("000214F2-0000-0000-C000-000000000046"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface IEnumIDList
    {
        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int Next(uint celt, IntPtr rgelt, out uint pceltFetched);

        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int Skip([In] uint celt);

        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int Reset();

        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int Clone([MarshalAs(UnmanagedType.Interface)] out IEnumIDList ppenum);
    }

    class NativeMethods
    {
        static readonly int pointerSize = Marshal.SizeOf(typeof(IntPtr));

        [DllImport("ole32.dll", EntryPoint = "CreateBindCtx")]
        public static extern int CreateBindCtx_(int reserved, out IBindCtx ppbc);

        public static IBindCtx CreateBindCtx()
        {
            IBindCtx result;
            Marshal.ThrowExceptionForHR(CreateBindCtx_(0, out result));
            return result;
        }

        [DllImport("shell32.dll", EntryPoint = "SHGetDesktopFolder", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern int SHGetDesktopFolder_([MarshalAs(UnmanagedType.Interface)] out IShellFolder ppshf);

        public static IShellFolder SHGetDesktopFolder()
        {
            IShellFolder result;
            Marshal.ThrowExceptionForHR(SHGetDesktopFolder_(out result));
            return result;
        }

        [DllImport("shell32.dll", EntryPoint = "SHOpenFolderAndSelectItems")]
        static extern int SHOpenFolderAndSelectItems_(
            [In] IntPtr pidlFolder, uint cidl, [In, Optional, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, int dwFlags
            );

        public static void SHOpenFolderAndSelectItems(IntPtr pidlFolder, IntPtr[] apidl, int dwFlags)
        {
            var cidl = (apidl != null) ? (uint)apidl.Length : 0U;
            var result = NativeMethods.SHOpenFolderAndSelectItems_(pidlFolder, cidl, apidl, dwFlags);
            Marshal.ThrowExceptionForHR(result);
        }

        [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr ILCreateFromPath([In, MarshalAs(UnmanagedType.LPWStr)] string pszPath);

        [DllImport("shell32.dll")]
        public static extern void ILFree([In] IntPtr pidl);
    }

    static IntPtr GetShellFolderChildrenRelativePIDL(IShellFolder parentFolder, string displayName)
    {
        var bindCtx = NativeMethods.CreateBindCtx();

        uint pchEaten;
        uint pdwAttributes = 0;
        IntPtr ppidl;
        parentFolder.ParseDisplayName(IntPtr.Zero, null, displayName, out pchEaten, out ppidl, ref pdwAttributes);

        return ppidl;
    }

    static IntPtr PathToAbsolutePIDL(string path)
    {
        var desktopFolder = NativeMethods.SHGetDesktopFolder();
        return GetShellFolderChildrenRelativePIDL(desktopFolder, path);
    }

    static Guid IID_IShellFolder = typeof(IShellFolder).GUID;
    static int pointerSize = Marshal.SizeOf(typeof(IntPtr));

    static IShellFolder PIDLToShellFolder(IShellFolder parent, IntPtr pidl)
    {
        IShellFolder folder;
        var result = parent.BindToObject(pidl, null, ref IID_IShellFolder, out folder);
        Marshal.ThrowExceptionForHR((int)result);
        return folder;
    }

    static IShellFolder PIDLToShellFolder(IntPtr pidl)
    {
        return PIDLToShellFolder(NativeMethods.SHGetDesktopFolder(), pidl);
    }

    static void SHOpenFolderAndSelectItems(IntPtr pidlFolder, IntPtr[] apidl, bool edit)
    {
        NativeMethods.SHOpenFolderAndSelectItems(pidlFolder, apidl, edit ? 1 : 0);
    }

    public static void FileOrFolder(string path, bool edit = false)
    {
        if (path == null) throw new ArgumentNullException("path");

        var pidl = PathToAbsolutePIDL(path);
        try
        {
            SHOpenFolderAndSelectItems(pidl, null, edit);
        }
        finally
        {
            NativeMethods.ILFree(pidl);
        }
    }

    static IEnumerable<FileSystemInfo> PathToFileSystemInfo(IEnumerable<string> paths)
    {
        foreach (var path in paths)
        {
            string fixedPath = path;
            if (fixedPath.EndsWith(Path.DirectorySeparatorChar.ToString()) || fixedPath.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
            {
                fixedPath = fixedPath.Remove(fixedPath.Length - 1);
            }

            if (Directory.Exists(fixedPath)) yield return new DirectoryInfo(fixedPath);
            else if (File.Exists(fixedPath)) yield return new FileInfo(fixedPath);
            else
            {
                throw new FileNotFoundException("The specified file or folder doesn't exists : " + fixedPath, fixedPath);
            }
        }
    }

    public static void FilesOrFolders(string parentDirectory, ICollection<string> filenames)
    {
        if (filenames == null) throw new ArgumentNullException("filenames");
        if (filenames.Count == 0) return;

        var parentPidl = PathToAbsolutePIDL(parentDirectory);
        try
        {
            var parent = PIDLToShellFolder(parentPidl);

            List<IntPtr> filesPidl = new List<IntPtr>(filenames.Count);
            foreach (var filename in filenames)
            {
                filesPidl.Add(GetShellFolderChildrenRelativePIDL(parent, filename));
            }

            try
            {
                SHOpenFolderAndSelectItems(parentPidl, filesPidl.ToArray(), false);
            }
            finally
            {
                foreach (var pidl in filesPidl)
                {
                    NativeMethods.ILFree(pidl);
                }
            }
        }
        finally
        {
            NativeMethods.ILFree(parentPidl);
        }
    }

    public static void FilesOrFolders(params string[] paths)
    {
        FilesOrFolders((IEnumerable<string>)paths);
    }

    public static void FilesOrFolders(IEnumerable<string> paths)
    {
        FilesOrFolders(PathToFileSystemInfo(paths));
    }

    public static void FilesOrFolders(IEnumerable<FileSystemInfo> paths)
    {
        if (paths == null) throw new ArgumentNullException("paths");
        if (paths.Count() == 0) return;

        var explorerWindows = paths.GroupBy(p => Path.GetDirectoryName(p.FullName));

        foreach (var explorerWindowPaths in explorerWindows)
        {
            var parentDirectory = Path.GetDirectoryName(explorerWindowPaths.First().FullName);
            FilesOrFolders(parentDirectory, explorerWindowPaths.Select(fsi => fsi.Name).ToList());
        }
    }
}

Usage:

 ShowSelectedInExplorer.FilesOrFolders(@"C:\Temp\image.gif");
Igor Buchelnikov
  • 505
  • 4
  • 14
0

The question is a bit unclear as the code doesn't create or use a file saved in C:\Temp. It just uses this hard-coded name. I assume the real question is how to save to a specific file, not how to select a folder.

You can do this easily with the SaveFileDialog class :

var dlg = new Microsoft.Win32.SaveFileDialog();
dlg.FileName = "image.gif"; 
dlg.DefaultExt = ".gif"; 
dlg.Filter = "GIF files (.gif)|*.gif"; 
// `ShowDialog` returns a bool?
if(dlg.ShowDialog()==true)
{
    using(var fs=dlg.OpenFile())
    {
        var rtb = new RenderTargetBitmap((int)InkCanvas1.Width, (int)InkCanvas1.Height, 96, 96, PixelFormats.Default);
        rtb.Render(InkCanvas1);

        vargifEnc = new GifBitmapEncoder(); //saving a file in GIF
        gifEnc.Frames.Add(BitmapFrame.Create(rtb));
        gifEnc.Save(fs);
    }
    MessageBox.Show($"THE FILE HAS BEEN SAVED, {dlg.FileName}");
}

You can use the FileName propert to retrieve the selected name if you want to override the user's selection :

if(dlg.ShowDialog()==true)
{
    var fileName=Path.ChangeExtension(dlg.FileName,".gif");
    using(var fs=File.Open(fileName))
    {
        ...
    }
    MessageBox.Show($"THE FILE HAS BEEN SAVED, {fileName}");
}
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236