文件对话框子系统(CategoryDialog)
SDL 提供了文件对话框相关接口,允许应用通过系统原生的图形界面让用户选择文件/文件夹——支持「打开文件」「保存文件」「选择文件夹」三种核心场景,还可控制文件过滤规则、是否允许多选等细节。
重要特性
- 对话框基于系统原生 GUI 实现,视觉风格与操作系统保持一致;
- 显示对话框是非阻塞操作:调用后立即返回控制权给应用,用户完成选择后(确认/取消),SDL 会调用预设的回调函数(可能在其他线程执行)返回结果。
函数
- SDL_ShowOpenFileDialog:显示「打开文件」对话框,支持文件过滤、多选配置,用户选择后触发回调返回选中的文件路径列表
- SDL_ShowSaveFileDialog:显示「保存文件」对话框,支持文件过滤,用户确认后触发回调返回保存路径
- SDL_ShowOpenFolderDialog:显示「选择文件夹」对话框,用户选择后触发回调返回选中的文件夹路径
- SDL_ShowFileDialogWithProperties:显示自定义属性的文件对话框(最灵活的接口),支持指定对话框类型、过滤规则、父窗口、默认路径等所有配置
数据类型
- SDL_DialogFileCallback:文件对话框回调函数类型,用户完成选择后触发,参数包含「是否取消」「选中的文件/文件夹路径数组」「自定义用户数据」
结构体
- SDL_DialogFileFilter:文件过滤规则结构体,包含过滤器名称(如「图片文件」)和扩展名列表(如「.png;.jpg」)
枚举
- SDL_FileDialogType:文件对话框类型枚举,核心取值:
- SDL_FILEDIALOG_OPEN:打开文件对话框
- SDL_FILEDIALOG_SAVE:保存文件对话框
- SDL_FILEDIALOG_OPEN_FOLDER:选择文件夹对话框
宏
- (无)
FreeBASIC 示例代码
' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库)
#Include "SDL.bi"
' 补充枚举/类型/结构体/函数声明(FreeBASIC 绑定可能缺失)
Enum SDL_FileDialogType
SDL_FILEDIALOG_OPEN = 0 ' 打开文件
SDL_FILEDIALOG_SAVE = 1 ' 保存文件
SDL_FILEDIALOG_OPEN_FOLDER = 2 ' 选择文件夹
End Enum
' 文件过滤规则结构体
Type SDL_DialogFileFilter
name As ZString Ptr ' 过滤器名称(如 "图片文件")
patterns As ZString Ptr ' 扩展名模式(如 "*.png;*.jpg;*.bmp")
End Type
' 回调函数类型定义:用户完成选择后触发
Type SDL_DialogFileCallback As Sub( _
ByVal cancelled As SDL_bool, _
ByVal file_count As Integer, _
ByVal files As ZString Ptr Ptr, _
ByVal userdata As Any Ptr _
)
' 核心函数声明
Declare Function SDL_ShowOpenFileDialog CDecl ( _
ByVal parent As SDL_Window Ptr, _
ByVal title As ZString Ptr, _
ByVal default_path As ZString Ptr, _
ByVal filter_count As Integer, _
ByVal filters As SDL_DialogFileFilter Ptr, _
ByVal allow_multiple As SDL_bool, _
ByVal callback As SDL_DialogFileCallback, _
ByVal userdata As Any Ptr _
) As SDL_bool
Declare Function SDL_ShowSaveFileDialog CDecl ( _
ByVal parent As SDL_Window Ptr, _
ByVal title As ZString Ptr, _
ByVal default_path As ZString Ptr, _
ByVal filter_count As Integer, _
ByVal filters As SDL_DialogFileFilter Ptr, _
ByVal callback As SDL_DialogFileCallback, _
ByVal userdata As Any Ptr _
) As SDL_bool
Declare Function SDL_ShowOpenFolderDialog CDecl ( _
ByVal parent As SDL_Window Ptr, _
ByVal title As ZString Ptr, _
ByVal default_path As ZString Ptr, _
ByVal callback As SDL_DialogFileCallback, _
ByVal userdata As Any Ptr _
) As SDL_bool
' 全局标志:用于主线程等待回调执行完成
Dim Shared As SDL_bool g_dialogCompleted = SDL_FALSE
' 回调函数:处理「打开文件」对话框结果
Sub OpenFileCallback( _
ByVal cancelled As SDL_bool, _
ByVal file_count As Integer, _
ByVal files As ZString Ptr Ptr, _
ByVal userdata As Any Ptr _
)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【打开文件对话框回调】")
If (cancelled = SDL_TRUE) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户取消了文件选择")
ElseIf (file_count > 0) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选中了 %d 个文件:", file_count)
For i As Integer = 0 To file_count - 1
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " - %s", *files[i])
Next
Else
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "未选中任何文件")
End If
' 标记对话框操作完成
g_dialogCompleted = SDL_TRUE
End Sub
' 回调函数:处理「保存文件」对话框结果
Sub SaveFileCallback( _
ByVal cancelled As SDL_bool, _
ByVal file_count As Integer, _
ByVal files As ZString Ptr Ptr, _
ByVal userdata As Any Ptr _
)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【保存文件对话框回调】")
If (cancelled = SDL_TRUE) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户取消了保存操作")
ElseIf (file_count = 1) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选择的保存路径:%s", *files[0])
' 模拟保存文件逻辑
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "→ 开始保存文件到指定路径...")
End If
g_dialogCompleted = SDL_TRUE
End Sub
' 回调函数:处理「选择文件夹」对话框结果
Sub OpenFolderCallback( _
ByVal cancelled As SDL_bool, _
ByVal file_count As Integer, _
ByVal files As ZString Ptr Ptr, _
ByVal userdata As Any Ptr _
)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【选择文件夹对话框回调】")
If (cancelled = SDL_TRUE) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户取消了文件夹选择")
ElseIf (file_count = 1) Then
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选中的文件夹:%s", *files[0])
End If
g_dialogCompleted = SDL_TRUE
End Sub
' 示例1:显示「打开文件」对话框(带过滤规则、支持多选)
Sub ShowOpenFileDialogExample()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例1:显示打开文件对话框】")
' 重置完成标志
g_dialogCompleted = SDL_FALSE
' 定义文件过滤规则
Dim As SDL_DialogFileFilter filters(1)
' 过滤器1:图片文件
filters(0).name = StrPtr("图片文件")
filters(0).patterns = StrPtr("*.png;*.jpg;*.jpeg;*.bmp")
' 过滤器2:所有文件
filters(1).name = StrPtr("所有文件")
filters(1).patterns = StrPtr("*.*")
' 显示「打开文件」对话框
Dim As SDL_bool result = SDL_ShowOpenFileDialog( _
NULL, ' 无父窗口
StrPtr("选择要打开的图片文件"), ' 对话框标题
StrPtr("."), ' 默认路径(当前目录)
2, ' 过滤器数量
@filters(0), ' 过滤器数组
SDL_TRUE, ' 允许选择多个文件
@OpenFileCallback, ' 回调函数
NULL ' 自定义用户数据
)
If (result = SDL_FALSE) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "显示打开文件对话框失败:%s", SDL_GetError())
Exit Sub
End If
' 等待回调执行完成(非阻塞对话框需主动等待,实际应用可结合事件循环)
While (g_dialogCompleted = SDL_FALSE)
SDL_Delay(100) ' 避免CPU占用过高
Wend
End Sub
' 示例2:显示「保存文件」对话框(带过滤规则)
Sub ShowSaveFileDialogExample()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例2:显示保存文件对话框】")
g_dialogCompleted = SDL_FALSE
' 定义保存文件的过滤规则(文本文件)
Dim As SDL_DialogFileFilter filter
filter.name = StrPtr("文本文件")
filter.patterns = StrPtr("*.txt")
' 显示「保存文件」对话框
Dim As SDL_bool result = SDL_ShowSaveFileDialog( _
NULL, ' 无父窗口
StrPtr("保存文本文件"), ' 对话框标题
StrPtr("./untitled.txt"), ' 默认保存路径/文件名
1, ' 过滤器数量
@filter, ' 过滤器
@SaveFileCallback, ' 回调函数
NULL ' 自定义用户数据
)
If (result = SDL_FALSE) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "显示保存文件对话框失败:%s", SDL_GetError())
Exit Sub
End If
' 等待回调执行完成
While (g_dialogCompleted = SDL_FALSE)
SDL_Delay(100)
Wend
End Sub
' 示例3:显示「选择文件夹」对话框
Sub ShowOpenFolderDialogExample()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例3:显示选择文件夹对话框】")
g_dialogCompleted = SDL_FALSE
' 显示「选择文件夹」对话框
Dim As SDL_bool result = SDL_ShowOpenFolderDialog( _
NULL, ' 无父窗口
StrPtr("选择工作目录"), ' 对话框标题
StrPtr("."), ' 默认路径
@OpenFolderCallback, ' 回调函数
NULL ' 自定义用户数据
)
If (result = SDL_FALSE) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "显示选择文件夹对话框失败:%s", SDL_GetError())
Exit Sub
End If
' 等待回调执行完成
While (g_dialogCompleted = SDL_FALSE)
SDL_Delay(100)
Wend
End Sub
' 主程序
Sub Main()
' 初始化 SDL(必须初始化视频子系统)
If (SDL_Init(SDL_INIT_VIDEO) < 0) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError())
Exit Sub
End If
' 运行示例
ShowOpenFileDialogExample()
ShowSaveFileDialogExample()
ShowOpenFolderDialogExample()
' 清理 SDL
SDL_Quit()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出")
End Sub
' 运行主程序
Main()
核心知识点补充
-
关键前置条件:
- 必须初始化 SDL 视频子系统(
SDL_Init(SDL_INIT_VIDEO)),否则对话框无法显示; - 回调函数可能在非主线程执行,若需操作 UI/渲染资源,需通过 SDL 事件队列同步到主线程。
- 必须初始化 SDL 视频子系统(
-
文件过滤规则格式:
- 扩展名模式使用分号
;分隔(如"*.png;*.jpg"); - 过滤器名称用于对话框的下拉选择(如「图片文件」「文本文件」);
- 通配符
*.*表示所有文件,是通用过滤器。
- 扩展名模式使用分号
-
非阻塞特性处理:
- 示例中使用
SDL_Delay()+ 全局标志等待回调,实际应用中建议:- 将标志整合到 SDL 事件循环中;
- 回调函数中发送自定义 SDL 事件,主线程处理事件时执行后续逻辑;
- 避免长时间阻塞主线程,保证应用响应性。
- 示例中使用
-
平台兼容性: 平台 支持情况 特殊说明 Windows 完全支持(Open/Save/Folder) 原生文件资源管理器样式 macOS 完全支持(Open/Save/Folder) 原生访达(Finder)样式 Linux 完全支持(依赖桌面环境) GTK/KDE 风格,无桌面环境可能降级为终端选择 移动平台 仅部分支持(需适配) Android/iOS 需调用系统文件选择器
总结
-
核心优势:
- 跨平台统一的文件对话框接口,无需适配 Windows 的 GetOpenFileName、macOS 的 NSOpenPanel 等原生 API;
- 非阻塞设计,避免对话框阻塞应用主线程,保证应用响应性;
- 支持文件过滤、多选、默认路径等实用配置,满足大部分文件操作场景;
- 基于系统原生 UI,视觉体验与操作系统一致。
-
使用建议:
- 简单场景优先使用
SDL_ShowOpenFileDialog/SDL_ShowSaveFileDialog/SDL_ShowOpenFolderDialog; - 复杂配置(如指定父窗口、自定义样式)使用
SDL_ShowFileDialogWithProperties; - 回调函数中避免直接操作 UI,需同步到主线程;
- 过滤规则建议包含「所有文件」选项,提升用户灵活性;
- 处理路径时注意跨平台分隔符(Windows 用
\,Linux/macOS 用/),可使用 SDL 路径工具函数统一处理。
- 简单场景优先使用
-
关键点回顾:
- 显示文件对话框必须初始化 SDL 视频子系统;
- 对话框为非阻塞操作,结果通过
SDL_DialogFileCallback回调返回; SDL_DialogFileFilter用于设置文件类型过滤规则,扩展名用分号分隔;- 回调可能在非主线程执行,需注意线程安全(如 UI 操作、资源访问)。
评论一下?