为什么FolderBrowserDialog对话框不滚动到选定的文件夹?

2023-12-23

如该屏幕截图所示,所选文件夹不在视图中。需要向下滚动才能查看所选文件夹。

同一对话框显示在不同计算机上可见的选定文件夹

我在两台装有 Windows 7 的计算机上运行它。它在一台计算机上运行正常,但在第二台计算机上运行不正常。它看起来与 Windows 环境有关,而不是一些代码问题?谁能提出任何修复建议?

代码没有变化。我使用了来自不同驱动器的较长路径,但结果是相同的。

private void TestDialog_Click ( object sender, EventArgs e )
        {
            //Last path store the selected path, to show the same directory as selected on next application launch.
            //Properties.Settings.Default.LastPath

            FolderBrowserDialog dlgFolder = new FolderBrowserDialog ();

            dlgFolder.RootFolder = Environment.SpecialFolder.DesktopDirectory;

            dlgFolder.SelectedPath = Properties.Settings.Default.LastPath;

            if (dlgFolder.ShowDialog () == System.Windows.Forms.DialogResult.OK)
            {

                Properties.Settings.Default.LastPath = dlgFolder.SelectedPath;               

                Properties.Settings.Default.Save ();
            }

        }

根本问题是糟糕的设计决策FolderBrowserDialog。首先,我们需要认识到,FolderBrowserDialog不是 .NET 控件,而是Common Dialog并且是 Windows 的一部分。该对话框的设计者选择不向 TreeView 控件发送TVM_ENSUREVISIBLE显示对话框并选择初始文件夹后的消息。此消息导致 TreeView 控件滚动,以便当前选定的项目在窗口中可见。

因此,解决这个问题我们需要做的就是发送 TreeView,它是FolderBrowserDialog the TVM_ENSUREVISIBLE消息,一切都会很棒。正确的?嗯,没那么快。这确实是答案,但有些事情阻碍了我们。

  • 首先,因为FolderBrowserDialog并不是真正的 .NET 控件,它没有内部Controls收藏。这意味着我们不能仅仅从.NET 中查找和访问TreeView 子控件。

  • 二、.NET的设计者FolderBrowserDialog班级决定seal这个班。这个不幸的决定阻止我们从中派生并覆盖窗口消息处理程序。如果我们能够做到这一点,我们可能会尝试发布TVM_ENSUREVISIBLE当我们收到消息时WM_SHOWWINDOW消息处理程序中的消息。

  • 第三个问题是我们无法发送TVM_ENSUREVISIBLE消息直到树视图控件实际上作为真实窗口存在,并且直到我们调用ShowDialog方法。但是,此方法会阻塞,因此一旦调用此方法,我们将没有机会发布消息。

为了解决这些问题,我创建了一个静态帮助器类,其中包含一个方法,可用于显示FolderBrowserDialog,并将使其滚动到所选文件夹。我通过开始一个短片来解决这个问题Timer就在调用对话之前ShowDialog方法,然后追踪该句柄TreeView控制在Timer处理程序(即,显示对话后)并发送我们的TVM_ENSUREVISIBLE信息。

这个解决方案并不完美,因为它依赖于一些先验知识FolderBrowserDialog。具体来说,我使用窗口标题找到对话。这会因非英语安装而中断。我使用对话项 ID(而不是标题文本或类名称)来追踪对话中的子控件,因为我觉得随着时间的推移,这会更可靠。

此代码已在 Windows 7(64 位)和 Windows XP 上进行了测试。

这是代码: (你可能需要:using System.Runtime.InteropServices;)

public static class FolderBrowserLauncher
{
    /// <summary>
    /// Using title text to look for the top level dialog window is fragile.
    /// In particular, this will fail in non-English applications.
    /// </summary>
    const string _topLevelSearchString = "Browse For Folder";

    /// <summary>
    /// These should be more robust.  We find the correct child controls in the dialog
    /// by using the GetDlgItem method, rather than the FindWindow(Ex) method,
    /// because the dialog item IDs should be constant.
    /// </summary>
    const int _dlgItemBrowseControl = 0;
    const int _dlgItemTreeView = 100;

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32.dll")]
    static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    /// <summary>
    /// Some of the messages that the Tree View control will respond to
    /// </summary>
    private const int TV_FIRST = 0x1100;
    private const int TVM_SELECTITEM = (TV_FIRST + 11);
    private const int TVM_GETNEXTITEM = (TV_FIRST + 10);
    private const int TVM_GETITEM = (TV_FIRST + 12);
    private const int TVM_ENSUREVISIBLE = (TV_FIRST + 20);

