|
I'm having the same issue on W7 32-bit although I get a mysterious StackHash error at runtime. I'm also getting the error if I try either of these:
NativeMethods.Shell32.ILFree(relpidl);
NativeMethods.Shell32.ILFree(parentpidl);
I suspect it has something to do with how they are "combined" above with
ILCombine , but I just don't know enough about it to troubleshoot.
Did anyone ever solve this issue?
There are more things in heaven and on earth than are written of in your philosophies, Horatio.
|
|
|
|
|
Hi all,
I found a solution for this problem:
Go to the class FileDialog.cs
Go to the method
int NativeMethods.ICommDlgBrowser.OnDefaultCommand(IntPtr ppshv)
Replace the code at the end of the method :
NativeMethods.Shell32.ILFree(abspidl);
NativeMethods.Shell32.ILFree(relpidl);
NativeMethods.Shell32.ILFree(parentpidl);
NativeMethods.Kernel32.GlobalUnlock(stg.unionmember);
NativeMethods.Ole32.ReleaseStgMedium(ref stg);
by
NativeMethods.Shell32.ILFree(abspidl);
System.Threading.Thread.Sleep(30);
NativeMethods.Shell32.ILFree(relpidl);
System.Threading.Thread.Sleep(30);
NativeMethods.Shell32.ILFree(parentpidl);
System.Threading.Thread.Sleep(30);
NativeMethods.Kernel32.GlobalUnlock(stg.unionmember);
System.Threading.Thread.Sleep(30);
NativeMethods.Ole32.ReleaseStgMedium(ref stg);
regards,
|
|
|
|
|
Hmm, didn't work for me (Win7 32-bit). It seems like this routine sometimes works the first time its called, but subsequent calls don't work. Is it possible this is what you experienced?
There are more things in heaven and on earth than are written of in your philosophies, Horatio.
|
|
|
|
|
You're right, after many calls, it crach.
I try to find another solution
|
|
|
|
|
First, excellent work on this!
I've been using this dialog for several weeks and it's really excellent. The followup comments have resolved just about every issue I've had save for 2 (arguably 1, they're semi-related).
From the look-in dropdown if I select My Network Places I get nothing in the ShellBrowser. From looking at the code it appears that this simply wasn't implemented.
Regardless it's a real pain to traverse My Network Places -> Entire Network -> Microsoft Windows Network -> Domain -> Hostname, etc. What the default FileOpenDialog allows for is entering a UNC path in the File name comboBox and then enter/OK will browse to that location and you can select files from there. I'm struggling though with how to implement this behavior, specifically how to walk the PIDL tree of My Network Places to determine the PIDL of the Server/share that matches (if there is a match) whatever is typed into the File name combo box. Any ideas for how this could be accomplished.
FWIW I implemented the changes Frohmen psoted Sept 25th, 2008 on how to enable folder AND file selection, but I don't think that's what's preventing the UNC browsing functionality.
Thanks!
|
|
|
|
|
Hi, and I'm glad to hear that my dialog is useful to you.
I haven't had the time to update my article in a while, even though I've made some improvements.
But, I didn't actually know that My Network Places didn't work, but I have started trying to resolve the problem.
So far I have found out that the key to the solution is the WNet API (at least I think), but I haven't yet figured it all out.
This might take a while to implement, but I will return when I know more.
|
|
|
|
|
Wow that's a quick response for such an old article. Thanks for keeping up with it and anything you come up with! I was able to get My Network Places working by combining what you did with Desktop and My Documents in the Init() just using SpecialFolder.Network vs. SpecialFolder.Desktop, etc. Then I created an EnumNetwork() which follows the logic of EnumMyComputer() (probably needs to be refactored) that is called when EnumDesktop() comes across a PIDL matching the one defined for My Network Places in the Init(). Once that was done I was able to navigate all the way down to machine level, select a file, and it was returned correctly.
Now I'm working on trying to be able to type in a UNC path in the filename combobox and then have it traverse My Network Places looking for a match on hostname. I seem to be able to enumerate the Entire Network properly but getting the display name of the items is problematic for some reason. I believe I have the right enumeration of items because it loops 3 times (Microsoft Terminal Services, Microsoft Windows Network, Web Client Network) but the display name keeps coming back as Entire Network (or empty string in my other attempts).
I'll keep hacking at it (and I do mean hack). If I come up with something stable I'll be sure to post the code changes once they're vetted a bit.
|
|
|
|
|
Ok, so it looks like I finally accomplished what I was wanting to do with this component. Hopefully you find some use for it Frohmen.
These changes were made after implementing the select folders or files change listed in another post, just an FYI. I also did this all very quickly so there may be some sloppiness.
In constructor
internal NativeMethods.IShellFolder m_myNetFolder;
private IntPtr m_myNetPidl;
private IntPtr entireNetworkPidl = new IntPtr();
private IntPtr windowsNetworkPidl = new IntPtr();
private IntPtr lstPidl = new IntPtr();
private string m_myNetPath;
private string m_myNetName;
private const DOMAINNAME = "yourDomainNameHere";
In Init()
info = new NativeMethods.SHFILEINFO();
NativeMethods.Shell32.SHGetSpecialFolderLocation(IntPtr.Zero, (int)SpecialFolder.Network, out m_myNetPidl);
NativeMethods.Shell32.SHGetFileInfo(m_myNetPidl, 0, ref info, NativeMethods.cbFileInfo,
NativeMethods.SHGFI_PIDL | NativeMethods.SHGFI_DISPLAYNAME);
m_myNetName = info.szDisplayName;
In EnumDesktop() - right after the EnumComputer() if block
if (NativeMethods.Shell32.ILIsEqual(pidlSubItem, m_myNetPidl))
EnumMyNetPlaces();
New function EnumMyNetPlaces() - could probably refactor EnumMyComputer or something to reduce code but I was in a hurry
private void EnumMyNetPlaces()
{
IntPtr[] path;
int level = GetLevel(m_pidlAbsCurrent);
bool isMyNetChild = IsParentFolder(m_myNetPidl, m_pidlAbsCurrent, out path);
IntPtr myNetPtr;
if (m_desktopFolder.BindToObject(
m_myNetPidl,
IntPtr.Zero,
ref NativeMethods.IID_IShellFolder,
out myNetPtr) == NativeMethods.S_OK)
{
NativeMethods.IShellFolder myNetwork =
(NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(myNetPtr);
NativeMethods.IEnumIDList folderEnum;
NativeMethods.SHCONTF folderFlag =
NativeMethods.SHCONTF.SHCONTF_FOLDERS |
NativeMethods.SHCONTF.SHCONTF_INCLUDEHIDDEN;
if (myNetwork.EnumObjects(
IntPtr.Zero,
folderFlag,
out folderEnum) == NativeMethods.S_OK)
{
IntPtr pidlSubItem;
int celtFetched;
while (folderEnum.Next(1, out pidlSubItem, out celtFetched) == NativeMethods.S_OK &&
celtFetched == 1)
{
IntPtr abspidl = NativeMethods.Shell32.ILCombine(m_myNetPidl, pidlSubItem);
string text = GetDisplayName(m_desktopFolder, abspidl, NativeMethods.SHGNO.SHGDN_INFOLDER);
IntPtr[] pidls = new IntPtr[] { pidlSubItem };
NativeMethods.SHGFAO attribs = NativeMethods.SHGFAO.SFGAO_FILESYSANCESTOR;
myNetwork.GetAttributesOf(1, pidls, ref attribs);
if ((attribs & NativeMethods.SHGFAO.SFGAO_FILESYSANCESTOR) != 0)
lookInComboBox.Items.Add(new LookInComboBoxItem(text, abspidl, 2));
if (path != null && isMyNetChild && level >= 3 &&
text.Equals(GetDisplayName(m_desktopFolder, path[2], NativeMethods.SHGNO.SHGDN_INFOLDER)))
{
for (int i = 3; i < path.Length; i++)
{
string childText = GetDisplayName(m_desktopFolder, path[i]);
lookInComboBox.Items.Add(new LookInComboBoxItem(childText, path[i], i));
}
}
}
}
}
}
New function BrowseToUNCPath(string uncPath)
private void BrowseToUNCPath(string uncPath)
{
string[] uncPathBreakDown = uncPath.Split('\\');
string[] netPath = { "Entire Network", "Microsoft Windows Network", DOMAINNAME};
string[] fullPath = new string[netPath.Length + uncPathBreakDown.Length];
string serverName = uncPathBreakDown[0];
netPath.CopyTo(fullPath, 0);
uncPathBreakDown.CopyTo(fullPath, netPath.Length);
IntPtr rootPidl = m_myNetPidl;
IntPtr leafPidl = m_myNetPidl;
foreach (string pathItem in fullPath)
{
leafPidl = FindPidl(rootPidl, pathItem);
rootPidl = leafPidl;
}
((NativeMethods.IShellBrowser)this).BrowseObject(leafPidl, NativeMethods.SBSP_ABSOLUTE);
}
New function FindPidl(IntPtr root, string nodeName)
private IntPtr FindPidl(IntPtr root, string nodeName)
{
IntPtr currentPtr;
if (m_desktopFolder.BindToObject(
root,
IntPtr.Zero,
ref NativeMethods.IID_IShellFolder,
out currentPtr) == NativeMethods.S_OK)
{
NativeMethods.IShellFolder currentFolder =
(NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(currentPtr);
NativeMethods.IEnumIDList folderEnum;
NativeMethods.SHCONTF folderFlag =
NativeMethods.SHCONTF.SHCONTF_FOLDERS |
NativeMethods.SHCONTF.SHCONTF_INCLUDEHIDDEN;
if (currentFolder.EnumObjects(
IntPtr.Zero,
folderFlag,
out folderEnum) == NativeMethods.S_OK)
{
IntPtr pidlSubItem;
int celtFetched;
while (folderEnum.Next(1, out pidlSubItem, out celtFetched) == NativeMethods.S_OK &&
celtFetched == 1)
{
IntPtr abspidl = NativeMethods.Shell32.ILCombine(root, pidlSubItem);
string text = "";
if (nodeName == "Entire Network")
text = GetDisplayName(m_desktopFolder, abspidl, NativeMethods.SHGNO.SHGDN_INFOLDER);
else
text = GetDisplayName(m_desktopFolder, abspidl, NativeMethods.SHGNO.SHGDN_FORPARSING);
if (text.IndexOf('\\') > -1)
text = text.Substring(text.LastIndexOf('\\') + 1, text.Length - (text.LastIndexOf('\\') + 1));
if (text.ToLower() == nodeName.ToLower())
{
return abspidl;
}
}
}
}
return m_desktopPidl;
}
If block added to OnFileOK
if (fileNameComboBox.Text != "" && fileNameComboBox.Text.Substring(0, 2) == @"\\")
{
string servername = fileNameComboBox.Text.Substring(2, fileNameComboBox.Text.Length - 2);
if (servername.Substring(servername.Length - 1, 1) == "\\")
servername = servername.Substring(0, servername.Length - 1);
BrowseToUNCPath(servername);
fileNameComboBox.Text = "";
}
else
|
|
|
|
|
I am missing the ability to set the column sort order.
Why not saving the last view in registry?
Regards
Chris
|
|
|
|
|
Hi,
I have continued to explore his code (very interesting). I found out that I sometimes get :
"Warning 1 Could not find type 'FileDialogs.LookInComboBox'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built."
(line 375) : “Warning 2 The variable 'lookInComboBox' is either undeclared or was never assigned. FileDialogs\FileDialog.Designer.cs”
I've noticed that at the first click (after "open") the combox is not working. only at the second click and sometimes not at all.
How to fix it?
Thanks again,
gilvini
|
|
|
|
|
Member 4179230 wrote: "Warning 1 Could not find type 'FileDialogs.LookInComboBox'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built."
(line 375) : “Warning 2 The variable 'lookInComboBox' is either undeclared or was never assigned. FileDialogs\FileDialog.Designer.cs”
These warnings sometimes occur when a project isn't built, especially when the project has some build errors. They can be ignored without any problems, just rebuild the project.
Member 4179230 wrote: I've noticed that at the first click (after "open") the combox is not working. only at the second click and sometimes not at all.
It is caused by a very poor solution created in my laziness. The combo box gets populated every time it's clicked and it just doesn't catch up sometimes. There isn't any easy way to fix this, however I'm soon about to update my article and code with some new features and some bugfixes (including the issue concerning the combo box).
Hope it helps!
|
|
|
|
|
Thanks for this great work. I am currently trying to use it in my open source project and it is very useful work.
Frohmen wrote: There isn't any easy way to fix this...
Edit: I have now found the actual source of the problem, it is with the DropDownHeight, not the DropDownWidth.
Just deleting the DropDownHeight set line, solves the problem.
Also, overriding the OnDropDown method instead of the event seems to produce a better results - do not know why.
There is another problem, the processing in the
protected override void WndProc(ref Message m)
It fails in dual monitors, since you are using the primary screen for your computations, moving the dialog to the secondary monitor will cause the drop-down to be still displayed in the primary monitor.
I do not know why it is needed, but I simply commented it out.
Again, thanks.
Best regards,
Paul.
Jesus Christ is LOVE! Please tell somebody.
modified on Tuesday, August 25, 2009 2:22 PM
|
|
|
|
|
Hi,
I would like to know if there is a way to replace ALL windows file open/save dialog with such application? (I mean to modify other application)
Regards,
Gilvini
|
|
|
|
|
Hi,
Thanks. Great code! I would appreciate if you could explain (I'm new to c#) why I' getting "The designer must create an instance of type 'FileDialogs.FileDialog' but it cannot because the type is declared as abstract. " when I'm trying to open SelectFolderDialog.cs, SaveFileDialog.cs or OpenFileDialog.cs?
Regards,
Gilvini
|
|
|
|
|
This error occur because the FileDialog base class is abstract, which isn't allowed by the designer. You can only open the FileDialog base class in designer mode. If however you must change the design of SelectFolderDialog, SaveFileDialog and OpenFileDialog separetly you must remove the abstract keyword from the FileDialog base class declaration.
public abstract partial class FileDialog : Form, NativeMethods.IShellBrowser, NativeMethods.ICommDlgBrowser,
NativeMethods.IServiceProvider
{
...
}
I'm not at the moment able to test this but it should work.
|
|
|
|
|
Hi,
Thanks for the quick response. This was the first thing I've done but unfortunately, with no success.
Regards,
gilvini
|
|
|
|
|
Great article.
bug: when you Open/Close "Open/Save dialog" several times, the dialog's position is changed.
|
|
|
|
|
This is standard Windows behaviour! The system decides where to put a form when it is displayed and this may well change from one Show() call to the next.
If you want to fix the position, set the Form to .StartPosition property to "Manual", set the .Left and .Top properties accordingly and then call the ShowDialog() method.
Thanks
Gee
|
|
|
|
|
|
Thanks a million for going through the trouble to implement a customizable FileDialog library. I made some modifications to suit my needs which are:
1) Display selected file names in the fileNameComboBox.
2) Added My Recent Documents and My Network Places to the placesBar.
3) Allow improved folder selection.
4) Restrict navigating away from the desktop.
5) Hide special folders on the desktop (My Documents, My Computer, My Network Places).
6) Added a Title Property.
I made all the changes in the FileDialog base class, aside from an additional item for My Network Places in the SpecialFolder enum. Other than the first two items all modifications can be turned on or off via the properties below.
FileDialog.HideSpecialFolders
FileDialog.DesktopOnly
FileDialog.FolderSelect
I noticed that others were looking for a couple of the features above so I'll post the changes in a reply to this message (To avoid having to scroll past it). Thanks again!
|
|
|
|
|
SpecialFolder new item:
MyNetwork = 0x12,
FileDialog design Changes:
FileDialog.MinimumSize = new Size(600, 420);
FileDialog member changes:
private static Padding FileViewPadding = new Padding(96, 28, 5, 53);
private bool m_DesktopOnly;
private bool m_FolderSelect;
private bool m_HideSpecialFolders;
private IntPtr m_myNetPidl;
private string m_myNetPath;
private string m_myNetName;
private IntPtr m_recentPidl;
private string m_recentPath;
private string m_recentName;
FileDialog method changes:
FileDialog.Init() changes:
private void Init()
{
NativeMethods.SHFILEINFO info;
info = new NativeMethods.SHFILEINFO();
NativeMethods.Shell32.SHGetSpecialFolderLocation(IntPtr.Zero, (int)SpecialFolder.MyComputer,
out m_myCompPidl);
NativeMethods.Shell32.SHGetFileInfo(m_myCompPidl, 0, ref info, NativeMethods.cbFileInfo,
NativeMethods.SHGFI_PIDL | NativeMethods.SHGFI_DISPLAYNAME);
m_myCompName = info.szDisplayName;
info = new NativeMethods.SHFILEINFO();
NativeMethods.Shell32.SHGetSpecialFolderLocation(IntPtr.Zero, (int)SpecialFolder.MyNetwork,
out m_myNetPidl);
NativeMethods.Shell32.SHGetFileInfo(m_myNetPidl, 0, ref info, NativeMethods.cbFileInfo,
NativeMethods.SHGFI_PIDL | NativeMethods.SHGFI_DISPLAYNAME);
m_myNetName = info.szDisplayName;
info = new NativeMethods.SHFILEINFO();
NativeMethods.Shell32.SHGetSpecialFolderLocation(IntPtr.Zero, (int)SpecialFolder.Recent,
out m_recentPidl);
NativeMethods.Shell32.SHGetFileInfo(m_recentPidl, 0, ref info, NativeMethods.cbFileInfo,
NativeMethods.SHGFI_PIDL | NativeMethods.SHGFI_DISPLAYNAME);
m_recentName = info.szDisplayName;
NativeMethods.Shell32.SHGetSpecialFolderLocation(IntPtr.Zero, (int)SpecialFolder.Desktop, out m_desktopPidl);
IntPtr desktopFolderPtr;
NativeMethods.Shell32.SHGetDesktopFolder(out desktopFolderPtr);
m_desktopFolder = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(desktopFolderPtr);
m_desktopPath = GetDisplayName(m_desktopFolder, m_desktopPidl, NativeMethods.SHGNO.SHGDN_FORPARSING);
m_currentFolder = m_desktopFolder;
NativeMethods.SHGFAO pdwAttributes = 0;
m_desktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, NativeMethods.CLSID_MyDocuments, IntPtr.Zero,
out m_myDocsPidl, pdwAttributes);
info = new NativeMethods.SHFILEINFO();
NativeMethods.Shell32.SHGetFileInfo(m_myDocsPidl, 0, ref info, NativeMethods.cbFileInfo,
NativeMethods.SHGFI_PIDL | NativeMethods.SHGFI_DISPLAYNAME);
m_myDocsName = info.szDisplayName;
m_myDocsPath = GetDisplayName(m_desktopFolder, m_myDocsPidl, NativeMethods.SHGNO.SHGDN_FORPARSING);
m_myNetPath = GetDisplayName(m_desktopFolder, m_myNetPidl, NativeMethods.SHGNO.SHGDN_FORPARSING);
m_recentPath = GetDisplayName(m_desktopFolder, m_recentPidl, NativeMethods.SHGNO.SHGDN_FORPARSING);
}
FileDialog.InitPlacesBar() changes:
private void InitPlacesBar()
{
int lineLimit = 13;
ToolStripButton recentDocumentsButton = new ToolStripButton(ShellImageList.GetImage(SpecialFolder.Recent));
recentDocumentsButton.Tag = m_recentPidl;
recentDocumentsButton.Text = this.InsertLineBreaks(m_recentName, lineLimit);
placesBar.Items.Add(recentDocumentsButton);
ToolStripButton desktopButton = new ToolStripButton(ShellImageList.GetImage(SpecialFolder.Desktop));
desktopButton.Tag = m_desktopPidl;
desktopButton.Text = this.InsertLineBreaks(GetDisplayName(m_desktopFolder, m_desktopPidl, NativeMethods.SHGNO.SHGDN_INFOLDER), lineLimit);
placesBar.Items.Add(desktopButton);
ToolStripButton myDocsButton = new ToolStripButton(ShellImageList.GetImage(SpecialFolder.MyDocuments));
myDocsButton.Tag = m_myDocsPidl;
myDocsButton.Text = this.InsertLineBreaks(m_myDocsName, lineLimit);
placesBar.Items.Add(myDocsButton);
ToolStripButton myCompButton = new ToolStripButton(ShellImageList.GetImage(SpecialFolder.MyComputer));
myCompButton.Tag = m_myCompPidl;
myCompButton.Text = this.InsertLineBreaks(m_myCompName, lineLimit);
placesBar.Items.Add(myCompButton);
ToolStripButton myNetButton = new ToolStripButton(ShellImageList.GetImage(SpecialFolder.MyNetwork));
myNetButton.Tag = m_myNetPidl;
myNetButton.Text = this.InsertLineBreaks(m_myNetName, lineLimit);
placesBar.Items.Add(myNetButton);
foreach (ToolStripItem placeItem in placesBar.Items)
{
placeItem.Margin = new Padding(1, 0, 0, 0);
placeItem.Padding = new Padding(0, 8, 0, 8);
placeItem.ImageAlign = ContentAlignment.BottomCenter;
placeItem.TextImageRelation = TextImageRelation.ImageAboveText;
}
}
private string InsertLineBreaks(string text, int lineLimit)
{
string[] splitText = text.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
text = "";
int charactersOnCurrentLine = 0;
for (int wordIndex = 0; wordIndex < splitText.Length; wordIndex++)
{
string word = splitText[wordIndex];
if (word.Length + charactersOnCurrentLine + 1 <= lineLimit)
{
if (charactersOnCurrentLine != 0)
text += " ";
text += word;
charactersOnCurrentLine += word.Length + 1;
}
else
{
text += "\r\n" + word;
charactersOnCurrentLine = word.Length;
}
}
return text;
}
FileDialog.OnFileOK(object sender, EventArgs e) changes:
protected virtual void OnFileOK(object sender, EventArgs e)
{
if (m_selectedPidls != null && m_selectedPidls.Length > 0)
{
IntPtr[] pidls = new IntPtr[] { m_selectedPidls[0] };
NativeMethods.SHGFAO attribs = NativeMethods.SHGFAO.SFGAO_STREAM;
m_currentFolder.GetAttributesOf(1, pidls, ref attribs);
if ((attribs & NativeMethods.SHGFAO.SFGAO_STREAM) == 0 && !this.FolderSelect)
{
((NativeMethods.IShellBrowser)this).BrowseObject(m_selectedPidls[0], NativeMethods.SBSP_RELATIVE);
}
else
{
int index = 0;
string[] fileNames = new string[m_selectedPidls.Length];
fileNames[0] =
GetDisplayName(m_currentFolder, m_selectedPidls[0], NativeMethods.SHGNO.SHGDN_FORPARSING);
for (int i = 1; i < m_selectedPidls.Length; i++)
{
pidls = new IntPtr[] { m_selectedPidls[i] };
attribs = NativeMethods.SHGFAO.SFGAO_STREAM;
m_currentFolder.GetAttributesOf(1, pidls, ref attribs);
if ((attribs & NativeMethods.SHGFAO.SFGAO_STREAM) == NativeMethods.SHGFAO.SFGAO_STREAM || this.FolderSelect)
{
fileNames[++index] =
GetDisplayName(m_currentFolder, m_selectedPidls[i], NativeMethods.SHGNO.SHGDN_FORPARSING);
}
}
if (fileNames.Length > index + 1)
Array.Resize(ref fileNames, index + 1);
if (!File.Exists(fileNames[0]) || PromptFileOverwrite(Path.GetFileName(fileNames[0])))
{
m_fileNames = fileNames;
DialogResult = DialogResult.OK;
}
}
}
else
{
string path = fileNameComboBox.Text, driveName;
string trimmedPath = path.Trim();
if (path != trimmedPath)
{
m_ignoreFileNameChange = true;
path = trimmedPath;
fileNameComboBox.Text = trimmedPath;
}
if (string.IsNullOrEmpty(path))
{
if (!string.IsNullOrEmpty(m_currentFilePattern) && m_shellView != null)
{
m_currentFilePattern = string.Empty;
m_shellView.Refresh();
}
return;
}
bool lastCharIsSeparator = (path[path.Length - 1] == Path.DirectorySeparatorChar);
UpdateFileNameMRU(path);
bool isPathRooted = Path.IsPathRooted(path);
string orgPath = path;
if (!isPathRooted)
path =
Path.Combine(
GetDisplayName(m_desktopFolder, m_pidlAbsCurrent, NativeMethods.SHGNO.SHGDN_FORPARSING),
path);
if (path.Contains(".."))
path = Path.GetFullPath(path);
if (Directory.Exists(path))
{
IntPtr pidl;
m_desktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, path, IntPtr.Zero, out pidl, 0);
((NativeMethods.IShellBrowser)this).BrowseObject(pidl, NativeMethods.SBSP_ABSOLUTE);
fileNameComboBox.Text = string.Empty;
return;
}
else if (path.Length <= 3 && PathUtils.PathRootIsDrive(path, out driveName))
{
DriveInfo di = new DriveInfo(driveName);
if (di.DriveType == DriveType.CDRom)
{
string message = "The selected disk drive is not in use. Check to make sure a disk is inserted.";
while (!di.IsReady)
{
if (
MessageBoxWithFocusRestore(message, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) ==
DialogResult.Cancel)
{
fileNameComboBox.SelectAll();
return;
}
}
}
else if (di.DriveType == DriveType.NoRootDirectory)
{
string message =
string.Format("The drive '{0}' is not valid. Enter a valid drive letter.",
driveName.Substring(0, 2));
MessageBoxWithFocusRestore(message, MessageBoxButtons.OK, MessageBoxIcon.Information);
fileNameComboBox.SelectAll();
return;
}
IntPtr pidl;
m_desktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, driveName, IntPtr.Zero, out pidl, 0);
((NativeMethods.IShellBrowser)this).BrowseObject(pidl, NativeMethods.SBSP_ABSOLUTE);
fileNameComboBox.Text = string.Empty;
return;
}
else if (lastCharIsSeparator)
{
string message =
string.Format(
@"The folder '{0}' isn't accessible. The folder may be located in an unavailable location, protected with a password, or the filename contains a / or \.",
path);
MessageBoxWithFocusRestore(message, MessageBoxButtons.OK, MessageBoxIcon.Information);
fileNameComboBox.SelectAll();
return;
}
string parentPath = Path.GetDirectoryName(path);
if (File.Exists(path))
{
if (PromptFileOverwrite(Path.GetFileName(path)))
{
FileName = path;
DialogResult = DialogResult.OK;
return;
}
}
else if (Directory.Exists(parentPath))
{
string currentPath =
GetDisplayName(m_desktopFolder, m_pidlAbsCurrent, NativeMethods.SHGNO.SHGDN_FORPARSING);
if (!isPathRooted)
{
if (parentPath != currentPath)
{
IntPtr pidl;
m_currentFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, Path.GetDirectoryName(orgPath),
IntPtr.Zero, out pidl, 0);
((NativeMethods.IShellBrowser)this).BrowseObject(pidl, NativeMethods.SBSP_RELATIVE);
fileNameComboBox.Text = Path.GetFileName(orgPath);
}
PromptFileCreate();
}
else
{
if (parentPath != currentPath)
{
IntPtr pidl;
m_desktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, parentPath, IntPtr.Zero, out pidl,
0);
((NativeMethods.IShellBrowser)this).BrowseObject(pidl, NativeMethods.SBSP_ABSOLUTE);
fileNameComboBox.Text = Path.GetFileName(path);
}
PromptFileCreate();
}
}
else
{
if (PromptFileCreate())
{
FileName = path;
DialogResult = DialogResult.OK;
return;
}
}
}
}
FileDialog.NativeMethods.IShellBrowser.BrowseObject(IntPtr pidl, uint wFlags) changes:
int NativeMethods.IShellBrowser.BrowseObject(IntPtr pidl, uint wFlags)
{
int hr;
IntPtr folderTmpPtr;
NativeMethods.IShellFolder folderTmp = null;
IntPtr pidlTmp = IntPtr.Zero;
if (NativeMethods.Shell32.ILIsEqual(pidl, m_desktopPidl))
{
pidlTmp = NativeMethods.Shell32.ILClone(m_desktopPidl);
folderTmp = m_desktopFolder;
}
else if ((wFlags & NativeMethods.SBSP_RELATIVE) != 0)
{
if ((hr = m_currentFolder.BindToObject(pidl, IntPtr.Zero, ref NativeMethods.IID_IShellFolder,
out folderTmpPtr)) != NativeMethods.S_OK)
return hr;
pidlTmp = NativeMethods.Shell32.ILCombine(m_pidlAbsCurrent, pidl);
folderTmp = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(folderTmpPtr);
}
else if ((wFlags & NativeMethods.SBSP_PARENT) != 0)
{
pidlTmp = GetParentPidl(m_pidlAbsCurrent);
string pathTmp = GetDisplayName(m_desktopFolder, pidlTmp, NativeMethods.SHGNO.SHGDN_FORPARSING);
if (pathTmp.Equals(m_desktopPath))
folderTmp = m_desktopFolder;
else
{
if ((hr = m_desktopFolder.BindToObject(pidlTmp, IntPtr.Zero, ref NativeMethods.IID_IShellFolder,
out folderTmpPtr)) != NativeMethods.S_OK)
return hr;
folderTmp = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(folderTmpPtr);
}
}
else
{
pidlTmp = NativeMethods.Shell32.ILClone(pidl);
if ((hr = m_desktopFolder.BindToObject(pidlTmp, IntPtr.Zero, ref NativeMethods.IID_IShellFolder,
out folderTmpPtr)) != NativeMethods.S_OK)
return hr;
folderTmp = (NativeMethods.IShellFolder)Marshal.GetObjectForIUnknown(folderTmpPtr);
}
if (folderTmp == null)
{
NativeMethods.Shell32.ILFree(pidlTmp);
return NativeMethods.E_FAIL;
}
string path = GetDisplayName(m_desktopFolder, pidlTmp, NativeMethods.SHGNO.SHGDN_FORPARSING);
if (path == m_myDocsPath && !NativeMethods.Shell32.ILIsEqual(pidlTmp, m_myDocsPidl))
{
NativeMethods.Shell32.ILFree(pidlTmp);
pidlTmp = NativeMethods.Shell32.ILClone(m_myDocsPidl);
}
string driveName;
if (PathUtils.PathRootIsDrive(path, out driveName))
{
DriveInfo di = new DriveInfo(driveName);
if (di.DriveType == DriveType.CDRom)
{
string message = "The selected disk drive is not in use. Check to make sure a disk is inserted.";
while (!di.IsReady)
{
if (MessageBoxWithFocusRestore(message, MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) ==
DialogResult.Cancel)
return NativeMethods.S_OK;
}
}
else if (di.DriveType == DriveType.NoRootDirectory)
{
string message =
string.Format("The drive '{0}' is not valid. Enter a valid drive letter.",
driveName.Substring(0, 2));
MessageBoxWithFocusRestore(message, MessageBoxButtons.OK, MessageBoxIcon.Information);
return NativeMethods.S_OK;
}
}
if (!this.DesktopOnly || NativeMethods.Shell32.ILIsEqual(pidl, m_desktopPidl))
{
m_currentFolder = folderTmp;
NativeMethods.FOLDERSETTINGS fs = new NativeMethods.FOLDERSETTINGS();
NativeMethods.IShellView lastIShellView = m_shellView;
if (lastIShellView != null)
lastIShellView.GetCurrentInfo(ref fs);
else
{
fs = new NativeMethods.FOLDERSETTINGS();
fs.fFlags = (uint)m_flags;
fs.ViewMode = (uint)m_viewMode;
}
IntPtr iShellViewPtr;
hr = folderTmp.CreateViewObject(Handle, ref NativeMethods.IID_IShellView, out iShellViewPtr);
if (hr == NativeMethods.S_OK)
{
m_shellView = (NativeMethods.IShellView)Marshal.GetObjectForIUnknown(iShellViewPtr);
m_hWndListView = IntPtr.Zero;
NativeMethods.RECT rc =
new NativeMethods.RECT(FileViewPadding.Left, FileViewPadding.Top,
ClientSize.Width - FileViewPadding.Right,
ClientSize.Height - FileViewPadding.Bottom);
int res;
try
{
res = m_shellView.CreateViewWindow(lastIShellView, ref fs, this, ref rc, ref m_hWndListView);
}
catch (COMException)
{
return NativeMethods.E_FAIL;
}
if (res < 0)
return NativeMethods.E_FAIL;
bool shellViewHasFocus = m_shellViewHasFocus;
if (lastIShellView != null)
{
lastIShellView.GetCurrentInfo(ref fs);
lastIShellView.UIActivate((uint)NativeMethods.SVUIA_STATUS.SVUIA_DEACTIVATE);
lastIShellView.DestroyViewWindow();
Marshal.ReleaseComObject(lastIShellView);
}
m_shellView.UIActivate(shellViewHasFocus
? (uint)NativeMethods.SVUIA_STATUS.SVUIA_ACTIVATE_FOCUS
: (uint)NativeMethods.SVUIA_STATUS.SVUIA_ACTIVATE_NOFOCUS);
IntPtr previousPidl = m_pidlAbsCurrent;
m_pidlAbsCurrent = pidlTmp;
UpdateUI(previousPidl);
m_selectedPidls = null;
OnSelectionChanged();
}
}
return NativeMethods.S_OK;
}
FileDialog.OnSelectionChanged() changes:
protected virtual void OnSelectionChanged()
{
if (m_selectedPidls == null)
fileNameComboBox.Text = "";
else
{
if (this.FolderSelect)
{
for (int pidlIndex = 0; pidlIndex < this.m_selectedPidls.Length; pidlIndex++)
{
m_ignoreFileNameChange = true;
if (pidlIndex == 0 && m_selectedPidls.Length == 1)
fileNameComboBox.Text = GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]);
else if (pidlIndex == 0)
fileNameComboBox.Text = "\"" + GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]) + "\"";
else
fileNameComboBox.Text += " \"" + GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]) + "\"";
}
}
else
{
bool firstListed = false;
bool secondListed = false;
for (int pidlIndex = 0; pidlIndex < this.m_selectedPidls.Length; pidlIndex++)
{
IntPtr[] pidls = new IntPtr[] { m_selectedPidls[pidlIndex] };
NativeMethods.SHGFAO attribs = NativeMethods.SHGFAO.SFGAO_FILESYSANCESTOR |
NativeMethods.SHGFAO.SFGAO_STREAM |
NativeMethods.SHGFAO.SFGAO_NEWCONTENT;
m_currentFolder.GetAttributesOf(1, pidls, ref attribs);
bool isFile = ((attribs & NativeMethods.SHGFAO.SFGAO_STREAM) == NativeMethods.SHGFAO.SFGAO_STREAM);
if (isFile)
m_ignoreFileNameChange = true;
if (m_selectedPidls.Length == 1 && isFile)
{
fileNameComboBox.Text = GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]);
firstListed = true;
}
else if (!firstListed && isFile)
{
fileNameComboBox.Text = "\"" + GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]) + "\"";
firstListed = true;
}
else if (isFile)
{
fileNameComboBox.Text += " \"" + GetDisplayName(m_currentFolder, m_selectedPidls[pidlIndex]) + "\"";
secondListed = true;
}
}
if (!firstListed)
{
m_ignoreFileNameChange = true;
fileNameComboBox.Text = "";
}
else if (!secondListed && m_selectedPidls.Length > 1)
{
m_ignoreFileNameChange = true;
fileNameComboBox.Text = fileNameComboBox.Text.Replace("\"", "");
}
}
}
}
FileDialog.NativeMethods.ICommDlgBrowser.IncludeObject(IntPtr ppshv, IntPtr pidl) changes:
int NativeMethods.ICommDlgBrowser.IncludeObject(IntPtr ppshv, IntPtr pidl)
{
IntPtr strr = Marshal.AllocCoTaskMem(NativeMethods.MAX_PATH * 2 + 4);
Marshal.WriteInt32(strr, 0, 0);
StringBuilder buf = new StringBuilder(NativeMethods.MAX_PATH);
IntPtr[] pidls = new IntPtr[] { pidl };
NativeMethods.SHGFAO attribs = NativeMethods.SHGFAO.SFGAO_FILESYSANCESTOR |
NativeMethods.SHGFAO.SFGAO_STREAM |
NativeMethods.SHGFAO.SFGAO_NEWCONTENT;
m_currentFolder.GetAttributesOf(1, pidls, ref attribs);
bool isFile = ((attribs & NativeMethods.SHGFAO.SFGAO_STREAM) == NativeMethods.SHGFAO.SFGAO_STREAM);
if (!isFile && this.HideSpecialFolders)
{
if (NativeMethods.Shell32.ILIsEqual(pidl, this.m_myDocsPidl)
|| NativeMethods.Shell32.ILIsEqual(pidl, this.m_myCompPidl)
|| NativeMethods.Shell32.ILIsEqual(pidl, this.m_myNetPidl))
return NativeMethods.S_FALSE;
}
if (m_excludeFiles && (isFile || (attribs & NativeMethods.SHGFAO.SFGAO_FILESYSANCESTOR) == 0))
return NativeMethods.S_FALSE;
else if (!isFile && (attribs & NativeMethods.SHGFAO.SFGAO_FILESYSANCESTOR) == 0)
return NativeMethods.S_FALSE;
if (m_currentFolder.GetDisplayNameOf(
pidl,
NativeMethods.SHGNO.SHGDN_FORPARSING,
strr) == NativeMethods.S_OK)
{
NativeMethods.Shlwapi.StrRetToBuf(strr, pidl, buf, NativeMethods.MAX_PATH);
string path = buf.ToString();
string name = path.Substring(path.LastIndexOf('\\') + 1);
if (CreateNewFolder(path, pidl))
return NativeMethods.S_OK;
if (m_excludeFiles)
return NativeMethods.S_OK;
FileType fileType = (FileType)fileTypeComboBox.SelectedItem;
if (m_currentFilePattern != string.Empty)
{
if (isFile && !Regex.IsMatch(name, m_currentFilePattern, RegexOptions.Compiled))
return NativeMethods.S_FALSE;
}
else if (fileType != null)
{
if (fileType.IncludeAllFiles)
return NativeMethods.S_OK;
if (isFile && !Regex.IsMatch(name, fileType.FilterPattern, RegexOptions.Compiled))
return NativeMethods.S_FALSE;
}
}
return NativeMethods.S_OK;
}
New FileDialog properties:
[Description("Indicates whether the dialog box does not allow navigation away from the desktop.")]
[Category("Behavior")]
[DefaultValue(false)]
public bool DesktopOnly
{
get { return this.m_DesktopOnly; }
set
{
this.m_DesktopOnly = value;
if (value)
{
this.lookInComboBox.Enabled = false;
this.lookInLabel.Enabled = false;
this.placesBar.Visible = false;
this.fileNameLabel.Location = new Point(5, this.fileNameLabel.Location.Y);
this.fileTypeLabel.Location = new Point(5, this.fileTypeLabel.Location.Y);
this.fileTypeComboBox.Location = new Point(81, this.fileTypeComboBox.Location.Y);
this.fileNameComboBox.Location = new Point(81, this.fileNameComboBox.Location.Y);
this.fileNameComboBox.Width += 90;
this.fileTypeComboBox.Width += 90;
FileViewPadding = new Padding(5, 28, 5, 53);
}
else
{
this.lookInComboBox.Enabled = true;
this.lookInLabel.Enabled = true;
this.placesBar.Visible = true;
this.fileNameLabel.Location = new Point(95, this.fileNameLabel.Location.Y);
this.fileTypeLabel.Location = new Point(95, this.fileTypeLabel.Location.Y);
this.fileTypeComboBox.Location = new Point(171, this.fileTypeComboBox.Location.Y);
this.fileNameComboBox.Location = new Point(171, this.fileNameComboBox.Location.Y);
this.fileNameComboBox.Width -= 90;
this.fileTypeComboBox.Width -= 90;
FileViewPadding = new Padding(96, 28, 5, 53);
}
}
}
[Description("Indicates whether the dialog box allows folders to be selected.")]
[Category("Behavior")]
[DefaultValue(false)]
public bool FolderSelect
{
get { return m_FolderSelect; }
set { m_FolderSelect = value; }
}
[Description("Indicates whether the dialog box hides special folders.")]
[Category("Behavior")]
[DefaultValue(false)]
public bool HideSpecialFolders
{
get { return m_HideSpecialFolders; }
set { m_HideSpecialFolders = value; }
}
[Description("The string to display on the title bar of the dialog box.")]
[Category("Appearance")]
public string Title
{
get { return this.Text; }
set { this.Text = value; }
}
|
|
|
|
|
I am unable to unzip FileDialogs_src.zip since the last update .
Ark on Linux says unknown compression method 98
ZipGenius on Windows says enter password.
|
|
|
|
|
I cannot open this code either :'(
Gee
|
|
|
|
|
Yes, the zip file is partially corrupted. But you should still be able to extract all files except for the .sln and .xml.
Some decompressors, like 7-zip, do not let you extract anything if some files are corrupted. Windows explorer zip extractor worked.
|
|
|
|
|
In NativeMethods.cs the FOLDERVIEWMODE enumeration is incorrectly tagged with the [Flags] attribute.
|
|
|
|
|