SDL3_API分类参考_键盘(CategoryKeyboard)

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

键盘子系统(CategoryKeyboard)

SDL 提供的键盘管理功能集,用于处理键盘设备检测、按键状态查询、文本输入等核心键盘交互逻辑。

关于不同类型程序中键盘输入的最佳实践,可参考官方文档:
https://wiki.libsdl.org/SDL3/BestKeyboardPractices


函数

  • SDL_ClearComposition:清空当前的输入法候选文本(适用于中文/日文等输入法的组合输入状态)
  • SDL_GetKeyboardFocus:获取当前拥有键盘焦点的 SDL 窗口(返回 SDL_Window 指针)
  • SDL_GetKeyboardNameForID:根据键盘设备 ID 获取对应的设备名称(如 "USB Keyboard")
  • SDL_GetKeyboards:枚举系统中所有已连接的键盘设备(返回设备 ID 列表及数量)
  • SDL_GetKeyboardState:获取当前所有按键的状态(返回一个字节数组,索引为扫描码,值为 1 表示按下,0 表示释放)
  • SDL_GetKeyFromName:根据按键名称(如 "A"、"Escape")获取对应的 SDL_Keycode(按键码,与键盘布局相关)
  • SDL_GetKeyFromScancode:将 SDL_Scancode(扫描码,与硬件位置相关)转换为 SDL_Keycode(按键码)
  • SDL_GetKeyName:根据 SDL_Keycode 获取对应的按键名称(如 SDLK_a 返回 "A")
  • SDL_GetModState:获取当前的键盘修饰键状态(如 Shift/Ctrl/Alt 是否按下,返回 SDL_Keymod 组合值)
  • SDL_GetScancodeFromKey:将 SDL_Keycode(按键码)转换为 SDL_Scancode(扫描码)
  • SDL_GetScancodeFromName:根据扫描码名称(如 "ScanCode_A")获取对应的 SDL_Scancode
  • SDL_GetScancodeName:根据 SDL_Scancode 获取对应的扫描码名称(如 SDL_SCANCODE_A 返回 "A")
  • SDL_GetTextInputArea:获取当前设置的文本输入区域(用于移动平台虚拟键盘的位置适配)
  • SDL_HasKeyboard:检查系统是否连接了至少一个键盘设备(返回布尔值)
  • SDL_HasScreenKeyboardSupport:检查当前平台是否支持屏幕虚拟键盘(如手机/平板,返回布尔值)
  • SDL_ResetKeyboard:重置键盘状态(清除所有按键按下状态,恢复修饰键为默认)
  • SDL_ScreenKeyboardShown:检查屏幕虚拟键盘是否处于显示状态(返回布尔值)
  • SDL_SetModState:手动设置键盘修饰键状态(仅用于模拟,不会实际改变物理按键状态)
  • SDL_SetScancodeName:自定义扫描码的名称(覆盖系统默认名称)
  • SDL_SetTextInputArea:设置文本输入区域(移动平台虚拟键盘会避开该区域显示)
  • SDL_StartTextInput:启用文本输入功能(激活输入法,触发 SDL_TextInputEvent 事件)
  • SDL_StartTextInputWithProperties:带属性的文本输入启用(指定输入类型,如数字/密码)
  • SDL_StopTextInput:停止文本输入功能(禁用输入法,不再接收文本输入事件)
  • SDL_TextInputActive:检查文本输入功能是否处于激活状态(返回布尔值)

数据类型

  • SDL_KeyboardID:键盘设备唯一标识类型(用于区分多个连接的键盘设备)

结构体

  • (无)

枚举

  • SDL_Capitalization:文本大小写规则枚举(如 SDL_CAPITALIZATION_NONE/SDL_CAPITALIZATION_SENTENCES,用于控制输入文本的大小写)
  • SDL_TextInputType:文本输入类型枚举(如 SDL_TEXT_INPUT_TYPE_TEXT/SDL_TEXT_INPUT_TYPE_NUMBER/SDL_TEXT_INPUT_TYPE_PASSWORD,限定输入内容类型)

  • (无)

FreeBASIC 示例代码

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

' 辅助函数:打印修饰键状态
Sub PrintModState()
    Dim As SDL_Keymod modState = SDL_GetModState()
    Dim As String modStr = ""

    If (modState And SDL_MOD_SHIFT) Then modStr &= "Shift "
    If (modState And SDL_MOD_CTRL) Then modStr &= "Ctrl "
    If (modState And SDL_MOD_ALT) Then modStr &= "Alt "
    If (modState And SDL_MOD_GUI) Then modStr &= "GUI "  ' Windows/Command 键

    If (modStr = "") Then modStr = "无"
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "当前修饰键状态:%s", modStr)
End Sub

' 主程序
Dim As SDL_Window Ptr window = NULL
Dim As SDL_Event evt
Dim As UByte Ptr keyState = NULL
Dim As SDL_KeyboardID Ptr keyboardIDs = NULL
Dim As Integer keyboardCount = 0
Dim As Integer quit = 0
Dim As String inputText = ""

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

