阅读时间:约6分钟

适用人群:使用 LabVIEW 编写文件读写程序、需要为文件打开与保存对话框配置多组文件类型过滤列表的工程师与嵌入式开发者。

一、背景与问题现象

在基于 LabVIEW 开发文件读写功能时,常常需要通过"文件对话框"函数弹出操作系统的文件选择窗口,让使用者挑选要打开或保存的文件。为了让使用者快速定位目标文件,通常会在对话框底部的"文件类型"下拉列表中设置过滤条件,例如只显示文本文件、图片文件或数据文件。

然而,很多开发者在实践中发现,对话框的过滤列表似乎只能设置一组条件。例如将过滤模式设置为"*.txt"之后,下拉列表中就只有一个"文本文件"条目,无法像许多原生应用程序那样,在同一个下拉列表中同时出现"图片文件"、"文档文件"、"数据文件"等多个分组,每个分组下面再附上相应的通配符列表。想要获得这种多分组效果,只能反复编写自定义界面,或者求助于第三方控件,既增加了工作量,也破坏了与操作系统原生对话框的一致性。

事实上,"文件对话框"函数本身就支持多行文件类型过滤器,只是这一能力并未在上下文帮助中说明,触发方式也比较隐蔽。有经验的开发者发现,只要在过滤模式字符串中嵌入特定的分隔符,就能让下拉列表按行展开成多个分组。这一技巧虽然未被正式文档收录,却在实际项目中极具实用价值。

二、原理与机制分析

要理解这一技巧,需要先弄清"文件对话框"函数与操作系统底层对话框之间的关系。该函数本身并不实现对话框界面,而是对操作系统提供的公共文件对话框做了一层封装,将 LabVIEW 侧的输入参数映射到系统对话框的底层数据结构上。

在 Windows 平台上,系统公共对话框接收的过滤器信息是一个连续的缓冲区,其中每个过滤分组由"描述文本"与"过滤模式"两部分组成,两者之间以及分组与分组之间都以空字符分隔,整个列表以连续两个空字符结束。LabVIEW 的函数只对外暴露了"模式"与"模式标签"两个字符串输入,两者与底层缓冲区的对应关系并非一一对应,这正是多行过滤器语法显得怪异的原因。

通过在模式字符串中嵌入空字符作为"换行"分隔符,可以将多个分组的描述与模式逐段填入同一个字符串,从而让系统对话框按预期展开为多组过滤条目。之所以要在"\ Codes Display"显示模式下编辑该字符串常量,是因为普通显示模式下空字符不可见,只有在以代码转义形式显示时,才能准确地键入并确认空字符的存在。

这一功能之所以没有在文档中说明,是因为它并不是刻意设计的结果,而是底层操作系统函数附带的能力,属于"顺带可用"的隐藏特性。正因为如此,其语法中存在多处看似不合常理的约定,例如第一个分组之后出现一个不配对的括号、第一个分组的名称需要填入"模式标签"输入而不是"模式"输入、以及过滤模式本身需要重复书写等。这些约定与底层缓冲区的组装规则一一对应,属于必须原样遵守的格式约束。

三、实现方法与解决方案

实现多行过滤器有两条途径:一是直接使用"文件对话框"函数并手工构造字符串;二是编写一个封装子 VI,把繁杂的语法细节隐藏起来。

采用直接方式时,先在程序框图上放置"文件对话框"函数,为"模式"输入连接一个字符串常量。将该常量设置为"\ Codes Display"显示模式,然后按照"描述文本、空字符、过滤模式"的顺序依次填入各组内容,组与组之间也用空字符分隔。与此同时,将第一个分组的描述文本填入"模式标签"输入,使其与模式输入中的首段内容对应。配置完成后运行程序,弹出对话框,在"文件类型"下拉列表中即可看到按行排列的多组过滤条目。

1 "\ Codes Display"模式显示的多行过滤字符串常量,组间用空字符分隔

采用封装方式时,可以构建一个子 VI,对外提供两个数组输入,一个用于存放各分组的描述标签,另一个用于存放各分组对应的过滤模式集合。子 VI 内部先把同一分组内的多个通配符用分号连接成一行,例如将"*.bmp;*.png;*.gif"作为图片分组的模式;再把各分组依次拼装为带空字符分隔的完整字符串,并正确写入"模式"与"模式标签"输入。如此,调用方只需维护清晰的数组数据,无需接触任何转义字符。

2 运行后得到的文件对话框,"文件类型"下拉列表已按分组展开

这种封装还便于进一步扩展,例如允许同一个描述标签下挂接任意多个过滤模式、支持动态增删分组等,从而使文件对话框的过滤能力与工程需求解耦,代码的可读性与可维护性都得到明显提升。

四、关键设计要点与易错点

多行过滤器虽然好用,但在实际落地时存在若干极易出错的关键点,需要特别留意。

第一,空字符不可见。空字符是整段语法的核心分隔符,但在普通显示模式下并不显示。若直接以普通模式编辑常量,很容易在不知不觉中丢失分隔符,导致下拉列表无法按预期分组。务必切换到"\ Codes Display"模式进行编辑与核对。

第二,输入位置容易混淆。第一个分组的描述文本必须放入"模式标签"输入,而不是"模式"输入;后续分组的描述则嵌在模式字符串内部。如果全部塞进模式输入,或者把标签与模式内容放反,对话框的过滤列表就会残缺或错乱。

第三,模式需要重复。底层缓冲区要求每个分组同时包含描述与模式两段信息,因此同一个通配符往往需要在字符串中重复出现。漏写某一段,会使对应分组的过滤失效。

第四,括号等格式细节必须原样保留。例如第一个分组之后的不配对括号,虽然看起来像是笔误,实际上却是底层格式的一部分,删除后反而会导致行为异常。

第五,取消行为的兼容性。默认情况下,使用者在对话框上按下"取消"按钮时,函数会返回一个取消错误,很多既有程序正是依赖这一错误信号来分支处理"未选择文件"的流程。若将默认行为改为不产生错误,会破坏大量已有代码,因此相关改动必须以可配置选项的形式提供,例如增加一个"取消时返回错误"的开关端子,而不能直接修改默认语义。

第六,附加条目的处理。系统对话框默认会在过滤列表末尾附加"所有文件"条目,函数没有提供直接移除该条目的开关。若工程要求隐藏这一选项,同样需要以功能请求的形式向厂商提出,期待后续版本提供相应配置。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