打开并另存为对话框

[从 Windows Vista 开始,打开另存为 常见对话框已被 通用项对话框取代。 建议使用通用项对话框 API,而不是通用对话框库中的这些对话框。

“打开”对话框允许用户指定要打开的文件或文件集的名称、目录和名称。 通过初始化 OPENFILENAME 结构并将结构传递给 GetOpenFileName 函数,创建并显示 打开 对话框。

另存为 对话框允许用户指定要保存的文件的驱动器、目录和名称。 通过初始化 OPENFILENAME 结构并将结构传递给 GetSaveFileName 函数,创建并显示 另存为 对话框。

资源管理器样式 打开另存为 对话框提供类似于 Windows 资源管理器的用户界面功能。 但是,对于必须与旧式用户界面一致的应用程序,系统继续支持旧式 打开另存为 对话框。

除了外观差异外,资源管理器样式和旧样式对话框在自定义对话框时使用的自定义模板和挂钩过程也有所不同。 但是,对于大多数基本作,资源管理器样式和旧样式对话框具有相同的行为,例如指定文件名筛选器、验证用户的输入以及获取用户指定的文件名。 有关资源管理器样式和旧样式对话框的详细信息,请参阅 打开和另存为对话框自定义

下图显示了典型的“资源管理器”样式 “打开”对话框。

打开文件对话框

下图显示了典型的资源管理器样式 另存为 对话框。

保存文件对话框

如果用户指定文件名并单击“确定 ”按钮GetOpenFileNameGetSaveFileName 返回 TRUE OPENFILENAME 结构的 lpstrFile 成员指向的缓冲区包含用户指定的完整路径和文件名。

如果用户取消 打开另存为 对话框或发生错误,该函数将返回 FALSE。 若要确定错误的原因,请调用 CommDlgExtendedError 函数来检索扩展的错误值。 如果 lpstrFile 缓冲区太小而无法接收全名,CommDlgExtendedError 将返回 FNERR_BUFFERTOOSMALLlpstrFile 成员指向的缓冲区的前 2 个字节设置为指定接收全名所需的大小的整数值。

本节将讨论以下主题。

文件名和目录

本节中的信息适用于资源管理器样式和旧样式 打开另存为 对话框。

在调用 GetOpenFileNameGetSaveFileName 函数之前,OPENFILENAME 结构的 lpstrFile 成员必须指向缓冲区才能接收文件名。 nMaxFile 成员必须指定 lpstrFile 缓冲区的大小(以字符为单位)。 对于 ANSI 函数,这是字节数,但对于 Unicode 函数,这是字符数。

如果用户指定文件名并单击 确定 按钮,则对话框会将所选驱动器、目录和文件名复制到 lpstrFile 缓冲区。 该函数还将 nFileOffsetnFileExtension 成员分别设置为缓冲区开头到文件名和文件扩展名的偏移量(以字符为单位)。

若要仅检索文件名和扩展名,请将 lpstrFileTitle 成员设置为指向缓冲区,并将 nMaxFileTitle 成员设置为缓冲区的大小(以字符为单位)。 或者,可以在调用 GetFileTitle 函数以获取所选文件的显示名称时传递 lpstrFile 缓冲区。 但是,请注意,仅当 GetFileTitle 返回的文件名仅当它是用户用于显示文件名的首选项时,才会返回扩展名。

该对话框使用当前目录作为显示文件和目录的初始目录的调用过程。 使用 GetCurrentDirectorySetCurrentDirectory 函数来获取和更改进程的当前目录。 若要在不更改当前目录的情况下指定其他初始目录,请使用 lpstrInitialDir 成员指定目录的名称。 当用户选择其他驱动器或目录时,对话框会自动更改当前目录。 若要防止对话框更改当前目录,请设置 OFN_NOCHANGEDIR 标志。 此标志不会阻止用户更改目录以查找文件。

若要指定默认文件扩展名,请使用 lpstrDefExt 成员。 如果用户指定没有扩展名的文件名,则对话框会添加默认扩展名。 如果指定默认扩展名,并且用户指定具有不同扩展名的文件名,则对话框将设置 OFN_EXTENSIONDIFFERENT 标志。

若要让用户从目录中选择多个文件,请设置 OFN_ALLOWMULTISELECT 标志。 为了与较旧的应用程序兼容,默认的多个选择对话框使用旧式用户界面。 若要显示资源管理器样式的多个选择对话框,还必须设置 OFN_EXPLORER 标志。

如果用户选择多个文件,lpstrFile 成员指向的缓冲区将返回当前目录的路径,后跟所选文件的文件名。 nFileOffset 成员是第一个文件名的偏移量,不使用 nFileExtension 成员。 下表描述了返回多个文件名时资源管理器样式和旧样式对话框之间的差异。

对话框样式 描述
资源管理器样式对话框 目录和文件名字符串 NULL 分隔,在姓氏后面额外 NULL 字符。 此格式使资源管理器样式对话框能够返回包含空格的长文件名。
旧样式对话框 目录和文件名字符串用空格分隔。 对于带空格的文件名,该函数使用短文件名。

 

可以使用 FindFirstFile 函数在长文件名和短文件名之间进行转换。

如果指定 OFN_ALLOWMULTISELECT 并且用户仅选择一个文件,则 lpstrFile 字符串在路径和文件名之间没有分隔符。

过滤 器

本节中的信息适用于“资源管理器”样式和旧样式 “打开”和“另存为”对话框。

可以提供文件名筛选器,以帮助用户限制对话框显示的文件名。 文件名筛选器由一对以 null 结尾的字符串、说明和模式组成,一个连接到另一个字符串。 该对话框显示说明,让用户选取要使用的筛选器;并使用模式选择要显示的文件。

若要指定筛选器,请将 lpstrFilterOPENFILENAME 结构的成员设置为指向包含筛选器字符串对数组的缓冲区。 数组中的最后一个字符串必须后跟额外的 null 字符。

模式字符串可以是有效文件名字符和星号 {的组合。 星号是一个通配符,表示有效文件名字符的任意组合。 该对话框仅显示与模式匹配的文件。 若要为同一说明指定多个模式,必须使用分号(;)分隔模式)。 请注意,模式字符串中的空格字符可能会产生意外的结果。

以下代码片段指定两个筛选器。 带有“源”说明的筛选器有两种模式。 如果用户选择此筛选器,对话框仅显示具有此筛选器的文件。C 和 .CXX 扩展。 请注意,在 C 编程语言中,用双引号括起来的字符串以 null 结尾。

OPENFILENAME ofn;       // common dialog box structure

ofn.lpstrFilter = "Source\0*.C;*.CXX\0All\0*.*\0"
ofn.nFilterIndex = 1;

nFilterIndexOPENFILENAME 结构的成员指定一个索引,该索引指示对话框最初使用的筛选器。 缓冲区中的第一个筛选器具有索引 1、第二个 2 等。 如果用户在使用对话框时更改筛选器,则 nFilterIndex 成员设置为返回时所选筛选器的索引。

可以通过将 lpstrCustomFilter 成员设置为包含单个筛选器的缓冲区的地址,并将 nMaxCustFilter 成员设置为缓冲区的大小(以字符或字节为单位)。创建自定义筛选器。 对话框始终将自定义筛选器放在筛选器列表的开头,返回时,始终使用用户选择的筛选器中的模式更新筛选器的模式部分。

对于“资源管理器”样式对话框,如果用户选择其他筛选器,则默认扩展可能会更改。 如果用户选择其第一个模式为窗体 *的筛选器。xxx(即扩展不包含通配符),对话框使用 xxx 作为默认扩展。 仅当在 lpstrDefExtOPENFILENAME 结构的成员中指定了默认扩展时,才会发生这种情况。 例如,如果用户选择“Source\0*”。C;*.CXX\0“ 筛选器,默认扩展将更改为”C”。 但是,如果已将筛选器定义为“Source\0*”。C*\0“,默认扩展不会更改,因为该扩展包含通配符。

CDN_INCLUDEITEM 通知消息提供了另一种方法来筛选对话框显示的名称。 若要使用此消息,请在创建对话框时,提供 OFNHookProc 挂钩过程,并在 OPENFILENAME 结构中指定 OFN_ENABLEINCLUDENOTIFY 标志。 每次用户打开文件夹时,对话框都会向新打开文件夹中每个项目的挂钩过程发送 CDN_INCLUDEITEM 通知。 挂钩过程的返回值指示对话框是否应在文件夹的项目列表中显示该项。

文件和目录验证

除非另有说明,本节中的信息适用于资源管理器样式和旧样式 打开另存为 对话框。

该对话框会自动验证用户键入的文件名,以确保名称仅包含有效字符。 若要替代文件名字符验证,请设置 OFN_NOVALIDATE 标志。

若要强制对话框验证用户是否指定了现有文件的名称,请设置 OFN_FILEMUSTEXIST 标志。 若要强制验证指定路径是否存在,请设置 OFN_PATHMUSTEXIST 标志。 如果设置 OFN_CREATEPROMPT 标志,对话框会提示用户创建不存在的文件的权限。 如果设置了此标志,并且用户选择创建新文件,则对话框将关闭,该函数将返回指定的名称。 否则,对话框将保持打开状态。

使用 另存为 对话框时,可以通过设置 OFN_OVERWRITEPROMPT 标志来指示对话框提示用户覆盖现有文件的权限。

默认情况下,对话框会创建一个零长度的测试文件,以确定是否可以在所选目录中创建新文件。 若要防止创建此测试文件,请设置 OFN_NOTESTFILECREATE 标志。

如果启用挂钩过程,对话框会在用户指定的文件名发生网络共享冲突时通知挂钩过程。 如果设置 OFN_EXPLORER 标志,对话框会将 CDN_SHAREVIOLATION 消息发送到挂钩过程。 如果未设置 OFN_EXPLORER,对话框会将 SHAREVISTRING 注册的消息发送到挂钩过程。 若要阻止对话框发送任何共享冲突通知,请设置 OFN_SHAREAWARE 标志。

如果用户选中只读复选框,对话框将设置返回时 OFN_READONLY 标志。 若要隐藏 “打开为只读”复选框,请设置 OFN_HIDEREADONLY 标志。 若要防止对话框返回具有只读属性的现有文件的名称,请设置 OFN_NOREADONLYRETURN 标志。

若要阻止对话框取消引用链接文件,请设置 OFN_NODEREFERENCELINKS 值。 在这种情况下,对话框返回链接文件的名称,而不是链接文件引用的文件的名称。

打开并另存为对话框自定义

可以通过提供挂钩过程、自定义模板或两者来自定义 打开另存为 对话框。 但是,对话框的资源管理器样式和旧样式版本在自定义模板和挂钩过程中的使用有所不同。

有关自定义资源管理器样式对话框的信息,请参阅 Explorer-Style 挂钩过程Explorer-Style 自定义模板,以及 Explorer-Style 控件标识符。 有关自定义旧样式对话框的信息,请参阅 自定义 Old-Style 对话框

下表总结了两种样式之间的差异。

定制 描述
资源管理器样式挂钩过程 挂钩过程接收从公共对话框发送的通知消息,以及通过指定子对话模板定义的任何其他控件的消息。 挂钩过程不会接收默认对话框的标准控件的消息。
资源管理器样式的自定义模板 系统使用自定义模板创建子对话框。 该模板可以定义其他控件,并且可以指定标准控件群集的位置。 自定义模板不会替换默认模板。
旧式挂钩过程 挂钩过程接收发送到对话框的所有消息,包括标准控件的消息和任何自定义控件的消息。 挂钩过程还会接收从通用对话框发送的已注册消息。
旧样式自定义模板 自定义模板替换默认模板。 通过修改 Fileopen.dlg 文件中指定的默认模板创建自定义模板。

 

资源管理器样式和旧样式对话框的默认标题为“打开”或“另存为”。若要更改标题,请在 OPENFILENAME 结构的 lpstrTitle 成员中指定新标题。

用户的 HKEY_CURRENT_USER 注册表配置单元可以包含值,这些值可自定义资源管理器样式 打开另存为 对话框的内容。 这些注册表项仅影响与注册表配置单元关联的用户显示的对话框。

若要隐藏资源管理器样式 打开另存为 对话框的功能,管理员可以在此子项下设置下表中的值:

HKEY_CURRENT_USER
   Software
      Microsoft
         Windows
            CurrentVersion
               Policies
                  Comdlg32
值名称 价值 意义
NoPlacesBar 1 隐藏位置栏。
NoFileMRU 1 隐藏“最近使用”(MRU)列表。
NoBackButton 1 隐藏 “后退”按钮。

 

Places 栏的内容由以下子项的内容确定:

HKEY_CURRENT_USER
   Software
      Microsoft
         Windows
            CurrentVersion
               Policies
                  Comdlg32
                     Placesbar

目前,此键下只能有五个条目,值/名称索引是从零开始的。 条目的名称应为 Place0、Place1、Place2、Place3 和 Place4。 条目的值可以 REG_DWORDREG_SZREG_EXPAND_SZ 值来标识要包含在位置栏中的位置。

值类型 意义
REG_DWORD 标识文件夹的 CSIDL 值。 有关 CSIDL 值的列表,请参阅 CSIDL 值
REG_SZREG_EXPAND_SZ 一个指定有效路径的以 null 结尾的字符串。

 

Explorer-Style 挂钩过程

可以通过提供挂钩过程、自定义模板或两者来自定义资源管理器样式 打开另存为 对话框。 如果为资源管理器样式对话框提供挂钩过程,系统将创建一个对话框,该对话框是默认对话框的子级。 挂钩过程充当子对话框的对话框的对话框过程。 此子对话框基于自定义模板,或默认模板(如果未提供)。 有关详细信息,请参阅 Explorer-Style 自定义模板

若要为资源管理器样式 打开另存为 对话框启用挂钩过程,请在创建对话框时使用 OPENFILENAME 结构。 在 标志 成员中设置 OFN_ENABLEHOOKOFN_EXPLORER 标志,并在 lpfnHook 成员中指定 OFNHookProc 挂钩过程的地址。 如果提供挂钩过程并省略 OFN_EXPLORER 标志,则必须使用 OFNHookProcOldStyle 挂钩过程,并且你将获得旧式用户界面。 有关详细信息,请参阅 自定义 Old-Style 对话框

打开对话框时,资源管理器样式挂钩过程接收各种消息。 其中包括:

  • WM_INITDIALOG 消息和其他标准对话框消息,如 WM_CTLCOLORDLG 控件颜色消息。
  • 一组 WM_NOTIFY 通知消息,指示用户或其他对话框事件执行的作。
  • 通过指定子对话模板定义的任何其他控件的消息。

此外,还可以向资源管理器样式对话框发送一组消息来获取信息或控制对话框的行为和外观。

如果为资源管理器样式对话框提供挂钩过程,则默认对话框过程会在默认对话过程处理其 WM_INITDIALOG 消息时创建子对话框。 挂钩过程充当子对话框的对话框的对话框过程。 此时,挂钩过程会收到自己的 WM_INITDIALOG 消息,lParam 参数设置为用于初始化对话框的 OPENFILENAME 结构的地址。 子对话完成处理自己的 WM_INITDIALOG 消息后,默认对话过程会根据需要移动标准控件,以便为子对话框的任何其他控件腾出空间。 然后,默认对话过程会将 CDN_INITDONE 通知消息发送到挂钩过程。

挂钩过程接收 WM_NOTIFY 通知消息,指示对话框中用户执行的作。 可以使用其中一些消息来控制对话框的行为。 例如,当用户选择文件名并单击“确定” 按钮时,挂钩过程会收到 CDN_FILEOK 消息。 为了响应此消息,挂钩过程可以使用 SetWindowLong 函数拒绝所选名称并强制对话框保持打开状态。

每个 WM_NOTIFY 消息的 lParam 参数是指向定义作的 OFNOTIFYOFNOTIFYEX 结构的指针。 此结构的标头中的 代码 成员包含以下通知消息之一。

消息 意义
CDN_FILEOK 用户单击 “确定” 按钮;对话框即将关闭。
CDN_FOLDERCHANGE 用户打开了一个新文件夹或目录。
CDN_HELP 用户单击了 帮助 按钮。
CDN_INCLUDEITEM 确定是否应显示项。 当用户打开新文件夹或目录时,系统会为文件夹或目录中的每一项发送此通知。 仅当设置了 OFN_ENABLEINCLUDENOTIFY 标志时,系统才会发送此通知。
CDN_INITDONE 系统已完成对话框初始化,对话框已完成处理 WM_INITDIALOG 消息。 此外,系统已完成在通用对话框中排列控件,以便为子对话框的控件腾出空间(如果有)。
CDN_SELCHANGE 用户从文件列表中选择了一个新文件或文件夹。
CDN_SHAREVIOLATION 常见对话框在即将返回的文件上遇到共享冲突。
CDN_TYPECHANGE 用户从文件类型列表中选择了一个新文件类型。

 

这些 WM_NOTIFY 消息取代了 FILEOKSTRINGLBSELCHSTRINGSHAREVISTRING,以及 HELPMSGSTRING 以前版本的 open另存为 对话框使用的消息。 但是,如果 WM_NOTIFY 处理 不使用 setWindowLong 设置非零 DWL_MSGRESULT 值,则挂钩过程也会在 WM_NOTIFY 消息后接收被取代的消息。

若要检索有关对话框状态或控制对话框的行为和外观的信息,挂钩过程可以将以下消息发送到对话框。

消息 意义
CDM_GETFILEPATH 检索所选文件的路径和文件名。
CDM_GETFOLDERIDLIST 检索与对话框打开的当前文件夹对应的项标识符列表。 有关项标识符列表的详细信息,请参阅 shell 命名空间 简介。
CDM_GETFOLDERPATH 检索对话框的当前文件夹或目录的路径。
CDM_GETSPEC 检索对话框中当前所选文件的文件名(不包括路径)。
CDM_HIDECONTROL 隐藏指定的控件。
CDM_SETCONTROLTEXT 设置指定控件中的文本。
CDM_SETDEFEXT 设置对话框的默认文件扩展名。

 

Explorer-Style 自定义模板

若要为资源管理器样式 打开另存为 对话框定义其他控件,请使用 OPENFILENAME 结构为包含其他控件的子对话框指定模板。 如果子对话模板是应用程序或动态链接库中的资源,请在 标志 成员中设置 OFN_ENABLETEMPLATE 标志,并使用 hInstancelpTemplateName 结构的成员来标识模块和资源名称。 如果模板已在内存中,请设置 OFN_ENABLETEMPLATEHANDLE 标志,并使用 hInstance 成员标识包含该模板的内存对象。 为资源管理器样式对话框提供子对话模板时,还必须设置 OFN_EXPLORER 标志;否则,系统假定你正在为旧式对话框提供替换模板。 通常,如果提供其他控件,还必须提供 资源管理器样式挂钩过程 来处理新控件的消息。

可以像执行任何其他模板一样创建子对话框模板,但必须指定 WS_CHILDWS_CLIPSIBLINGS 样式,并指定 DS_3DLOOKDS_CONTROL 样式。 系统需要 WS_CHILD 样式,因为模板定义了默认 打开另存为 对话框的子对话框。 WS_CLIPSIBLINGS 样式可确保子对话框不会在默认对话框中的任何控件上绘制。 DS_3DLOOK 样式可确保子对话框中控件的外观与默认对话框中的控件保持一致。 DS_CONTROL 样式可确保用户可以使用 TAB 和其他导航键在自定义对话框中的所有控件(默认或自定义)之间移动。

若要为新控件腾出空间,系统将默认对话框扩展为自定义对话框的宽度和高度。 默认情况下,自定义对话框中的所有控件都位于默认对话框中的控件下方。 但是,可以通过在自定义对话框模板中包含静态文本控件并为其分配 stc32的控件标识符值来替代此默认定位。 (此值在 Dlgs.h 头文件中定义。在这种情况下,系统使用控件作为确定新控件位置的参考点。 stc32 控件的上方和左侧的所有新控件都位于默认对话框中控件的上方和左侧。 下面和 stc32 控件右侧的新控件位于默认控件的下方和右侧。 通常,每个新控件都定位,使其相对于默认控件具有相同的位置,因为它必须与 stc32 控件相同。 为了为这些新控件腾出空间,系统根据需要将空间添加到默认对话框的左侧、右侧、底部和顶部。

系统要求挂钩过程处理用于自定义对话框的所有消息,因此会将相同的窗口消息发送到挂钩过程,就像处理任何其他对话框过程一样。 例如,当用户单击自定义对话框中的按钮控件时,挂钩过程会收到 WM_COMMAND 消息。 挂钩过程负责初始化这些控件,并在对话框关闭时从控件中检索值。 请注意,当挂钩过程收到 WM_INITDIALOG 消息时,系统尚未将控件移动到其最终位置。

默认对话框过程处理默认对话框中所有控件的消息,但挂钩过程接收有关这些控件的用户作的通知消息,如 Explorer-Style 挂钩过程中所述。

Explorer-Style 控件标识符

Windows 软件开发工具包(SDK)为旧式对话框提供默认对话框模板,但不包括资源管理器样式对话框的默认模板。 这是因为资源管理器样式对话框允许添加自己的控件,但不支持修改标准控件的模板。 但是,在某些情况下,可能需要知道默认模板中使用的控件标识符。 例如,CDM_HIDECONTROLCDM_SETCONTROLTEXT 消息需要控制标识符。

下表显示了资源管理器样式 打开另存为 对话框中的标准控件的标识符。 标识符是在 Dlgs.h 和 Winuser.h 中定义的常量。

控制标识符 控件说明
chx1 只读复选框
cmb1 显示文件类型筛选器列表的下拉列表组合框
stc2 cmb1 组合框的标签
cmb2 显示当前驱动器或文件夹的下拉组合框,允许用户选择驱动器或文件夹以打开
stc4 cmb2 组合框的标签
cmb13 显示当前文件名称的下拉组合框,允许用户键入要打开的文件的名称,并选择最近打开或保存的文件。 这适用于早期不带挂钩或对话框模板的与资源管理器兼容的应用程序。 与 edt1进行比较。
edt1 编辑显示当前文件的名称的控件,或允许用户键入要打开的文件的名称。 与 cmb13进行比较。
stc3 cmb13 组合框和 edt1 编辑控件的标签
lst1 显示当前驱动器或文件夹内容的列表框
stc1 lst1 列表框的标签
IDOK OK 命令按钮(按下按钮)
IDCANCEL 取消 命令按钮(按下按钮)
pshHelp 帮助 命令按钮(按下按钮)

 

自定义 Old-Style 对话框

可以通过提供 OFNHookProcOldStyle 挂钩过程来自定义旧式 打开另存为 对话框。 还可以提供一个自定义模板来代替默认模板。 用于旧式对话框的挂钩过程和模板类似于用于其他常见对话框的挂钩过程和模板。 有关详细信息,请参阅 常见对话框的挂钩过程自定义模板

若要为旧式 打开另存为 对话框启用挂钩过程,请在创建对话框时使用 OPENFILENAME 结构。 在 标志 成员中设置 OFN_ENABLEHOOK 标志,并在 lpfnHook 成员中指定 OFNHookProcOldStyle 挂钩过程的地址。 对话框过程将 WM_INITDIALOG 消息发送到挂钩过程,Param 参数设置为用于初始化对话框的 OPENFILENAME 结构的地址。

可以使用 OPENFILENAME 结构为 打开另存为 对话框指定自定义模板,以代替默认模板。 如果自定义模板是应用程序或动态链接库中的资源,请在 标志 成员中设置 OFN_ENABLETEMPLATE 标志,并使用 hInstancelpTemplateName 结构的成员来标识模块和资源名称。 如果自定义模板已在内存中,请设置 OFN_ENABLETEMPLATEHANDLE 标志,并使用 hInstance 成员标识包含模板的内存对象。 通过修改 Fileopen.dlg 文件中指定的默认模板创建自定义模板。 默认的“查找和替换”对话框模板中使用的控件标识符在 Dlgs.h 文件中定义。

默认情况下,GetOpenFileNameGetSaveFileName 函数显示资源管理器样式对话框。 如果要显示旧样式对话框,则必须提供 OFNHookProcOldStyle 挂钩过程,并确保未在 标志OPENFILENAME 结构的成员中设置 OFN_EXPLORER 标志。

如果设置 OFN_EXPLORER 标志,系统将挂钩过程或自定义模板视为资源管理器样式的自定义。 有关自定义资源管理器样式对话框的信息,请参阅 Explorer-Style 自定义模板

另请参阅