【问题标题】:Select file OR folder from same dialog on Windows?从 Windows 上的同一对话框中选择文件或文件夹?
【发布时间】:2011-12-26 14:48:12
【问题描述】:

我想允许我的 Windows 游戏用户使用对话框来选择文件夹文件。我目前可以使用 SHBrowseForFolder 或 GetOpenFileName 来做一个或另一个,但不能在同一个对话框中使用这两个选项。这可能吗? (原因是我正在移植一个 Mac 游戏,这 是可能的。)

【问题讨论】:

  • SHBrowseForFolder 和 BIF_BROWSEINCLUDEFILES,但它会在 Vista 和更高版本上显示一个丑陋的对话框。有两个菜单项,一个用于文件,一个用于文件夹有什么问题?
  • 到目前为止这似乎有效。谢谢!!!

标签: windows winapi dialog getopenfilename


【解决方案1】:

当您打开文件对话框时,给它一个默认文件名,例如“整个文件夹”,并在启用“确定”按钮之前关闭要求文件存在的标志。当对话框返回时,检查文件名以查看它是否与特殊字符串“整个文件夹”匹配并进行相应处理。

根据我对另一个问题的回答:How do you configure an OpenFileDialog to select folders?

【讨论】:

  • GetOpenFileName 对我不起作用。必须是适用于 OpenFileDialog 的东西。我使用的是 C。可以直接从 C 调用 OpenFileDialog,还是必须创建一个带有 C 接口的 C++ 类?
  • @Vern,这真的很奇怪 - 当我写另一个答案时,我使用内部使用 GetOpenFileName 的框架进行了测试。我稍后再试一下,看看问题出在哪里。
【解决方案2】:

如果您在 OPENFILENAME 结构的 Flags 成员中设置了 OFN_NOVALIDATE,则在末尾键入不带“\”的文件夹名称,然后按 Enter(或打开),会将 CDN_FILEOK 通知发送到挂钩过程,而不是 CDN_FOLDERCHANGE通知。

从那里,您可以对文件夹路径做任何您想做的事情。对我来说,这是一个错误,但它可能会对您有所帮助。

【讨论】:

    【解决方案3】:

    据我所知,无法在可以从同一对话框中选择文件夹或文件的模式下操作常用对话框。

    【讨论】:

      【解决方案4】:

      我知道这个帖子很旧,但我最近遇到了同样的问题。 我发现当单击 OK 按钮时,对话框会发出 CDN_FOLDERCHANGE 消息,但文件夹实际上没有更改(与上次调用时相同)。 所以我想出了下面的钩子程序:

      UINT_PTR CALLBACK openfilename_cb (
        HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
      {
        NMHDR *nmhdr;
        OFNOTIFY *ofnotify;
        static char dir_now[PATH_MAX], dir_prev[PATH_MAX];
      
        do_debug (5, "openfilename_cb(): hwnd=%p, msg=%d\n", hwnd, msg);
        switch (msg)
        {
          case WM_INITDIALOG:
            do_debug (2, "openfilename_cb(): WM_INITDIALOG\n");
            break;
      
          case WM_NOTIFY:
            ofnotify = (OFNOTIFY *)lParam;
            nmhdr = &ofnotify->hdr;
            do_debug (4,"openfilename_cb(): WM_NOTIFY, hwnd=%p, id=%d, code=%d\n",
              nmhdr->hwndFrom, nmhdr->idFrom, nmhdr->code);
            switch (nmhdr->code)
            {
              case CDN_INITDONE:
                do_debug (3, "openfilename_cb(): CDN_INITDONE\n");
                dir_prev[0] = '\0';
                break;
      
              case CDN_FILEOK:
                do_debug (3, "openfilename_cb(): CDN_FILEOK\n");
                break;
      
              case CDN_FOLDERCHANGE:
                do_debug (3, "openfilename_cb(): CDN_FOLDERCHANGE\n");
                SendMessage (nmhdr->hwndFrom, CDM_GETFOLDERPATH, sizeof(dir_now),
                                                                  (LPARAM)dir_now);
                do_debug (3, "  directory=%s\n", dir_now);
                if (ofnotify->lpOFN->lCustData & FN_OPENDIR)
                {
                  if (stricmp(dir_now, dir_prev) == 0)
                  {
                    /* user clicked the OK button */
                    strncpy (ofnotify->lpOFN->lpstrFile, dir_now, PATH_MAX);
                    ofnotify->lpOFN->lCustData = MAGIC;
                    PostMessage (nmhdr->hwndFrom, WM_COMMAND, IDCANCEL, 0);
                    do_debug (3, "  closing dialog\n");
                    break;
                  }
                  strncpy (dir_prev, dir_now, sizeof(dir_prev));
                }
                break;
      
              case CDN_HELP:
                do_debug (3, "openfilename_cb(): CDN_HELP\n");
                break;
              case CDN_SELCHANGE:
                do_debug (3, "openfilename_cb(): CDN_SELCHANGE\n");
                break;
      
              case CDN_SHAREVIOLATION:
                do_debug (3, "openfilename_cb(): CDN_SHAREVIOLATION\n");
                break;
      
              case CDN_TYPECHANGE:
                do_debug (3, "openfilename_cb(): CDN_TYPECHANGE\n");
                break;
            }  /* switch (nmhdr->code) */
            break;  /* WM_NOTIFY */
        }  /*   switch (msg) */
        return 0;
      }
      

      确保在 OPENFILENAME 结构标志成员中设置 OFN_ENABLEHOOK 和 OFN_EXPLORER 位,以便调用挂钩过程。当然,将 lpfnHook 成员设置为钩子函数的地址。

      我发现无论是否使用钩子程序,对话框看起来都大不相同(元素的排序方式不同,左窗格中有一个树形视图与大图标,也许更多)。

      你必须与你的调用函数来回沟通你想要/已经选择了一个目录。为此,我使用了 OPENFILENAME 结构的 lCustData 成员。

      我使用 Windows 10 版本 19042.1052 64 位和 Windows XP 32 位进行了测试。

      约翰内斯

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-30
        • 1970-01-01
        • 1970-01-01
        • 2020-11-24
        • 2017-10-21
        • 2011-04-29
        • 2015-11-29
        • 1970-01-01
        相关资源
        最近更新 更多