SDL3_API分类参考_剪贴板(CategoryClipboard)

2026-3-6 / 0 评论 / 5 阅读

剪贴板子系统(CategoryClipboard)

SDL 提供对系统剪贴板的完整访问能力,既能读取其他进程写入的剪贴板内容,也能将自身数据发布到剪贴板中。

SDL 剪贴板不仅支持文本,还能按 MIME 类型访问和发布任意格式的数据。

基础用法(文本)

获取/发布纯文本到系统剪贴板非常简单,只需分别调用 SDL_GetClipboardText()SDL_SetClipboardText()

  • 处理的是 UTF-8 编码 的 C 字符串;
  • 数据传输和编码转换由 SDL 完全托管,无需手动处理。

剪贴板回调(非文本数据)

当剪贴板包含非文本数据时,逻辑会更复杂:

  • 系统剪贴板可存储任意类型数据,甚至同一数据的多种格式(如绘图软件复制图片时,同时提供 BMP/JPG/PNG 格式);
  • 读取非文本数据
    1. SDL_HasClipboardData() 判断目标 MIME 类型是否存在;
    2. SDL_GetClipboardMimeTypes() 获取剪贴板支持的所有 MIME 类型列表;
    3. SDL_GetClipboardData() 指定 MIME 类型读取对应数据。
  • 写入非文本数据
    调用 SDL_SetClipboardData() 时,无需直接传入数据,只需指定支持的 MIME 类型和回调函数;
    仅当其他程序请求粘贴时,SDL 才会触发回调生成对应格式的数据——避免提前拷贝大量数据,也支持为同一内容提供多格式(如 PNG/JPG),仅在被请求时才编码。

主选择区(Primary Selection)

X11/Wayland 系统除常规剪贴板外,还有「主选择区」(选中但未显式复制的文本):

  • SDL 提供 SDL_GetPrimarySelectionText()/SDL_SetPrimarySelectionText() 操作该区域;
  • 无此概念的平台(如 Windows/macOS)也支持这些 API,但仅在应用内保存字符串,系统不会外部修改该内容。

函数

  • SDL_ClearClipboardData:清空系统剪贴板的所有数据(包括所有 MIME 类型)
  • SDL_GetClipboardData:按指定 MIME 类型读取剪贴板数据(返回数据缓冲区和长度)
  • SDL_GetClipboardMimeTypes:获取剪贴板中可用的所有 MIME 类型列表(返回字符串数组)
  • SDL_GetClipboardText:读取剪贴板中的 UTF-8 文本内容(最常用的文本读取接口)
  • SDL_GetPrimarySelectionText:读取 X11/Wayland 主选择区的 UTF-8 文本(其他平台返回应用内缓存)
  • SDL_HasClipboardData:判断剪贴板是否包含指定 MIME 类型的数据(返回布尔值)
  • SDL_HasClipboardText:判断剪贴板是否包含文本数据(快捷接口,等价于检查 text/plain 类型)
  • SDL_HasPrimarySelectionText:判断主选择区是否包含文本数据
  • SDL_SetClipboardData:设置剪贴板的非文本数据(传入 MIME 类型列表和数据生成回调)
  • SDL_SetClipboardText:设置剪贴板的 UTF-8 文本内容(最常用的文本写入接口)
  • SDL_SetPrimarySelectionText:设置 X11/Wayland 主选择区的文本(其他平台仅缓存到应用内)

数据类型

  • SDL_ClipboardCleanupCallback:剪贴板数据清理回调类型(释放 SDL_SetClipboardData 生成的数据缓冲区)
  • SDL_ClipboardDataCallback:剪贴板数据生成回调类型(当其他程序请求粘贴时,生成指定 MIME 类型的数据)

结构体

  • (无)

枚举

  • (无)

  • (无)

FreeBASIC 示例代码

' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL 库)
#Include "SDL.bi"

