c#自定义保存对话框上的控件--如何禁用父文件夹按钮?

c#自定义保存对话框上的控件--如何禁用父文件夹按钮?,c#,savefiledialog,windows-messages,ofnhookproc,C#,Savefiledialog,Windows Messages,Ofnhookproc,我在这里的示例项目中工作: 我已经隐藏了顶部的地址/位置栏,并做了其他修改,但我一辈子都无法禁用允许您进入父文件夹的按钮。Ist在ToolbarWindow32类中,这就是问题所在。这是我目前拥有的,但它不起作用: int parentFolderWindow = GetDlgItem(parent, 0x440); //Doesn't work //ShowWindow((IntPtr)parentFolderWindow, SW_HIDE); //40961 gathered from

我在这里的示例项目中工作:

我已经隐藏了顶部的地址/位置栏,并做了其他修改,但我一辈子都无法禁用允许您进入父文件夹的按钮。Ist在ToolbarWindow32类中,这就是问题所在。这是我目前拥有的,但它不起作用:

int parentFolderWindow = GetDlgItem(parent, 0x440);

//Doesn't work
//ShowWindow((IntPtr)parentFolderWindow, SW_HIDE);

//40961 gathered from Spy++ watching messages when clicking on the control
// doesn't work
//SendMessage(parentFolderWindow, TB_ENABLEBUTTON, 40961, 0);

// doesn't work
//SendMessage(parentFolderWindow, TB_SETSTATE, 40961, 0);

//Comes back as '{static}', am I working with the wrong control maybe?
GetClassName((IntPtr)parentFolderWindow, lpClassName, (int)nLength);
或者,如果他们确实使用父文件夹按钮并转到我不希望他们去的地方,我可以查看他们登录的新目录,有没有办法强制导航返回


编辑:添加了截图

我不知道这是否可行。即使您禁用按钮,他们也可以键入
。\
并单击“保存”,这将使他们提高一个级别。不能完全禁用“文件名”文本框并维护对话框的功能

您最好使用和设置它的RootFolder属性,并要求用户键入文件名或自动生成文件名

如果要限制用户使用的文件夹不是
环境。SpecialFolder
,则需要进行一些工作,手动使用
ILCreateFromPath
调用
SHBrowseForFolder
,以获取要传递到BROWSEINFO.pidlRoot的路径的PIDLIST_绝对值

您可以反射
FolderBrowserDialog.RunDialog
以查看如何进行该调用

//返回为“{static}”,我是否使用了错误的控件

您知道您使用了错误的控件,您希望看到“ToolbarWindow32”返回。一个非常重要的问题,Codeproject.com代码的一个常见问题,是此代码无法按发布的方式继续工作。Windows自2004年以来变化太大。Vista是自那时以来第一个添加了一组全新的shell对话框的版本,它们基于。与以前的版本相比有了很大的改进,特别是通过界面定制对话框更为简洁。实际上并不是您想要做的事情,而且定制也不包括对导航栏的修补

IFileDialogEvents接口提供事件,您要查找的就是事件。旨在阻止用户离开当前文件夹,这是您真正想做的事情

虽然这在纸上看起来不错,但我应该提醒您不要尝试使用这些接口。与Windows外壳相关的任何一个常见问题是,它们只使得C++更容易使用。COM接口是一种“不友好”的接口,它基于IUnknown,没有类型库,您可以使用轻松添加对C#或VB.NET项目的引用。微软发布了“Vista桥”,使这些界面也可以从C#中使用。是的,恶心。双重恶心当你发现你必须这样做两次,这只适用于更高版本的Windows,有一个强烈的提示,你正在尝试这样做XP(从你找到的控制ID判断)

这根本不是你想要支持的东西。由于替代方法非常简单,因此请改用受支持的.NET FileOk事件。Winforms示例:

    private void SaveButton_Click(object sender, EventArgs e) {
        string requiredDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        using (var dlg = new SaveFileDialog()) {
            dlg.InitialDirectory = requiredDir;
            dlg.FileOk += (s, cea) => {
                string selectedDir = System.IO.Path.GetDirectoryName(dlg.FileName);
                if (string.Compare(requiredDir, selectedDir, StringComparison.OrdinalIgnoreCase) != 0) {
                    string msg = string.Format("Sorry, you cannot save to this directory.\r\nPlease select '{0}' instead", requiredDir);
                    MessageBox.Show(msg, "Invalid folder selection");
                    cea.Cancel = true;
                }
            };
            if (dlg.ShowDialog() == DialogResult.OK) {
                // etc...
            }
        }
    }

由于您需要此类自定义行为,而不是开发低级代码(这可能会在下一版本的windows中出现),因此可以尝试开发文件选择器表单

基本上,它是一个简单的树状视图+列表视图。微软有一个很好的解决方案


这将花费您半天的时间,但一旦您有了自定义表单,您就可以定义您需要的所有行为,而无需技巧和限制。

谢谢您提供的额外信息,但我已经在使用文件确定检查,以确保它们保存在正确的文件夹中或其子文件夹中。我也已经使用该演示项目完成了大部分工作(删除了地址栏,并进行了我自己的OnFolderChange检查,以便在我设置的文件夹上方显示窗口)。所以我希望保留这一点,只做最后的更改安全性不是问题,所以任何使用“.\”的人都不会对使用它感到困惑。我不能使用FolderBrowserDialog,因为这是用来将文件保存到云存储服务(如google drive)的,我需要向他们显示已经存在的文件,这样他们就不会意外覆盖任何内容。我担心如果他们在google drive文件夹中找到几个文件夹,然后开始捣乱文件夹向上按钮,他们会超调到临时文件夹区域。你试过查看吗