' 2. 检查键盘设备
If (Not SDL_HasKeyboard()) Then
    SDL_LogError(SDL_LOG_CATEGORY_INPUT, "系统未检测到键盘设备")
    SDL_Quit()
    End 1
End If

' 枚举键盘设备
keyboardCount = SDL_GetKeyboards(0, NULL)
If (keyboardCount > 0) Then
    keyboardIDs = Callocate(keyboardCount * SizeOf(SDL_KeyboardID))
    keyboardCount = SDL_GetKeyboards(keyboardCount, keyboardIDs)
    SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "检测到 %d 个键盘设备", keyboardCount)
    For i As Integer = 0 To keyboardCount - 1
        Dim As ZString Ptr kbName = SDL_GetKeyboardNameForID(keyboardIDs[i])
        SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "键盘 %d:%s", i, kbName)
        SDL_free(kbName)
    Next
End If

' 3. 创建窗口
window = SDL_CreateWindow("SDL 键盘输入示例", _
    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, _
    600, 400, SDL_WINDOW_SHOWN)
If (window = NULL) Then
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建窗口失败:%s", SDL_GetError())
    SDL_Quit()
    End 1
End If

' 4. 启用文本输入功能
SDL_StartTextInput()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "文本输入功能已启用")

SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "=== 键盘操作示例 ===")
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "按 ESC 退出 | 按任意键测试按键检测 | 输入文本将显示在日志中 | 按 F1 打印修饰键状态")

' 5. 主事件循环
While (quit = 0)
    ' 获取当前按键状态(实时查询,非事件驱动)
    keyState = SDL_GetKeyboardState(NULL)

    ' 处理事件队列
    While (SDL_PollEvent(@evt))
        Select Case evt.type
            ' 窗口关闭事件
            Case SDL_QUITEVENT
                quit = 1

            ' 键盘按键事件(按下/释放)
            Case SDL_KEYDOWN
                Select Case evt.key.keysym.sym
                    Case SDLK_ESCAPE
                        SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "ESC 键按下,退出程序")
                        quit = 1

                    Case SDLK_F1
                        PrintModState()

                    Case Else
                        ' 打印按键信息(扫描码 + 按键码 + 名称)
                        Dim As SDL_Scancode scancode = evt.key.keysym.scancode
                        Dim As SDL_Keycode keycode = evt.key.keysym.sym
                        Dim As ZString Ptr scName = SDL_GetScancodeName(scancode)
                        Dim As ZString Ptr kName = SDL_GetKeyName(keycode)

                        SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, _
                            "按键按下 - 扫描码:%s (0x%X) | 按键码:%s (0x%X)", _
                            scName, scancode, kName, keycode)
                        SDL_free(scName)
                        SDL_free(kName)
                End Select

            ' 文本输入事件(输入法处理后的完整文本)
            Case SDL_TEXTINPUT
                inputText &= *evt.text.text
                SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "文本输入:%s | 累计输入:%s", evt.text.text, inputText)

            ' 文本编辑事件(输入法组合状态,如中文拼音)
            Case SDL_TEXTEDITING
                SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "文本编辑:%s (光标位置:%d,选择长度:%d)", _
                    evt.edit.text, evt.edit.start, evt.edit.length)
        End Select
    Wend

    ' 实时检测特定按键(非事件驱动)
    If (keyState[SDL_SCANCODE_SPACE] = 1) Then
        Static As Integer spacePressed = 0
        If (Not spacePressed) Then
            SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "空格键被按住(实时检测)")
            spacePressed = 1
        End If
    Else
        spacePressed = 0
    End If

    SDL_Delay(10)
Wend

' 6. 清理资源
SDL_StopTextInput()
If (keyboardIDs <> NULL) Then
    Deallocate(keyboardIDs)
End If
SDL_DestroyWindow(window)
SDL_Quit()

SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "程序正常退出,累计输入文本:%s", inputText)
End 0

总结

  1. SDL 键盘子系统分两类核心能力:
    • 按键状态查询SDL_GetKeyboardState 实时获取按键状态(非事件驱动),SDL_KEYDOWN/UP 事件驱动检测;
    • 文本输入处理SDL_StartTextInput 启用输入法,通过 SDL_TEXTINPUT 事件接收完整文本(适配多语言输入法);
  2. FreeBASIC 中使用时需区分「扫描码(Scancode)」和「按键码(Keycode)」:
    • 扫描码:与硬件位置绑定(如 SDL_SCANCODE_A 始终对应键盘 A 键位置);
    • 按键码:与键盘布局绑定(如不同语言键盘的 A 键可能对应不同 Keycode);
  3. 关键接口:
    • 设备管理:SDL_GetKeyboards/SDL_GetKeyboardNameForID
    • 状态查询:SDL_GetKeyboardState/SDL_GetModState
    • 文本输入:SDL_StartTextInput/SDL_TEXTINPUT 事件。

评论一下?

OωO
取消