SDL3_API分类参考_文件对话框(CategoryDialog)

2026-3-7 / 0 评论 / 0 阅读

文件对话框子系统(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()

核心知识点补充

  1. 关键前置条件

    • 必须初始化 SDL 视频子系统(SDL_Init(SDL_INIT_VIDEO)),否则对话框无法显示;
    • 回调函数可能在非主线程执行,若需操作 UI/渲染资源,需通过 SDL 事件队列同步到主线程。
  2. 文件过滤规则格式

    • 扩展名模式使用分号 ; 分隔(如 "*.png;*.jpg");
    • 过滤器名称用于对话框的下拉选择(如「图片文件」「文本文件」);
    • 通配符 *.* 表示所有文件,是通用过滤器。
  3. 非阻塞特性处理

    • 示例中使用 SDL_Delay() + 全局标志等待回调,实际应用中建议:
      1. 将标志整合到 SDL 事件循环中;
      2. 回调函数中发送自定义 SDL 事件,主线程处理事件时执行后续逻辑;
      3. 避免长时间阻塞主线程,保证应用响应性。
  4. 平台兼容性 平台 支持情况 特殊说明
    Windows 完全支持(Open/Save/Folder) 原生文件资源管理器样式
    macOS 完全支持(Open/Save/Folder) 原生访达(Finder)样式
    Linux 完全支持(依赖桌面环境) GTK/KDE 风格,无桌面环境可能降级为终端选择
    移动平台 仅部分支持(需适配) Android/iOS 需调用系统文件选择器

总结

  1. 核心优势

    • 跨平台统一的文件对话框接口,无需适配 Windows 的 GetOpenFileName、macOS 的 NSOpenPanel 等原生 API;
    • 非阻塞设计,避免对话框阻塞应用主线程,保证应用响应性;
    • 支持文件过滤、多选、默认路径等实用配置,满足大部分文件操作场景;
    • 基于系统原生 UI,视觉体验与操作系统一致。
  2. 使用建议

    • 简单场景优先使用 SDL_ShowOpenFileDialog/SDL_ShowSaveFileDialog/SDL_ShowOpenFolderDialog
    • 复杂配置(如指定父窗口、自定义样式)使用 SDL_ShowFileDialogWithProperties
    • 回调函数中避免直接操作 UI,需同步到主线程;
    • 过滤规则建议包含「所有文件」选项,提升用户灵活性;
    • 处理路径时注意跨平台分隔符(Windows 用 \,Linux/macOS 用 /),可使用 SDL 路径工具函数统一处理。
  3. 关键点回顾

    • 显示文件对话框必须初始化 SDL 视频子系统;
    • 对话框为非阻塞操作,结果通过 SDL_DialogFileCallback 回调返回;
    • SDL_DialogFileFilter 用于设置文件类型过滤规则,扩展名用分号分隔;
    • 回调可能在非主线程执行,需注意线程安全(如 UI 操作、资源访问)。

评论一下?

OωO
取消