    /// <summary>
    /// Constants used to identity specific items in the Tree View control
    /// </summary>
    private const int TVGN_ROOT = 0x0;
    private const int TVGN_NEXT = 0x1;
    private const int TVGN_CHILD = 0x4;
    private const int TVGN_FIRSTVISIBLE = 0x5;
    private const int TVGN_NEXTVISIBLE = 0x6;
    private const int TVGN_CARET = 0x9;


    /// <summary>
    /// Calling this method is identical to calling the ShowDialog method of the provided
    /// FolderBrowserDialog, except that an attempt will be made to scroll the Tree View
    /// to make the currently selected folder visible in the dialog window.
    /// </summary>
    /// <param name="dlg"></param>
    /// <param name="parent"></param>
    /// <returns></returns>
    public static DialogResult ShowFolderBrowser( FolderBrowserDialog dlg, IWin32Window parent = null )
    {
        DialogResult result = DialogResult.Cancel;
        int retries = 10;

        using (Timer t = new Timer())
        {
            t.Tick += (s, a) =>
            {
                if (retries > 0)
                {
                    --retries;
                    IntPtr hwndDlg = FindWindow((string)null, _topLevelSearchString);
                    if (hwndDlg != IntPtr.Zero)
                    {
                        IntPtr hwndFolderCtrl = GetDlgItem(hwndDlg, _dlgItemBrowseControl);
                        if (hwndFolderCtrl != IntPtr.Zero)
                        {
                            IntPtr hwndTV = GetDlgItem(hwndFolderCtrl, _dlgItemTreeView);

                            if (hwndTV != IntPtr.Zero)
                            {
                                IntPtr item = SendMessage(hwndTV, (uint)TVM_GETNEXTITEM, new IntPtr(TVGN_CARET), IntPtr.Zero);
                                if (item != IntPtr.Zero)
                                {
                                    SendMessage(hwndTV, TVM_ENSUREVISIBLE, IntPtr.Zero, item);
                                    retries = 0;
                                    t.Stop();
                                }
                            }
                        }
                    }
                }

                else
                {
                    //
                    //  We failed to find the Tree View control.
                    //
                    //  As a fall back (and this is an UberUgly hack), we will send
                    //  some fake keystrokes to the application in an attempt to force
                    //  the Tree View to scroll to the selected item.
                    //
                    t.Stop();
                    SendKeys.Send("{TAB}{TAB}{DOWN}{DOWN}{UP}{UP}");
                }
            };

            t.Interval = 10;
            t.Start();

            result = dlg.ShowDialog( parent );
        }

        return result;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么FolderBrowserDialog对话框不滚动到选定的文件夹? 的相关文章

随机推荐

  • 从Android应用程序访问公共Google Drive文件夹而不进行身份验证

    我希望我的应用程序能够从预定义的共享公共 Google 云端硬盘文件夹中读取数据 而无需用户登录或选择 Google 帐户 背景 环境 Using my desktop browser I have created a public fol
  • uWSGI和joblib Semaphore:Joblib将以串行模式运行

    我正在 Docker 容器内的 Flask 应用程序中运行 joblib 以及由supervisord启动的uWSGI 以启用线程的方式启动 Web服务器的启动显示以下错误 unable to load configuration from
  • 如何抑制“避免使用捆绑版本的 Google Play 服务 SDK”警告?

    我在 Android 应用程序中使用 Google Play 服务 因此我的应用程序中有依赖项build gradle compile com google android gms play services 10 2 1 但 Androi
  • 如何从标签函数调用原生 es6 模板字符串替换?

    我正在为模板文字编写一个 es6 标记函数 它首先检查字符串中的条件 如果未找到条件 则仅将模板文字解释为未标记 我很好奇 从我的标签函数中 是否有一种方法可以调用浏览器的本机模板文字函数 我认为这会比我自己实现的功能 Bonue 有了这个
  • 向 Word 文档添加标题?

    我想使用 PowerShell 将自定义标头添加到 doc 文件 我的意思是实际标头 而不是标题 这应该有效 Word New Object ComObject Word Application wdSeekPrimaryHeader 1
  • qDebug() 的错误输出(UTF - 8)

    我正在尝试存储带有特殊字符的字符串 qDebug lt lt ABCg 输出 这里我什至无法输入正确的输出 在 之后缺少一些垃圾 ABCg 我怀疑有一些 UTF 8 Latin1 ASCII 但找不到输出到控制台 文件的设置 我在代码中写的
  • 为什么每次重新部署时都需要刷新连接池?

    我已经通过 Glassfish 成功连接到远程 MySQL 服务器 但是每次更改代码或 XHTML 文件时 我都需要打开 Glassfish 的管理员面板并刷新连接池 否则会出现以下错误我只是刷新页面 有人经历过这个吗 如果需要的话我可以发
  • 从非主线程绘制到主窗体画布

    我正在尝试为我的学校项目制作一款街机游戏 基本思想是在主线程之外的其他线程中完成所有数学和绘图 并且仅将主线程用于输入例程 绘图是通过保存在外部单元中的过程完成的 并且是通过创建位图 然后在位图上绘制部分环境 最后在主窗体的画布上绘制位图来
  • RoundRobin 函数方法 - 为什么我的函数有副作用?

    客观的 我正在尝试创建一个循环算法 https en wikipedia org wiki Round robin scheduling https en wikipedia org wiki Round robin scheduling
  • 覆盖查询集的更新方法 - Django

    我们如何更改 django 中查询集的 update 方法的默认过程 因为它不会为每个对象调用 save 方法 由于我已经重写了 save 方法 因此每次更改对象时都需要调用它 我寻找Django 文档 https docs djangop
  • AntiXSS JavaScriptEncode 获取 HTML 编码?

    我刚刚开始使用 AntiXSS 4 3 0 主要是为了使用 Encoder JavaScriptEncode如上所述here http weblogs asp net jongalloway preventing javascript en
  • 如何在默认范围内按相关型号订购? -- 轨道 3.1

    如何编写以下默认范围 class SimilarMerchant lt ActiveRecord Base relationships belongs to merchant belongs to similar merchant fore
  • Java swing 禁用窗口

    I would like to disable the window in my swing application here is a picture to demonstrate what I mean My paint skills
  • jBPM 5:数据库表脚本在哪里?

    我在 JBPM 5 4 中创建了一个关于持久性的简单示例 它运作成功并且 记录已成功插入到创建的架构中的表中 但我的问题是 虽然该表是在架构中创建的 但它还创建了其他三个表 节点实例日志 变量实例日志 进程实例日志 但是创建这些表的脚本在哪
  • 通过Python创建文件和目录

    我在创建目录然后打开 创建 写入指定目录中的文件时遇到问题 我似乎不清楚原因 我正在使用 os mkdir 和 path chap name print Path chap path For debugging purposes if no
  • 使用http而不是https的redirect_uri

    我正在使用 spring stack Spring Boot 2 0 1 RELEASE 来创建一个通过 OAuth2 将用户身份验证 注册委托给 Facebook 的网站 当我单击 使用 facebook 登录 按钮时 我会被重定向到 F
  • jQuery 查找并替换第二个

    我想知道如何查找和替换 div 中的某些文本 但我想查找并替换该文本的第二次出现 例如 您刚刚添加了一个项目 请删除该项目 所以我想找到第二个 项目 并将其替换为我选择的任何文本 JS var compareCount compareWid
  • SQL日期格式和引用混乱

    我有以下测试记录 以下查询结果为 0 条记录 SELECT FROM events dates WHERE start date 21 12 2014 但以下查询结果为 1 条记录 SELECT FROM events dates WHER
  • 用 | 分割字符串java中的分隔符

    我有一个像这样的字符串 1 value 我想拆分该字符串并选择 作为分隔符 我的代码如下所示 String separated line split 我得到的是一个包含所有字符作为一个条目的数组 separated 0 separated
  • 为什么FolderBrowserDialog对话框不滚动到选定的文件夹?

    如该屏幕截图所示 所选文件夹不在视图中 需要向下滚动才能查看所选文件夹 同一对话框显示在不同计算机上可见的选定文件夹 我在两台装有 Windows 7 的计算机上运行它 它在一台计算机上运行正常 但在第二台计算机上运行不正常 它看起来与 W