从Windows上的同一对话框中选择文件OR文件夹?

时间:2011-11-10 22:56:26

标签: windows winapi dialog getopenfilename

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

4 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

如果在OPENFILENAME结构的Flags成员中设置OFN_NOVALIDATE,则输入不带' \'的文件夹名称。最后,按Enter键(或打开),将CDN_FILEOK通知发送到挂钩程序,而不是CDN_FOLDERCHANGE通知。

从那里,您可以使用文件夹路径执行任何操作。对我来说,这是一个错误,但它可能对你有帮助。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我知道这个帖子很旧,但我最近遇到了同样的问题。 我发现当单击“确定”按钮时,对话框会发出 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 struct Flags 成员中设置 OFN_ENABLEHOOK 和 OFN_EXPLORER 位,以便调用挂钩过程。并且,当然,将 lpfnHook 成员设置为您的钩子函数的地址。

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

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

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

约翰内斯