protected override bool RunDialog(IntPtr hwndOwner)
    {
      DialogUtil.Assume(Marshal.SystemDefaultCharSize == 2, "The character size should be 2");

      var nativeBuffer = Marshal.AllocCoTaskMem(InteropUtil.NumberOfFileChars * 2);
      IntPtr filterBuffer = IntPtr.Zero;

      try
      {
        var openFileName = new InteropUtil.OpenFileName();
        openFileName.Initialize();
        openFileName.hwndOwner = hwndOwner;

        var chars = new char[InteropUtil.NumberOfFileChars];

        try
        {
          if (File.Exists(Path))
          {
            if (AcceptFiles)
            {
              var fileName = System.IO.Path.GetFileName(Path);
              var length = Math.Min(fileName.Length, InteropUtil.NumberOfFileChars);
              fileName.CopyTo(0, chars, 0, length);
              openFileName.lpstrInitialDir = System.IO.Path.GetDirectoryName(Path);
            }
            else
            {
              openFileName.lpstrInitialDir = System.IO.Path.GetDirectoryName(Path);
            }
          }
          else if (Directory.Exists(Path))
          {
            openFileName.lpstrInitialDir = Path;
          }
          else
          {
            //the path does not exist.
            //We don't just want to throw it away, however.
            //The initial path we get is most likely provided by the user in some way.
            //It could be what they typed into a text box before clicking a browse button,
            //or it could be a value they had entered previously that used to be valid, but now no longer exists.
            //In any case, we don't want to throw out the user's text. So, we find the first parent 
            //directory of Path that exists on disk.
            //We will set the initial directory to that path, and then set the initial file to
            //the rest of the path. The user will get an error if the click "OK"m saying that the selected path
            //doesn't exist, but that's ok. If we didn't do this, and showed the path, if they clicked
            //OK without making changes we would actually change the selected path, which would be bad.
            //This way, if the users want's to change the folder, he actually has to change something.
            string pathToShow;
            InitializePathDNE(Path, out openFileName.lpstrInitialDir, out pathToShow);
            pathToShow = pathToShow ?? "";
            var length = Math.Min(pathToShow.Length, InteropUtil.NumberOfFileChars);
            pathToShow.CopyTo(0, chars, 0, length);
          }
        }
        catch
        {
        }

        Marshal.Copy(chars, 0, nativeBuffer, chars.Length);

        openFileName.lpstrFile = nativeBuffer;

        if (!AcceptFiles)
        {
          var str = string.Format("Folders\0*.{0}-{1}\0\0", Guid.NewGuid().ToString("N"), Guid.NewGuid().ToString("N"));
          filterBuffer = openFileName.lpstrFilter = Marshal.StringToCoTaskMemUni(str);
        }
        else
        {
          openFileName.lpstrFilter = IntPtr.Zero;
        }

        openFileName.nMaxCustFilter = 0;
        openFileName.nFilterIndex = 0;
        openFileName.nMaxFile = InteropUtil.NumberOfFileChars;
        openFileName.nMaxFileTitle = 0;
        openFileName.lpstrTitle = Title;
        openFileName.lpfnHook = m_hookDelegate;
        openFileName.templateID = InteropUtil.IDD_CustomOpenDialog;
        openFileName.hInstance = Marshal.GetHINSTANCE(typeof(OpenFileOrFolderDialog).Module);

        openFileName.Flags =
            InteropUtil.OFN_DONTADDTORECENT |
            InteropUtil.OFN_ENABLEHOOK |
            InteropUtil.OFN_ENABLESIZING |
            InteropUtil.OFN_NOTESTFILECREATE |
            InteropUtil.OFN_EXPLORER |
            InteropUtil.OFN_FILEMUSTEXIST |
            InteropUtil.OFN_PATHMUSTEXIST |
            InteropUtil.OFN_NODEREFERENCELINKS |
            InteropUtil.OFN_ENABLETEMPLATE |
            (ShowReadOnly ? 0 : InteropUtil.OFN_HIDEREADONLY);

        m_useCurrentDir = false;

        var ret = InteropUtil.GetOpenFileNameW(ref openFileName);
        //var extErrpr = InteropUtil.CommDlgExtendedError();
        //InteropUtil.CheckForWin32Error();

        if (m_useCurrentDir)
        {
          Path = m_currentFolder;
          return true;
        }
        else if (ret)
        {
          Marshal.Copy(nativeBuffer, chars, 0, chars.Length);
          var firstZeroTerm = ((IList)chars).IndexOf('\0');
          if (firstZeroTerm >= 0 && firstZeroTerm <= chars.Length - 1)
          {
            Path = new string(chars, 0, firstZeroTerm);
          }
        }
        return ret;
      }
      finally
      {
        Marshal.FreeCoTaskMem(nativeBuffer);
        if (filterBuffer != IntPtr.Zero)
        {
          Marshal.FreeCoTaskMem(filterBuffer);
        }
      }
    }
