我想允许我的 Windows 游戏用户使用对话框来选择文件夹或文件。我目前可以使用 SHBrowseForFolder 或 GetOpenFileName 执行其中一项,但不能在同一个对话框中执行这两个选项。这可能吗?(原因是我要在可能的地方移植 Mac 游戏。)
4 回答
当您打开文件对话框时,给它一个默认文件名,例如“整个文件夹”,并在启用“确定”按钮之前关闭要求文件存在的标志。当对话框返回时,检查文件名以查看它是否与特殊字符串“整个文件夹”匹配并相应地处理它。
根据我对另一个问题的回答:如何配置 OpenFileDialog 来选择文件夹?
如果您在 OPENFILENAME 结构的 Flags 成员中设置了 OFN_NOVALIDATE,则在末尾键入一个不带“\”的文件夹名称,然后按 Enter(或 Open),将向挂钩过程发送 CDN_FILEOK 通知,而不是 CDN_FOLDERCHANGE 通知。
从那里,您可以对文件夹路径做任何您想做的事情。对我来说,这是一个错误,但它可能会对你有所帮助。
据我所知,无法在可以从同一对话框中选择文件夹或文件的模式下操作常用对话框。
我知道这个线程很旧,但我最近遇到了同样的问题。我发现当单击 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 位进行了测试。
约翰内斯