' 非文本数据回调:生成 PNG 格式数据(示例)
Function ClipboardDataCallback Cdecl (ByVal mimetype As ZString Ptr, ByVal userdata As Any Ptr, ByVal size As UInteger Ptr) As UByte Ptr
    ' 模拟 PNG 数据(实际应从文件/内存读取真实数据)
    Static As UByte pngData(0 To 10) = { &H89, &H50, &H4E, &H47, &H0D, &H0A, &H1A, &H0A, 0, 0, 0 }
    *size = 11  ' 数据长度
    Return @pngData(0)
End Function

' 数据清理回调:释放生成的剪贴板数据
Sub ClipboardCleanupCallback Cdecl (ByVal data As UByte Ptr, ByVal userdata As Any Ptr)
    ' 示例中使用静态数据,无需释放;实际应释放动态分配的内存
    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "剪贴板数据已清理")
End Sub

' 主程序
Dim As ZString Ptr clipText
Dim As Integer hasText
Dim As ZString Ptr mimeTypes(0 To 0)  ' MIME 类型列表
Dim As Integer quit = 0
Dim As SDL_Event evt

' 初始化 SDL
If (SDL_Init(SDL_INIT_VIDEO) < 0) Then
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError())
    End 1
End If

' 创建窗口(SDL 剪贴板 API 需初始化视频子系统,窗口可隐藏)
Dim As SDL_Window Ptr window = SDL_CreateWindow("SDL 剪贴板示例", _
    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, _
    400, 300, SDL_WINDOW_SHOWN)
If (window = NULL) Then
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建窗口失败:%s", SDL_GetError())
    SDL_Quit()
    End 1
End If

SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "=== 剪贴板操作示例 ===")
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "按 C 复制文本 | 按 V 粘贴文本 | 按 P 设置非文本数据 | 按 ESC 退出")

' 主循环
While (quit = 0)
    While (SDL_PollEvent(@evt))
        Select Case evt.type
            Case SDL_QUITEVENT
                quit = 1

            Case SDL_KEYDOWN
                Select Case evt.key.keysym.sym
                    ' 1. 复制文本到剪贴板
                    Case SDLK_c
                        If (SDL_SetClipboardText("SDL 剪贴板示例 - UTF-8 文本 🎮") = 0) Then
                            SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "已复制文本到剪贴板")
                        Else
                            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "复制文本失败:%s", SDL_GetError())
                        End If

                    ' 2. 粘贴剪贴板文本
                    Case SDLK_v
                        hasText = SDL_HasClipboardText()
                        If (hasText) Then
                            clipText = SDL_GetClipboardText()
                            If (clipText <> NULL) Then
                                SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "剪贴板文本:%s", clipText)
                                SDL_free(clipText)  ' 必须释放返回的字符串
                            End If
                        Else
                            SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "剪贴板无文本数据")
                        End If

                    ' 3. 设置非文本数据(PNG 格式)
                    Case SDLK_p
                        mimeTypes(0) = "image/png"  ' 支持的 MIME 类型
                        If (SDL_SetClipboardData(1, @mimeTypes(0), _
                            @ClipboardDataCallback, @ClipboardCleanupCallback, NULL) = 0) Then
                            SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "已设置 PNG 格式剪贴板数据")

                            ' 检查是否存在该 MIME 类型
                            If (SDL_HasClipboardData("image/png")) Then
                                SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "剪贴板包含 image/png 数据")
                            End If
                        Else
                            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "设置非文本数据失败:%s", SDL_GetError())
                        End If

                    ' 退出程序
                    Case SDLK_ESCAPE
                        quit = 1
                End Select
        End Select
    Wend

    SDL_Delay(10)
Wend

' 清理资源
SDL_DestroyWindow(window)
SDL_Quit()
End 0

总结

  1. SDL 剪贴板核心接口分两类:SDL_Get/SetClipboardText 处理 UTF-8 文本(最常用),SDL_Get/SetClipboardData 处理任意 MIME 类型数据;
  2. FreeBASIC 中使用文本接口时,需注意 SDL_GetClipboardText 返回的字符串必须用 SDL_free 释放,避免内存泄漏;
  3. 非文本数据需通过回调函数生成,仅在被请求时才编码/拷贝数据,SDL_HasClipboardData 可提前判断目标格式是否存在。

评论一下?

OωO
取消