Example #2
0
        protected override bool RunDialog(IntPtr hwndOwner)
        {
            DialogUtil.Assume(Marshal.SystemDefaultCharSize == 2, "The character size should be 2");

            var    nativeBuffer = Marshal.AllocCoTaskMem(InteropUtil.NumberOfFileChars * 2);
            IntPtr filterBuffer = IntPtr.Zero;

            try
            {
                var openFileName = new InteropUtil.OpenFileName();
                openFileName.Initialize();
                openFileName.hwndOwner = hwndOwner;

                var chars = new char[InteropUtil.NumberOfFileChars];

                try
                {
                    if (File.Exists(Path))
                    {
                        if (AcceptFiles)
                        {
                            var fileName = System.IO.Path.GetFileName(Path);
                            var length   = Math.Min(fileName.Length, InteropUtil.NumberOfFileChars);
                            fileName.CopyTo(0, chars, 0, length);
                            openFileName.lpstrInitialDir = System.IO.Path.GetDirectoryName(Path);
                        }
                        else
                        {
                            openFileName.lpstrInitialDir = System.IO.Path.GetDirectoryName(Path);
                        }
                    }
                    else if (Directory.Exists(Path))
                    {
                        openFileName.lpstrInitialDir = Path;
                    }
                    else
                    {
                        //the path does not exist.
                        //We don't just want to throw it away, however.
                        //The initial path we get is most likely provided by the user in some way.
                        //It could be what they typed into a text box before clicking a browse button,
                        //or it could be a value they had entered previously that used to be valid, but now no longer exists.
                        //In any case, we don't want to throw out the user's text. So, we find the first parent
                        //directory of Path that exists on disk.
                        //We will set the initial directory to that path, and then set the initial file to
                        //the rest of the path. The user will get an error if the click "OK"m saying that the selected path
                        //doesn't exist, but that's ok. If we didn't do this, and showed the path, if they clicked
                        //OK without making changes we would actually change the selected path, which would be bad.
                        //This way, if the users want's to change the folder, he actually has to change something.
                        string pathToShow;
                        InitializePathDNE(Path, out openFileName.lpstrInitialDir, out pathToShow);
                        pathToShow = pathToShow ?? "";
                        var length = Math.Min(pathToShow.Length, InteropUtil.NumberOfFileChars);
                        pathToShow.CopyTo(0, chars, 0, length);
                    }
                }
                catch
                {
                }

                Marshal.Copy(chars, 0, nativeBuffer, chars.Length);

                openFileName.lpstrFile = nativeBuffer;

                if (!AcceptFiles)
                {
                    var str = string.Format("Folders\0*.{0}-{1}\0\0", Guid.NewGuid().ToString("N"), Guid.NewGuid().ToString("N"));
                    filterBuffer = openFileName.lpstrFilter = Marshal.StringToCoTaskMemUni(str);
                }
                else
                {
                    openFileName.lpstrFilter = IntPtr.Zero;
                }

                openFileName.nMaxCustFilter = 0;
                openFileName.nFilterIndex   = 0;
                openFileName.nMaxFile       = InteropUtil.NumberOfFileChars;
                openFileName.nMaxFileTitle  = 0;
                openFileName.lpstrTitle     = Title;
                openFileName.lpfnHook       = m_hookDelegate;
                openFileName.templateID     = InteropUtil.IDD_CustomOpenDialog;
                openFileName.hInstance      = Marshal.GetHINSTANCE(typeof(OpenFileOrFolderDialog).Module);

                openFileName.Flags =
                    InteropUtil.OFN_DONTADDTORECENT |
                    InteropUtil.OFN_ENABLEHOOK |
                    InteropUtil.OFN_ENABLESIZING |
                    InteropUtil.OFN_NOTESTFILECREATE |
                    InteropUtil.OFN_EXPLORER |
                    InteropUtil.OFN_FILEMUSTEXIST |
                    InteropUtil.OFN_PATHMUSTEXIST |
                    InteropUtil.OFN_NODEREFERENCELINKS |
                    InteropUtil.OFN_ENABLETEMPLATE |
                    (ShowReadOnly ? 0 : InteropUtil.OFN_HIDEREADONLY);

                m_useCurrentDir = false;

                var ret = InteropUtil.GetOpenFileNameW(ref openFileName);
                //var extErrpr = InteropUtil.CommDlgExtendedError();
                //InteropUtil.CheckForWin32Error();

                if (m_useCurrentDir)
                {
                    Path = m_currentFolder;
                    return(true);
                }
                else if (ret)
                {
                    Marshal.Copy(nativeBuffer, chars, 0, chars.Length);
                    var firstZeroTerm = ((IList)chars).IndexOf('\0');
                    if (firstZeroTerm >= 0 && firstZeroTerm <= chars.Length - 1)
                    {
                        Path = new string(chars, 0, firstZeroTerm);
                    }
                }
                return(ret);
            }
            finally
            {
                Marshal.FreeCoTaskMem(nativeBuffer);
                if (filterBuffer != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(filterBuffer);
                }
            }
        }