VisualFreeBasic的编程文档和教程
论坛的首页 勇芳的软件
教程和帮助
  • VisualFreeBasic编程文档
  • 勇芳系列软件帮助说明教程
  • 留言或交流 登录
    登录
    侧边栏壁纸
    博主头像
    勇芳

    • 累计撰写 326 篇文章
    • 累计收到 0 条评论
    • 首页
    • 栏目
      • 论坛的首页
      • 勇芳的软件
      • 教程和帮助
        • VisualFreeBasic编程文档
        • 勇芳系列软件帮助说明教程
      • 留言或交流
      • 登录
    VisualFreeBasic编程文档
    • SDL3_API分类参考_其它功能(CategoryMisc) 2026-3-7
      SDL3_API分类参考_其它功能(CategoryMisc) 其它功能子系统(CategoryMisc) SDL 中无法归类到其他特定子系统的零散 API 函数集合,这类函数功能独立且不隶属于某一核心模块,目前仅包含 URL 打开这一通用功能。 函数 SDL_OpenURL:调用系统默认程序打开指定的 URL(支持 http/https 网页链接、mailto 邮件链接、file 本地文件链接等),跨平台行为一致,无需关心不同系统的 URL 打开方式差异 数据类型 (无) 结构体 (无) 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充 SDL_OpenURL 函数声明(FreeBASIC 绑定可能缺失) Declare Function SDL_OpenURL CDecl (ByVal url As ZString Ptr) As SDL_bool ' 辅助函数:封装 URL 打开逻辑并处理错误 Function OpenURLHelper(ByVal url As ZString Ptr, ByVal desc As ZString Ptr) As SDL_bool SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "尝试打开 %s:%s", desc, url) ' 调用 SDL_OpenURL 打开 URL Dim As SDL_bool result = SDL_OpenURL(url) ' 处理返回结果 If (result = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "✓ %s 打开成功", desc) Return SDL_TRUE Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "✗ %s 打开失败:%s", desc, SDL_GetError()) Return SDL_FALSE End If End Function ' ==================== 示例 1:打开网页链接 ==================== Sub OpenWebURLExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例 1:打开网页链接】") ' 打开 SDL 官方网站 OpenURLHelper(StrPtr("https://www.libsdl.org/"), StrPtr("SDL 官方网站")) ' 打开带参数的网页链接(如搜索页面) OpenURLHelper(StrPtr("https://www.google.com/search?q=SDL+OpenURL"), StrPtr("Google 搜索页面")) End Sub ' ==================== 示例 2:打开邮件链接 ==================== Sub OpenMailURLExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例 2:打开邮件链接】") ' 打开系统默认邮件客户端,预填收件人、主题、正文 Dim As ZString * 256 mailURL SDL_snprintf( _ @mailURL, _ sizeof(mailURL), _ "mailto:support@example.com?subject=SDL 反馈&body=我在使用 SDL_OpenURL 时遇到了以下问题:" _ ) OpenURLHelper(@mailURL, StrPtr("邮件链接")) End Sub ' ==================== 示例 3:打开本地文件/文件夹 ==================== Sub OpenLocalFileURLExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例 3:打开本地文件/文件夹】") ' 注意:本地文件需使用 file:// 协议,且路径格式需适配平台 #If Defined(SDL_PLATFORM_WINDOWS) ' Windows 路径示例(需转义反斜杠,或使用正斜杠) Dim As ZString Ptr folderURL = StrPtr("file:///C:/Users/Public/Documents") OpenURLHelper(folderURL, StrPtr("Windows 公共文档文件夹")) #ElseIf Defined(SDL_PLATFORM_LINUX) Or Defined(SDL_PLATFORM_MACOS) ' Linux/macOS 路径示例 Dim As ZString Ptr folderURL = StrPtr("file:///home/user/Documents") OpenURLHelper(folderURL, StrPtr("Linux 文档文件夹")) #EndIf End Sub ' ==================== 示例 4:处理无效 URL ==================== Sub OpenInvalidURLExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例 4:处理无效 URL】") ' 无效的 URL(无协议头) OpenURLHelper(StrPtr("www.example.com"), StrPtr("无效 URL(无协议头)")) ' 不存在的本地文件 OpenURLHelper(StrPtr("file:///不存在的文件路径.txt"), StrPtr("不存在的本地文件")) End Sub ' ==================== 主程序 ==================== Sub Main() ' 初始化 SDL(Misc 子系统无需特定初始化,基础初始化即可) If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 OpenWebURLExample() OpenMailURLExample() OpenLocalFileURLExample() OpenInvalidURLExample() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 URL 格式规范: SDL_OpenURL 支持标准 RFC 3986 格式的 URL,必须包含协议头(如 http://、mailto:、file://),无协议头的字符串会被判定为无效 URL; 特殊字符(如空格、中文、问号)需进行 URL 编码(如空格替换为 %20,中文转换为 UTF-8 编码的十六进制值); 本地文件路径需使用 file:// 协议,Windows 路径需注意斜杠方向(推荐使用正斜杠 /,避免反斜杠 \ 的转义问题)。 跨平台实现逻辑: 平台 底层实现方式 特殊说明 Windows ShellExecuteW 函数 需要 URL 转换为宽字符格式 macOS NSWorkspace 的 openURL 方法 需在主线程调用,否则可能无响应 Linux xdg-open 命令(桌面环境) 依赖桌面环境的默认程序配置 Android Intent.ACTION_VIEW 意图 需申请 INTERNET 权限(网页链接) iOS UIApplication 的 openURL 方法 需配置 ATS 规则(http 链接) 错误处理要点: SDL_OpenURL 返回 SDL_TRUE 仅表示「成功发起打开请求」,不代表 URL 本身有效或程序能正常打开; 返回 SDL_FALSE 时,可通过 SDL_GetError() 获取具体错误信息(如「无效的 URL 格式」「无默认程序关联」); 本地文件 URL 失败常见原因:文件不存在、权限不足、无默认文件管理器。 使用限制: 移动平台(Android/iOS)打开 URL 可能触发应用跳转,需处理应用生命周期变化; macOS/Linux 下打开 URL 可能需要应用有桌面权限(沙箱环境下需配置); 避免在子线程中频繁调用 SDL_OpenURL,部分平台(如 macOS)要求主线程调用。 总结 核心优势: 跨平台统一的 URL 打开接口,无需针对不同系统编写原生代码; 自动适配系统默认程序,符合用户使用习惯; 简单的返回值和错误信息,便于错误处理。 使用建议: 调用前确保 URL 格式正确(含协议头、特殊字符编码); 对返回结果进行判断,失败时给出用户友好提示; 本地文件 URL 需做平台适配,避免路径格式错误; 移动平台调用后需处理应用切换/返回的逻辑。 关键点回顾: CategoryMisc 是 SDL 的杂项函数集合,目前仅包含 SDL_OpenURL 一个核心函数; SDL_OpenURL 可打开网页、邮件、本地文件等各类标准 URL,跨平台行为一致; URL 必须包含协议头,特殊字符需编码,本地文件需使用 file:// 协议; 返回值仅表示请求发起结果,需结合 SDL_GetError() 排查失败原因。
      • 2026年-3月-7日
      • 2 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_GUID 处理(CategoryGUID) 2026-3-7
      SDL3_API分类参考_GUID 处理(CategoryGUID) GUID 处理子系统(CategoryGUID) GUID(全局唯一标识符)是一个 128 位的数值,用于唯一标识某个对象/实体——其核心特性是「全局唯一性」,可确保在不同系统、不同场景下不会出现重复值。 SDL 为 GUID 提供了核心的序列化/反序列化能力:支持将二进制格式的 GUID 转换为人类可读的字符串格式,也支持将字符串格式的 GUID 解析回二进制结构,方便存储、传输和展示。 函数 SDL_GUIDToString:将二进制格式的 SDL_GUID 结构体转换为字符串格式(输出如 "12345678-1234-1234-1234-1234567890ab"),参数需指定输出缓冲区大小以避免溢出 SDL_StringToGUID:将字符串格式的 GUID(标准 UUID 格式)解析为二进制的 SDL_GUID 结构体,解析失败时返回全零的 GUID 数据类型 (无) 结构体 SDL_GUID:存储 128 位 GUID 的二进制结构体,内部包含一个 16 字节的数组(对应 128 位),是 SDL 中表示 GUID 的核心数据结构 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充 SDL_GUID 结构体和函数声明(FreeBASIC 绑定可能缺失) Type SDL_GUID data(0 To 15) As Uint8 ' 16字节 = 128位,存储GUID的二进制数据 End Type ' GUID字符串的标准长度:36个可见字符 + 1个终止符 = 37 Const SDL_GUID_STRING_LENGTH = 37 Declare Sub SDL_GUIDToString CDecl ( _ ByVal guid As SDL_GUID, _ ByVal str As ZString Ptr, _ ByVal maxlen As Size_t _ ) Declare Function SDL_StringToGUID CDecl ( _ ByVal str As ZString Ptr _ ) As SDL_GUID ' 辅助函数:打印二进制 GUID 数据 Sub PrintGUIDBinary(ByVal guid As SDL_GUID) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "GUID 二进制数据(16字节):") For i As Integer = 0 To 15 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 字节 %2d: 0x%02X", i, guid.data(i)) ' 每4字节换行,方便阅读 If ((i + 1) Mod 4 = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "") End If Next End Sub ' 辅助函数:比较两个 GUID 是否相等 Function GUIDEquals(ByVal a As SDL_GUID, ByVal b As SDL_GUID) As SDL_bool For i As Integer = 0 To 15 If (a.data(i) <> b.data(i)) Then Return SDL_FALSE End If Next Return SDL_TRUE End Function ' ==================== 示例 1:GUID 转字符串 ==================== Sub GUIDToStringExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例 1:GUID 转字符串】") ' 构造一个测试用的 GUID(二进制数据) Dim As SDL_GUID testGUID ' 手动填充测试数据(模拟一个真实的 GUID 二进制值) testGUID.data(0) = &H12 : testGUID.data(1) = &H34 : testGUID.data(2) = &H56 : testGUID.data(3) = &H78 testGUID.data(4) = &H90 : testGUID.data(5) = &HAB : testGUID.data(6) = &HCD : testGUID.data(7) = &HEF testGUID.data(8) = &H11 : testGUID.data(9) = &H22 : testGUID.data(10) = &H33 : testGUID.data(11) = &H44 testGUID.data(12) = &H55 : testGUID.data(13) = &H66 : testGUID.data(14) = &H77 : testGUID.data(15) = &H88 ' 打印二进制 GUID PrintGUIDBinary(testGUID) ' 转换为字符串格式 Dim As ZString * SDL_GUID_STRING_LENGTH guidStr SDL_GUIDToString(testGUID, @guidStr, sizeof(guidStr)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "GUID 转换为字符串:%s", guidStr) End Sub ' ==================== 示例 2:字符串转 GUID ==================== Sub StringToGUIDExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例 2:字符串转 GUID】") ' 标准格式的 GUID 字符串(UUID 格式) Dim As ZString Ptr guidStr = StrPtr("12345678-90ab-cdef-1122-334455667788") SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "待解析的 GUID 字符串:%s", guidStr) ' 将字符串解析为二进制 GUID Dim As SDL_GUID parsedGUID = SDL_StringToGUID(guidStr) ' 打印解析后的二进制数据 PrintGUIDBinary(parsedGUID) ' 验证解析结果:转换回字符串,检查是否与原字符串一致 Dim As ZString * SDL_GUID_STRING_LENGTH checkStr SDL_GUIDToString(parsedGUID, @checkStr, sizeof(checkStr)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "解析后转回字符串:%s", checkStr) If (SDL_strcmp(guidStr, @checkStr) = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "✓ 解析与转换结果一致") Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "✗ 解析与转换结果不一致") End If End Sub ' ==================== 示例 3:无效 GUID 字符串处理 ==================== Sub InvalidGUIDStringExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例 3:无效 GUID 字符串处理】") ' 无效的 GUID 字符串(长度不足、格式错误) Dim As ZString Ptr invalidStrs(2) = { _ StrPtr("12345678-90ab-cdef-1122"), ' 长度不足 StrPtr("12345678-90ab-cdef-1122-zzzzzzzzzzzz"), ' 包含非十六进制字符 StrPtr("无效的GUID字符串") ' 完全错误格式 } ' 全零 GUID(用于对比解析失败的情况) Dim As SDL_GUID zeroGUID For i As Integer = 0 To 15 zeroGUID.data(i) = 0 Next For i As Integer = 0 To 2 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "解析无效字符串:%s", invalidStrs(i)) Dim As SDL_GUID parsedGUID = SDL_StringToGUID(invalidStrs(i)) If (GUIDEquals(parsedGUID, zeroGUID) = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " → 解析失败,返回全零 GUID") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " → 解析结果非全零(意外情况)") End If Next End Sub ' ==================== 主程序 ==================== Sub Main() ' 初始化 SDL(GUID 子系统无需特定初始化) If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 GUIDToStringExample() StringToGUIDExample() InvalidGUIDStringExample() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 GUID 格式规范: SDL 遵循标准 UUID v4 格式:8-4-4-4-12 共 36 个字符(含 4 个连字符),例如 12345678-1234-1234-1234-1234567890ab; 二进制存储为 16 字节(128 位),字符串格式是其十六进制的可读性表示; SDL_GUIDToString 的输出缓冲区至少需要 37 字节(36 个字符 + 1 个字符串终止符 \0)。 解析/转换规则: SDL_StringToGUID 仅支持标准 UUID 格式的字符串,非标准格式(如无连字符、大小写混合、非十六进制字符)会解析失败; 解析失败时返回全零的 SDL_GUID(所有 16 字节均为 0),可通过对比全零 GUID 判断解析是否成功; SDL_GUIDToString 输出的字符串为小写形式,输入字符串为大写时也可正常解析(大小写不敏感)。 典型使用场景: 标识游戏控制器/输入设备(SDL 中常用于区分不同的物理设备); 生成唯一的用户/设备 ID 用于数据存储/传输; 跨平台唯一标识资源(如配置文件、缓存数据)。 跨平台注意事项: SDL_GUID 结构体的二进制布局在所有平台一致,可安全序列化/反序列化; 字符串格式的 GUID 无平台差异,是跨平台传输的首选格式; 避免手动修改 SDL_GUID 的二进制数据,如需生成新 GUID,需使用平台原生的 GUID 生成函数(如 Windows 的 CoCreateGuid)。 总结 核心优势: 提供简单统一的 GUID 序列化/反序列化接口,无需手动处理二进制与字符串的转换; 严格遵循标准 UUID 格式,保证与其他系统/库的兼容性; 解析失败时返回可预测的全零 GUID,便于错误处理。 使用建议: 转换字符串时,务必使用 SDL_GUID_STRING_LENGTH(37)作为缓冲区大小,避免溢出; 解析字符串后,先对比全零 GUID 判断是否解析成功,再进行后续操作; 存储 GUID 时优先选择字符串格式(易读、易调试),传输/存储体积敏感时使用二进制格式。 关键点回顾: SDL_GUID 是 16 字节的结构体,用于存储 128 位的全局唯一标识符; SDL_GUIDToString/SDL_StringToGUID 实现 GUID 二进制与字符串的双向转换; 解析无效字符串时返回全零 GUID,可通过对比全零值判断解析结果; 字符串格式遵循标准 UUID 格式(36 字符 + 终止符),缓冲区需至少 37 字节。
      • 2026年-3月-7日
      • 1 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_标准工具函数(CategoryStdinc) 2026-3-7
      SDL3_API分类参考_标准工具函数(CategoryStdinc) 标准工具函数子系统(CategoryStdinc) SDL 提供了一套自研的核心 C 运行时函数实现,旨在解决跨平台开发中 C 标准库的兼容性问题: 解耦运行时依赖:应用可直接使用这些函数,无需依赖特定的 C 运行时库(甚至无需任何 C 运行时); 跨平台行为一致:避免不同平台的 C 函数表现差异(如 Windows/Linux 下 snprintf() 行为不同、itoa() 仅存在于部分平台); 性能与兼容性兼顾:对于 SDL_memcpy 等高频函数,SDL 会在底层调用平台原生实现(若其更高效且稳定),既减少库体积又保证性能; 扩展增强功能:补充了 C 标准未定义但实用的功能(如 SDL_crc32 校验、SDL_strlcpy 安全字符串拷贝)。 函数 1. 内存管理函数 SDL_malloc:内存分配(替代标准 malloc,跨平台行为一致) SDL_calloc:分配并清零内存(替代标准 calloc) SDL_realloc:内存重分配(替代标准 realloc) SDL_free:释放内存(替代标准 free,需与 SDL 分配函数配对使用) SDL_aligned_alloc:按指定对齐方式分配内存(如 16 字节对齐) SDL_aligned_free:释放对齐分配的内存 SDL_GetNumAllocations:获取当前 SDL 分配的内存块数量(调试内存泄漏) SDL_GetMemoryFunctions:获取当前使用的内存分配函数指针 SDL_SetMemoryFunctions:自定义 SDL 的内存分配函数(如接入自定义内存池) SDL_GetOriginalMemoryFunctions:获取 SDL 原生的内存函数指针 2. 字符串操作函数 SDL_strlen:计算字符串长度(替代 strlen,仅统计 ASCII 字符) SDL_utf8strlen:计算 UTF-8 字符串的字符数(而非字节数) SDL_strlcpy:安全字符串拷贝(防止缓冲区溢出,替代 strcpy) SDL_strlcat:安全字符串拼接(替代 strcat) SDL_strcmp/SDL_strncmp:字符串比较(区分大小写) SDL_strcasecmp/SDL_strncasecmp:字符串比较(不区分大小写) SDL_strchr/SDL_strrchr:查找字符在字符串中的位置 SDL_strstr/SDL_strnstr:查找子字符串 SDL_strdup/SDL_strndup:字符串拷贝(自动分配内存) SDL_strtok_r:可重入的字符串分割(替代 strtok,线程安全) SDL_itoa/SDL_ltoa/SDL_lltoa:整数转字符串(跨平台兼容,标准库无统一实现) SDL_uitoa/SDL_ultoa/SDL_ulltoa:无符号整数转字符串 SDL_atof/SDL_atoi:字符串转数值(替代 atof/atoi) SDL_strtod/SDL_strtol/SDL_strtoll:字符串转数值(带错误处理) SDL_strtoul/SDL_strtoull:字符串转无符号数值 SDL_asprintf/SDL_vasprintf:动态格式化字符串(自动分配内存) SDL_snprintf/SDL_vsnprintf:安全格式化字符串(防止缓冲区溢出) SDL_utf8strlcpy:UTF-8 安全字符串拷贝 3. 内存操作函数 SDL_memcpy:内存拷贝(替代 memcpy,平台优化实现) SDL_memmove:内存移动(处理重叠内存区域,替代 memmove) SDL_memset:内存填充(替代 memset) SDL_memset4:按 4 字节单位填充内存(更高效) SDL_memcmp:内存比较(替代 memcmp) 4. 数学函数 SDL_abs:整数绝对值(替代 abs) SDL_fabs/SDL_fabsf:浮点数绝对值(替代 fabs/fabsf) SDL_sin/SDL_sinf/SDL_cos/SDL_cosf:三角函数(正弦/余弦) SDL_atan/SDL_atanf/SDL_atan2/SDL_atan2f:反正切函数 SDL_acos/SDL_acosf/SDL_asin/SDL_asinf:反余弦/反正弦函数 SDL_tan/SDL_tanf:正切函数 SDL_sqrt/SDL_sqrtf:平方根函数 SDL_pow/SDL_powf:幂函数 SDL_exp/SDL_expf:指数函数 SDL_log/SDL_logf/SDL_log10/SDL_log10f:对数函数 SDL_floor/SDL_floorf:向下取整 SDL_ceil/SDL_ceilf:向上取整 SDL_round/SDL_roundf:四舍五入 SDL_trunc/SDL_truncf:截断小数部分 SDL_lround/SDL_lroundf:四舍五入转长整数 SDL_fmod/SDL_fmodf:取模运算(浮点数) SDL_copysign/SDL_copysignf:复制符号位 SDL_isinf/SDL_isinff:检测无穷大 SDL_isnan/SDL_isnanf:检测非数值(NaN) SDL_PI_F/SDL_PI_D:圆周率常量(单/双精度) 5. 字符判断函数 SDL_isalpha/SDL_isdigit/SDL_isalnum:字母/数字/字母数字判断 SDL_islower/SDL_isupper:大小写字母判断 SDL_isspace/SDL_isblank:空白字符判断 SDL_iscntrl/SDL_isprint/SDL_isgraph:控制字符/可打印字符/图形字符判断 SDL_ispunct:标点符号判断 SDL_isxdigit:十六进制字符判断 SDL_tolower/SDL_toupper:字符大小写转换 6. 排序/查找函数 SDL_qsort/SDL_qsort_r:快速排序(qsort_r 为可重入版本,线程安全) SDL_bsearch/SDL_bsearch_r:二分查找(bsearch_r 为可重入版本) 7. 哈希/校验函数 SDL_crc16/SDL_crc32:计算 CRC16/CRC32 校验值 SDL_murmur3_32:计算 Murmur3 32 位哈希值 8. 环境变量函数 SDL_getenv/SDL_getenv_unsafe:获取环境变量(_unsafe 版本不做安全检查) SDL_SetEnvironmentVariable/SDL_UnsetEnvironmentVariable:设置/删除环境变量 SDL_GetEnvironmentVariables:获取所有环境变量列表 SDL_CreateEnvironment/SDL_DestroyEnvironment:创建/销毁独立的环境变量上下文 9. 字符编码转换函数 SDL_iconv_open:打开字符编码转换上下文 SDL_iconv:执行编码转换 SDL_iconv_close:关闭转换上下文 SDL_iconv_string:字符串编码转换(简化接口) SDL_UCS4ToUTF8:UCS4 转 UTF-8 编码 SDL_StepUTF8/SDL_StepBackUTF8:UTF-8 字符串步进/回退(遍历字符) 10. 随机数函数 SDL_srand:设置随机数种子 SDL_rand:生成随机整数(替代 rand) SDL_randf:生成 0~1 浮点数随机数 SDL_rand_r/SDL_randf_r:可重入的随机数生成(线程安全) SDL_rand_bits:生成指定位数的随机数 11. 宽字符函数 SDL_wcslen/SDL_wcscmp/SDL_wcsncmp:宽字符串长度/比较 SDL_wcsstr/SDL_wcsnstr:宽字符串查找 SDL_wcslcpy/SDL_wcslcat:宽字符串安全拷贝/拼接 SDL_wcsdup:宽字符串拷贝(自动分配内存) SDL_wcstol:宽字符串转长整数 12. 格式化输入函数 SDL_sscanf/SDL_vsscanf:安全格式化输入(替代 sscanf) SDL_swprintf/SDL_vswprintf:宽字符串格式化输出 数据类型 SDL_malloc_func:内存分配函数指针类型(匹配 SDL_malloc 签名) SDL_calloc_func:内存分配并清零函数指针类型 SDL_realloc_func:内存重分配函数指针类型 SDL_free_func:内存释放函数指针类型 SDL_CompareCallback:排序/查找比较函数类型 SDL_CompareCallback_r:可重入的比较函数类型(带用户数据) SDL_Environment:环境变量上下文类型 SDL_iconv_t:字符编码转换上下文类型 SDL_FunctionPointer:通用函数指针类型 SDL_Time:时间类型(跨平台兼容) Sint8/Sint16/Sint32/Sint64:有符号整数类型(固定位宽) Uint8/Uint16/Uint32/Uint64:无符号整数类型(固定位宽) 结构体 (无) 枚举 (无) 宏 1. 类型转换宏 SDL_static_cast:静态类型转换(替代 C++ static_cast) SDL_reinterpret_cast:重解释类型转换(替代 C++ reinterpret_cast) SDL_const_cast:常量类型转换(替代 C++ const_cast) 2. 数学/工具宏 SDL_min/SDL_max:取最小值/最大值 SDL_clamp:将值限制在指定范围内(clamp(value, min, max)) SDL_arraysize:计算数组元素个数(编译期计算,安全) SDL_FLT_EPSILON:浮点数精度阈值(用于判断浮点数相等) SDL_SIZE_MAX:size_t 类型的最大值 3. 内存初始化宏 SDL_zero:将变量清零(SDL_zero(var)) SDL_zeroa:将数组清零(SDL_zeroa(array)) SDL_zerop:将指针指向的内存清零(SDL_zerop(ptr)) SDL_copyp:指针拷贝(SDL_copyp(dst, src)) SDL_stack_alloc:栈内存分配(临时内存,无需释放) SDL_stack_free:栈内存释放(配套 SDL_stack_alloc) 4. 编译期检查宏 SDL_COMPILE_TIME_ASSERT:编译期断言(失败则编译报错) 5. 格式化输出宏 SDL_PRIs32/SDL_PRIu32:32 位整数格式化占位符(跨平台兼容) SDL_PRIs64/SDL_PRIu64/SDL_PRIx64:64 位整数格式化占位符 SDL_PRINTF_FORMAT_STRING:标记格式化字符串参数(编译器检查) SDL_PRINTF_VARARG_FUNC:标记可变参数格式化函数 6. 编码转换宏 SDL_iconv_utf8_locale:UTF-8 转系统本地编码 SDL_iconv_utf8_ucs2/SDL_iconv_utf8_ucs4:UTF-8 转 UCS2/UCS4 SDL_iconv_wchar_utf8:宽字符转 UTF-8 7. 其他宏 SDL_FOURCC:生成四字符码(用于标识媒体格式等) SDL_SINT64_C/SDL_UINT64_C:64 位常量定义(跨平台兼容) SDL_INVALID_UNICODE_CODEPOINT:无效 Unicode 码点常量 FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充核心函数/宏声明(FreeBASIC 绑定可能缺失) #Define SDL_PI_F 3.14159265358979323846f #Define SDL_min(a, b) IIf((a) < (b), (a), (b)) #Define SDL_max(a, b) IIf((a) > (b), (a), (b)) #Define SDL_clamp(x, min_val, max_val) SDL_max(SDL_min((x), (max_val)), (min_val)) ' 函数声明补充 Declare Function SDL_utf8strlen CDecl (ByVal str As ZString Ptr) As Size_t Declare Function SDL_strlcpy CDecl (ByVal dst As ZString Ptr, ByVal src As ZString Ptr, ByVal size As Size_t) As Size_t Declare Function SDL_crc32 CDecl (ByVal crc As Uint32, ByVal data As Const Any Ptr, ByVal len As Size_t) As Uint32 Declare Sub SDL_zero CDecl (ByRef var As Any) Declare Function SDL_randf CDecl () As Float Declare Sub SDL_srand CDecl (ByVal seed As Uint32) ' ==================== 示例 1:安全字符串操作 ==================== Sub StringOperationsExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【安全字符串操作示例】") ' 1. SDL_strlcpy 安全拷贝(防止缓冲区溢出) Dim As ZString * 10 dstBuffer Dim As ZString Ptr src = StrPtr("Hello SDL!") ' 拷贝最多 9 个字符 + 终止符,返回原字符串长度 Dim As Size_t len = SDL_strlcpy(@dstBuffer, src, sizeof(dstBuffer)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "原字符串:%s,长度:%d", src, len) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "拷贝结果:%s(缓冲区大小:%d)", dstBuffer, sizeof(dstBuffer)) ' 2. UTF-8 字符串长度计算 Dim As ZString Ptr utf8Str = StrPtr("SDL 中文示例") Dim As Size_t byteLen = SDL_strlen(utf8Str) ' 字节数 Dim As Size_t charLen = SDL_utf8strlen(utf8Str) ' 字符数 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "UTF-8 字符串:%s", utf8Str) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "字节长度:%d,字符长度:%d", byteLen, charLen) ' 3. 整数转字符串(跨平台兼容) Dim As ZString * 32 numStr SDL_itoa(-12345, @numStr, 10) ' 十进制 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "整数转字符串:%s", numStr) SDL_uitoa(65535, @numStr, 16) ' 十六进制 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "无符号整数转十六进制:%s", numStr) End Sub ' ==================== 示例 2:内存操作与校验 ==================== Sub MemoryOperationsExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【内存操作与校验示例】") ' 1. 内存分配与初始化 Dim As Integer Ptr arr = SDL_calloc(5, sizeof(Integer)) If (arr = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "内存分配失败") Exit Sub End If ' 填充数据 For i As Integer = 0 To 4 arr[i] = i * 10 Next ' 2. 内存拷贝 Dim As Integer Ptr arrCopy = SDL_malloc(5 * sizeof(Integer)) SDL_memcpy(arrCopy, arr, 5 * sizeof(Integer)) ' 打印拷贝结果 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "内存拷贝结果:") For i As Integer = 0 To 4 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " arrCopy[%d] = %d", i, arrCopy[i]) Next ' 3. CRC32 校验 Dim As Uint32 crc = SDL_crc32(0, arr, 5 * sizeof(Integer)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "数据 CRC32 校验值:0x%08X", crc) ' 4. 内存释放 SDL_free(arr) SDL_free(arrCopy) ' 5. 内存清零 Type TestStruct a As Integer b As Float c As ZString * 20 End Type Dim As TestStruct ts SDL_zero(ts) ' 清零整个结构体 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "结构体清零后:a=%d, b=%.2f", ts.a, ts.b) End Sub ' ==================== 示例 3:数学与随机数 ==================== Sub MathAndRandomExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【数学与随机数示例】") ' 1. 数学函数 Dim As Float angle = SDL_PI_F / 4 ' 45 度 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "sin(45°) = %.4f", SDL_sinf(angle)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "cos(45°) = %.4f", SDL_cosf(angle)) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "sqrt(2) = %.4f", SDL_sqrtf(2.0f)) ' 2. 数值限制(clamp) Dim As Integer val = 150 Dim As Integer clamped = SDL_clamp(val, 0, 100) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "clamp(150, 0, 100) = %d", clamped) ' 3. 随机数 SDL_srand(SDL_GetTicks()) ' 以时间为种子 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "随机整数:%d", SDL_rand() Mod 100) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "随机浮点数(0~1):%.4f", SDL_randf()) End Sub ' ==================== 示例 4:环境变量操作 ==================== Sub EnvVarExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【环境变量操作示例】") ' 1. 设置环境变量 SDL_SetEnvironmentVariable(StrPtr("SDL_TEST_VAR"), StrPtr("Hello SDL Env")) ' 2. 获取环境变量 Dim As ZString Ptr envVal = SDL_getenv(StrPtr("SDL_TEST_VAR")) If (envVal <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "获取环境变量 SDL_TEST_VAR:%s", envVal) End If ' 3. 删除环境变量 SDL_UnsetEnvironmentVariable(StrPtr("SDL_TEST_VAR")) envVal = SDL_getenv(StrPtr("SDL_TEST_VAR")) If (envVal = NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "环境变量 SDL_TEST_VAR 已删除") End If End Sub ' ==================== 主程序 ==================== Sub Main() ' 初始化 SDL(Stdinc 子系统无需特定初始化) If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 StringOperationsExample() MemoryOperationsExample() MathAndRandomExample() EnvVarExample() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 核心设计理念: SDL_stdinc 的核心目标是「跨平台一致性」,而非「替代标准库」; 对于底层实现稳定的函数(如 memcpy),SDL 会直接调用平台原生版本,保证性能; 对于行为不一致/缺失的函数(如 itoa/snprintf),SDL 提供自研实现,保证跨平台表现相同。 内存管理最佳实践: SDL 内存函数(SDL_malloc/SDL_free 等)必须配对使用,不可混用标准库 free; SDL_calloc 会自动清零内存,优先用于需要初始化的场景; SDL_GetNumAllocations 可用于调试内存泄漏(记录分配/释放的数量差); 自定义内存函数需在 SDL 初始化前通过 SDL_SetMemoryFunctions 设置。 字符串安全要点: 优先使用 SDL_strlcpy/SDL_strlcat 替代 strcpy/strcat,避免缓冲区溢出; SDL_utf8strlen 是 UTF-8 字符串的「字符数」统计,SDL_strlen 是「字节数」统计; SDL_asprintf 会自动分配内存,使用后必须调用 SDL_free 释放。 跨平台兼容注意: 64 位整数格式化需使用 SDL_PRId64/SDL_PRIu64 等宏,避免 %lld/%llu 的平台差异; 整数类型优先使用 Sint32/Uint32 等固定位宽类型,而非 int/long; 随机数函数 SDL_rand 比标准 rand 更稳定,且 SDL_rand_r 保证线程安全。 总结 核心优势: 解耦 C 运行时依赖,降低跨平台编译复杂度; 统一函数行为,避免不同平台的标准库实现差异; 补充安全/增强功能(如 SDL_strlcpy/SDL_crc32),提升代码健壮性; 底层优化实现,兼顾性能与兼容性。 使用建议: 新项目优先使用 SDL_stdinc 函数替代标准库函数,减少跨平台问题; 内存分配/释放必须使用 SDL 配套函数(SDL_malloc ↔ SDL_free); UTF-8 字符串操作使用 SDL_utf8* 系列函数,避免多字节字符处理错误; 编译期使用 SDL_COMPILE_TIME_ASSERT 检查类型大小、常量等,提前发现问题。 关键点回顾: SDL_stdinc 是 SDL 的基础工具集,提供跨平台一致的 C 运行时函数; SDL_strlcpy/SDL_snprintf 等函数解决了标准库字符串操作的安全问题; 内存函数、数学函数、随机数函数均做了跨平台兼容和性能优化; 固定位宽类型(Sint32/Uint64)和格式化宏(SDL_PRIs64)是跨平台开发的关键。
      • 2026年-3月-7日
      • 1 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_系统适配(CategorySystem) 2026-3-7
      SDL3_API分类参考_系统适配(CategorySystem) 系统适配子系统(CategorySystem) SDL 提供的平台专属 API 集合,这类函数用于处理特定操作系统的个性化需求——由于其功能高度依赖平台特性,无法抽象为跨平台通用接口。 大多数应用无需使用这些函数即可正常运行,但在以下场景中能发挥关键作用: 与特定系统的其他组件集成(如 Android 的 JNI、Windows 的消息钩子); 为应用添加平台专属的体验优化(如 iOS 动画回调、Android 吐司提示); 解决仅影响单一目标平台的问题(如 Linux 线程优先级、X11 事件钩子)。 函数 Android 平台专属 SDL_GetAndroidActivity:获取 Android 应用的 Activity 实例指针(JNI 交互核心) SDL_GetAndroidCachePath:获取 Android 应用的缓存目录路径(应用卸载后会被清除) SDL_GetAndroidExternalStoragePath:获取 Android 外部存储(SD 卡)根路径 SDL_GetAndroidExternalStorageState:获取外部存储状态(如是否挂载、可读写) SDL_GetAndroidInternalStoragePath:获取 Android 内部存储(应用私有目录)路径 SDL_GetAndroidJNIEnv:获取 Android 应用的 JNIEnv 环境指针(用于调用 Java 方法) SDL_GetAndroidSDKVersion:获取设备的 Android SDK 版本号(如 30 对应 Android 11) SDL_RequestAndroidPermission:向 Android 系统申请权限(如存储、相机),异步返回结果 SDL_SendAndroidBackButton:模拟 Android 物理返回键事件(触发应用返回逻辑) SDL_SendAndroidMessage:向 Android 原生层发送自定义消息(JNI 通信) SDL_ShowAndroidToast:显示 Android 原生吐司提示(短/长时间悬浮提示) Windows 平台专属 SDL_GetDirect3D9AdapterIndex:获取 Direct3D 9 显卡适配器索引(适配多显卡) SDL_GetDXGIOutputInfo:获取 DXGI 输出设备信息(用于多显示器适配) SDLSetWindowsMessageHook:设置 Windows 消息钩子(拦截/处理系统消息如 WM*) Linux 平台专属 SDL_SetLinuxThreadPriority:设置 Linux 线程优先级(调整调度优先级) SDL_SetLinuxThreadPriorityAndPolicy:设置 Linux 线程优先级及调度策略(如 SCHED_FIFO) SDL_SetX11EventHook:设置 X11 事件钩子(拦截/处理 X11 窗口系统事件) iOS 平台专属 SDL_SetiOSAnimationCallback:设置 iOS 动画回调(同步应用动画与系统刷新率) SDL_SetiOSEventPump:设置 iOS 事件泵(自定义事件处理逻辑) SDL_OnApplicationDidChangeStatusBarOrientation:iOS 状态栏方向变更回调 SDL_OnApplicationDidEnterBackground:iOS 应用进入后台回调 SDL_OnApplicationDidEnterForeground:iOS 应用进入前台回调 SDL_OnApplicationDidReceiveMemoryWarning:iOS 内存警告回调 SDL_OnApplicationWillEnterBackground:iOS 应用即将进入后台回调 SDL_OnApplicationWillEnterForeground:iOS 应用即将进入前台回调 SDL_OnApplicationWillTerminate:iOS 应用即将终止回调 游戏主机/特殊平台 SDL_GetGDKDefaultUser:获取 GDK(Xbox 开发工具包)默认用户实例 SDL_GetGDKTaskQueue:获取 GDK 任务队列(异步任务调度) 跨平台检测类 SDL_GetSandbox:获取应用的沙箱模式状态(判断是否运行在受限环境) SDL_IsChromebook:检测设备是否为 Chromebook(ChromeOS 设备) SDL_IsDeXMode:检测三星设备是否处于 DeX 模式(桌面化模式) SDL_IsTablet:检测设备是否为平板(区分手机/平板) SDL_IsTV:检测设备是否为智能电视(如 Android TV、Tizen TV) 数据类型 SDL_iOSAnimationCallback:iOS 动画回调函数类型(同步应用动画帧) SDL_RequestAndroidPermissionCallback:Android 权限申请结果回调类型(返回权限是否授予) SDL_WindowsMessageHook:Windows 消息钩子函数类型(处理系统消息) SDL_X11EventHook:X11 事件钩子函数类型(处理 X11 窗口事件) 结构体 (无) 枚举 SDL_Sandbox:沙箱模式枚举,标识应用运行的沙箱环境类型: SDL_SANDBOX_UNKNOWN:未知沙箱状态 SDL_SANDBOX_NONE:无沙箱限制(普通桌面应用) SDL_SANDBOX_APPLE:Apple 沙箱(macOS/iOS 应用) SDL_SANDBOX_ANDROID:Android 沙箱(应用私有目录限制) SDL_SANDBOX_LINUX:Linux 沙箱(如 Flatpak/Snap 容器) 宏 SDL_ANDROID_EXTERNAL_STORAGE_READ:Android 外部存储读权限标志 SDL_ANDROID_EXTERNAL_STORAGE_WRITE:Android 外部存储写权限标志 FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充平台专属类型/函数声明(FreeBASIC 绑定可能缺失) ' ==================== Android 平台声明 ==================== #If Defined(SDL_PLATFORM_ANDROID) ' Android 权限申请回调类型 Type SDL_RequestAndroidPermissionCallback As Sub( _ ByVal permission As ZString Ptr, _ ByVal granted As SDL_bool, _ ByVal userdata As Any Ptr _ ) ' Android 函数声明 Declare Function SDL_GetAndroidCachePath CDecl () As ZString Ptr Declare Function SDL_GetAndroidExternalStoragePath CDecl () As ZString Ptr Declare Function SDL_GetAndroidInternalStoragePath CDecl () As ZString Ptr Declare Function SDL_GetAndroidSDKVersion CDecl () As Integer Declare Sub SDL_ShowAndroidToast CDecl (ByVal text As ZString Ptr, ByVal duration As Integer) Declare Function SDL_RequestAndroidPermission CDecl ( _ ByVal permission As ZString Ptr, _ ByVal callback As SDL_RequestAndroidPermissionCallback, _ ByVal userdata As Any Ptr _ ) As SDL_bool ' Android Toast 时长常量 Const SDL_ANDROID_TOAST_SHORT = 0 Const SDL_ANDROID_TOAST_LONG = 1 ' Android 权限常量 Const SDL_ANDROID_PERMISSION_WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE" #EndIf ' ==================== Windows 平台声明 ==================== #If Defined(SDL_PLATFORM_WINDOWS) ' Windows 消息钩子类型 Type SDL_WindowsMessageHook As Function( _ ByVal hwnd As HWND, _ ByVal msg As Uint32, _ ByVal wparam As WPARAM, _ ByVal lparam As LPARAM, _ ByVal userdata As Any Ptr, _ ByRef retval As LRESULT _ ) As SDL_bool ' Windows 函数声明 Declare Sub SDL_SetWindowsMessageHook CDecl ( _ ByVal hook As SDL_WindowsMessageHook, _ ByVal userdata As Any Ptr _ ) #EndIf ' ==================== Linux 平台声明 ==================== #If Defined(SDL_PLATFORM_LINUX) ' Linux 线程优先级函数声明 Declare Function SDL_SetLinuxThreadPriority CDecl ( _ ByVal thread As SDL_ThreadID, _ ByVal priority As Integer _ ) As SDL_bool #EndIf ' ==================== 跨平台检测函数 ==================== Declare Function SDL_GetSandbox CDecl () As Integer Declare Function SDL_IsTablet CDecl () As SDL_bool Declare Function SDL_IsTV CDecl () As SDL_bool ' ==================== 示例函数 ==================== ' Android 示例:获取存储路径并显示 Toast Sub AndroidStorageExample() #If Defined(SDL_PLATFORM_ANDROID) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【Android 存储路径示例】") ' 获取各类存储路径 Dim As ZString Ptr cachePath = SDL_GetAndroidCachePath() Dim As ZString Ptr externalPath = SDL_GetAndroidExternalStoragePath() Dim As ZString Ptr internalPath = SDL_GetAndroidInternalStoragePath() If (cachePath <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "缓存目录:%s", cachePath) End If If (externalPath <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "外部存储目录:%s", externalPath) End If If (internalPath <> NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "内部存储目录:%s", internalPath) End If ' 获取 SDK 版本 Dim As Integer sdkVersion = SDL_GetAndroidSDKVersion() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Android SDK 版本:%d", sdkVersion) ' 显示 Toast 提示 SDL_ShowAndroidToast(StrPtr("存储路径获取成功!"), SDL_ANDROID_TOAST_SHORT) #Else SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "非 Android 平台,跳过存储路径示例") #EndIf End Sub ' Android 示例:申请存储权限 Sub AndroidPermissionExample() #If Defined(SDL_PLATFORM_ANDROID) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【Android 权限申请示例】") ' 权限申请回调函数 Sub PermissionCallback( _ ByVal permission As ZString Ptr, _ ByVal granted As SDL_bool, _ ByVal userdata As Any Ptr _ ) If (granted = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "权限 %s 申请成功", permission) SDL_ShowAndroidToast(StrPtr("存储权限已授予!"), SDL_ANDROID_TOAST_SHORT) Else SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "权限 %s 申请失败", permission) SDL_ShowAndroidToast(StrPtr("存储权限申请失败!"), SDL_ANDROID_TOAST_SHORT) End If End Sub ' 申请外部存储写权限 Dim As SDL_bool result = SDL_RequestAndroidPermission( _ StrPtr(SDL_ANDROID_PERMISSION_WRITE_EXTERNAL_STORAGE), _ @PermissionCallback, _ NULL _ ) If (result = SDL_FALSE) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "申请权限失败:%s", SDL_GetError()) End If #Else SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "非 Android 平台,跳过权限申请示例") #EndIf End Sub ' 跨平台示例:设备类型检测 Sub DeviceDetectionExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【跨平台设备检测示例】") ' 检测沙箱模式 Dim As Integer sandbox = SDL_GetSandbox() Select Case sandbox Case 0: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "沙箱状态:未知") Case 1: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "沙箱状态:无限制") Case 2: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "沙箱状态:Apple 沙箱") Case 3: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "沙箱状态:Android 沙箱") Case 4: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "沙箱状态:Linux 沙箱") End Select ' 检测设备类型 If (SDL_IsTablet() = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "设备类型:平板") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "设备类型:非平板(手机/桌面)") End If If (SDL_IsTV() = SDL_TRUE) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "设备类型:智能电视") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "设备类型:非智能电视") End If End Sub ' ==================== 主程序 ==================== Sub Main() ' 初始化 SDL If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 DeviceDetectionExample() AndroidStorageExample() AndroidPermissionExample() ' 保持应用运行(Android 需等待权限回调) #If Defined(SDL_PLATFORM_ANDROID) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "等待权限申请结果...") Dim As Integer waitCount = 0 While (waitCount < 10) SDL_Delay(1000) waitCount += 1 Wend #EndIf ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 平台专属函数使用原则: 必须通过 #If Defined(SDL_PLATFORM_XXX) 做条件编译,避免跨平台编译错误; 非目标平台调用这些函数会返回默认值(如 NULL/SDL_FALSE),需做好容错; 优先使用跨平台 API,仅在必要时使用平台专属函数(降低维护成本)。 Android 平台关键注意事项: Android 10+ 需申请 MANAGE_EXTERNAL_STORAGE 权限才能访问公共目录,传统存储权限已失效; SDL_ShowAndroidToast 需在主线程调用,子线程调用可能无响应; 存储路径返回的字符串由 SDL 管理,无需手动释放,但不可修改。 Windows/Linux 平台关键注意事项: Windows 消息钩子需在主线程设置,且需在退出前移除(避免崩溃); Linux 线程优先级设置需要 root 权限,普通用户调用可能失败; X11 事件钩子仅在 X11 窗口系统下生效,Wayland 环境需适配其他接口。 沙箱模式影响: 沙箱类型 核心限制 适配建议 Apple 沙箱 无法访问外部文件、网络需配置权限 使用应用沙箱内目录存储数据 Android 沙箱 仅可访问应用私有目录、公共目录需权限 优先使用内部存储,避免依赖外部存储 Linux 沙箱 权限受限、文件系统隔离 适配 Flatpak/Snap 的目录结构 总结 核心优势: 提供一站式平台专属能力,无需直接调用原生 API(如 Android JNI、Windows Win32); 封装了平台特有的复杂逻辑(如权限申请、消息钩子),降低开发难度; 保持接口风格统一,跨平台代码只需少量条件编译即可适配。 使用建议: 平台专属函数仅在「跨平台 API 无法满足需求」时使用; 调用前必须做平台检测,避免非目标平台编译/运行错误; Android/iOS 等移动平台函数需注意主线程/子线程调用限制; 权限相关函数需处理用户拒绝的情况,保证应用容错性。 关键点回顾: CategorySystem 是 SDL 的平台专属函数集合,无跨平台通用逻辑; 调用平台专属函数前需通过 SDL_PLATFORM_XXX 宏做条件编译; Android 权限申请、Windows 消息钩子、Linux 线程优先级是该模块的高频使用场景; 沙箱模式检测可帮助应用适配不同平台的权限限制,避免运行时错误。
      • 2026年-3月-7日
      • 1 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_区域设置(CategoryLocale) 2026-3-7
      SDL3_API分类参考_区域设置(CategoryLocale) 区域设置子系统(CategoryLocale) SDL 提供了轻量的区域设置服务,核心能力是获取用户的首选区域列表(由「语言 + 国家/地区」组成)。该子系统仅包含一个核心函数:SDL_GetPreferredLocales(),它会自动处理不同系统、不同配置方式下的语言设置解析,兼容各类复杂的用户语言配置场景(如多语言优先级、地区变体等)。 这一功能是实现应用多语言适配的基础——通过获取用户的首选语言,应用可自动切换界面文本、音频、字体等资源,提升本地化体验。 函数 SDL_GetPreferredLocales:获取用户的首选区域设置列表,返回 SDL_Locale 结构体数组(数组末尾以 NULL 结尾);函数内部自动分配内存,调用者需通过 SDL_free() 释放整个数组 数据类型 (无) 结构体 SDL_Locale:区域设置结构体,包含两个核心字段: language:语言代码(符合 ISO 639 标准,如 "zh" 表示中文、"en" 表示英文、"ja" 表示日文) country:国家/地区代码(符合 ISO 3166 标准,如 "CN" 表示中国、"US" 表示美国、"TW" 表示中国台湾);若未指定地区,该字段为 NULL 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充结构体和函数声明(FreeBASIC 绑定可能缺失) Type SDL_Locale language As ZString Ptr ' 语言代码(如 "zh"、"en") country As ZString Ptr ' 国家/地区代码(如 "CN"、"US",NULL 表示未指定) End Type Declare Function SDL_GetPreferredLocales CDecl () As SDL_Locale Ptr Declare Sub SDL_free CDecl (ByVal ptr As Any Ptr) ' 打印区域设置信息 Sub PrintLocaleInfo(ByVal locale As SDL_Locale Ptr) If (locale = NULL) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " - 无区域信息") Exit Sub End If ' 拼接语言+地区字符串(如 "zh-CN"、"en-US") Dim As ZString * 32 localeStr If (locale->country <> NULL) Then snprintf(@localeStr, sizeof(localeStr), "%s-%s", *locale->language, *locale->country) Else snprintf(@localeStr, sizeof(localeStr), "%s", *locale->language) End If SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " - %s", localeStr) ' 补充语言/地区说明 If (strcmp(locale->language, "zh") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 语言:中文") If (locale->country <> NULL) Then If (strcmp(locale->country, "CN") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:中国大陆") ElseIf (strcmp(locale->country, "TW") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:中国台湾") ElseIf (strcmp(locale->country, "HK") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:中国香港") End If End If ElseIf (strcmp(locale->language, "en") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 语言:英文") If (locale->country <> NULL And strcmp(locale->country, "US") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:美国") ElseIf (locale->country <> NULL And strcmp(locale->country, "GB") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 地区:英国") End If ElseIf (strcmp(locale->language, "ja") = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 语言:日文") End If End Sub ' 获取并解析用户首选区域列表 Sub GetPreferredLocalesExample() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【获取用户首选区域设置】") ' 1. 获取首选区域列表(SDL 自动分配内存) Dim As SDL_Locale Ptr locales = SDL_GetPreferredLocales() If (locales = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "获取区域设置失败:%s", SDL_GetError()) Exit Sub End If ' 2. 遍历并打印所有区域设置(数组以 NULL 结尾) Dim As Integer i = 0 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户首选区域列表(按优先级排序):") While (locales[i].language <> NULL) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "第 %d 项:", i + 1) PrintLocaleInfo(@locales[i]) i += 1 Wend If (i = 0) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "未获取到任何区域设置") End If ' 3. 释放 SDL 分配的内存(必须调用,避免内存泄漏) SDL_free(locales) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "区域设置内存已释放") End Sub ' 根据区域设置选择应用语言 Sub SelectAppLanguage() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【根据区域设置选择应用语言】") Dim As SDL_Locale Ptr locales = SDL_GetPreferredLocales() If (locales = NULL) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "使用默认语言:英文") Exit Sub End If ' 遍历首选区域列表,匹配支持的语言 Dim As ZString Ptr appLang = StrPtr("en") ' 默认语言:英文 Dim As Integer i = 0 While (locales[i].language <> NULL) ' 检查是否支持该语言 If (strcmp(locales[i].language, "zh") = 0) Then appLang = StrPtr("zh") ' 进一步区分简繁(根据地区) If (locales[i].country <> NULL) Then If (strcmp(locales[i].country, "TW") = 0 Or strcmp(locales[i].country, "HK") = 0) Then appLang = StrPtr("zh-TW") ' 繁体中文 Else appLang = StrPtr("zh-CN") ' 简体中文 End If End If Exit While ' 匹配到首选语言,停止遍历 ElseIf (strcmp(locales[i].language, "ja") = 0) Then appLang = StrPtr("ja") ' 日文 Exit While End If i += 1 Wend ' 输出选择结果 Select Case *appLang Case "zh-CN": SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:简体中文") Case "zh-TW": SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:繁体中文") Case "ja": SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:日文") Case Else: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用语言切换为:英文(默认)") End Select ' 释放内存 SDL_free(locales) End Sub ' 主程序 Sub Main() ' 初始化 SDL(Locale 子系统无需特定子系统,基础初始化即可) If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 GetPreferredLocalesExample() SelectAppLanguage() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 区域代码规范: 语言代码遵循 ISO 639-1(两位小写,如 zh=中文、en=英文、fr=法语); 地区代码遵循 ISO 3166-1 alpha-2(两位大写,如 CN=中国、US=美国、JP=日本); 组合格式为 语言-地区(如 zh-CN=简体中文(中国大陆)、en-US=美式英语、zh-TW=繁体中文(中国台湾))。 平台实现逻辑: 平台 获取语言设置的原生方式 SDL 封装优势 Windows GetUserPreferredUILanguages 自动处理多语言优先级、兼容旧系统版本 macOS CFLocaleCopyPreferredLanguages 统一返回格式,无需处理 CoreFoundation 类型 Linux 读取 LANG/LC_* 环境变量 解析复杂的 locale 字符串(如 zh_CN.UTF-8) 移动平台 Android: getResources().getConfiguration()iOS: NSLocale 跨平台统一返回 SDL_Locale 结构体 内存管理注意: SDL_GetPreferredLocales() 返回的数组由 SDL 分配内存,必须调用 SDL_free() 释放,否则会导致内存泄漏; 数组内的 language/country 字符串是数组内存的一部分,无需单独释放; 数组以 language = NULL 的元素结尾,遍历需以此为终止条件。 常见区域设置示例: 区域字符串 含义 应用适配建议 zh-CN 简体中文(中国大陆) 使用简体中文字体、简体文本资源 zh-TW 繁体中文(中国台湾) 使用繁体中文字体、繁体文本资源 en-US 美式英语 使用美式拼写(如 color/center) en-GB 英式英语 使用英式拼写(如 colour/centre) ja-JP 日文(日本) 使用日文字体、日文文本资源 总结 核心优势: 跨平台统一的区域设置获取接口,无需适配不同系统的原生语言 API; 自动解析复杂的系统语言配置,返回标准化的「语言+地区」格式; 轻量易用,仅一个核心函数即可完成所有逻辑,降低本地化开发成本。 使用建议: 应用启动时调用 SDL_GetPreferredLocales(),优先匹配用户首选语言; 按优先级遍历区域列表,匹配到支持的语言后立即停止(无需遍历全部); 必须调用 SDL_free() 释放返回的数组,避免内存泄漏; 对未匹配到的语言,默认使用英文(或应用核心语言)保证可用性。 关键点回顾: SDL_GetPreferredLocales() 是区域设置子系统的唯一核心函数,返回按优先级排序的 SDL_Locale 数组; SDL_Locale 包含 language(语言代码)和 country(地区代码)两个字段,地区代码可能为 NULL; 返回的数组必须通过 SDL_free() 释放,这是避免内存泄漏的关键; 区域设置是应用本地化的基础,需结合文本资源、字体、格式适配等功能使用。
      • 2026年-3月-7日
      • 1 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_系统托盘(CategoryTray) 2026-3-7
      SDL3_API分类参考_系统托盘(CategoryTray) 系统托盘子系统(CategoryTray) SDL 提供了系统托盘(Windows 中更准确的称呼是「通知区域」)操作接口,在支持该功能的平台上(Windows/macOS/Linux 主流桌面环境),SDL 应用可创建托盘图标、添加子菜单、复选框、可点击菜单项,并注册回调函数响应用户的点击操作。 系统托盘功能让应用在后台运行时仍能与用户交互,是桌面应用的常用特性(如后台服务、工具类软件)。 函数 SDL_CreateTray:创建基础系统托盘实例,返回 SDL_Tray 句柄(失败返回 NULL,需初始化视频子系统) SDL_CreateTrayWithProperties:创建带自定义属性的托盘实例(支持图标、提示文本等初始配置) SDL_DestroyTray:销毁托盘实例,移除系统托盘中的图标和菜单,释放所有关联资源 SDL_SetTrayIcon:设置托盘图标(传入 SDL_Surface 或 SDL_Texture 类型的图标资源) SDL_SetTrayTooltip:设置托盘图标的悬浮提示文本(鼠标悬停时显示) SDL_CreateTrayMenu:创建托盘菜单容器,用于存放菜单项 SDL_CreateTraySubmenu:创建子菜单(嵌套在主菜单中的二级菜单) SDL_InsertTrayEntryAt:在指定位置插入托盘菜单项(支持普通项、复选框、分隔符等) SDL_RemoveTrayEntry:移除指定的托盘菜单项 SDL_SetTrayEntryLabel:设置菜单项的显示文本 SDL_SetTrayEntryChecked:设置复选框类型菜单项的选中状态 SDL_GetTrayEntryChecked:获取复选框菜单项的选中状态 SDL_SetTrayEntryEnabled:设置菜单项是否可用(禁用时灰显,无法点击) SDL_GetTrayEntryEnabled:获取菜单项的启用状态 SDL_GetTrayEntryLabel:获取菜单项的显示文本 SDL_SetTrayEntryCallback:为菜单项注册点击回调函数 SDL_ClickTrayEntry:手动触发菜单项的点击事件(模拟用户操作) SDL_GetTrayEntries:获取指定菜单下的所有菜单项列表 SDL_GetTrayEntryParent:获取菜单项所属的父菜单/父托盘 SDL_GetTrayMenu:获取托盘实例关联的主菜单 SDL_GetTraySubmenu:获取菜单项关联的子菜单(若有) SDL_GetTrayMenuParentEntry:获取子菜单所属的父菜单项 SDL_GetTrayMenuParentTray:获取菜单所属的父托盘实例 SDL_UpdateTrays:更新所有托盘实例的显示(修改菜单/图标后需调用) 数据类型 SDL_Tray:系统托盘实例句柄类型,封装平台相关的托盘资源(如 Windows 的 NOTIFYICONDATA) SDL_TrayMenu:托盘菜单容器类型,管理多个菜单项的集合 SDL_TrayEntry:托盘菜单项类型,代表单个可点击/可选的菜单元素(普通项、复选框、子菜单、分隔符) SDL_TrayEntryFlags:菜单项标志类型,标识菜单项类型(普通项、复选框、分隔符、子菜单等) SDL_TrayCallback:菜单项通用回调函数类型,响应菜单项的状态变更 SDL_TrayClickCallback:菜单项点击回调函数类型,用户点击菜单项时触发 结构体 (无) 枚举 (无) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充类型/函数声明(FreeBASIC 绑定可能缺失) Type SDL_Tray As Any Ptr Type SDL_TrayMenu As Any Ptr Type SDL_TrayEntry As Any Ptr Type SDL_TrayEntryFlags As Uint32 ' 菜单项类型标志(示例值,实际 SDL 定义以官方为准) Const SDL_TRAYENTRY_NORMAL = 0 ' 普通菜单项 Const SDL_TRAYENTRY_CHECKBOX = 1 Shl 0 ' 复选框菜单项 Const SDL_TRAYENTRY_SEPARATOR = 1 Shl 1 ' 分隔符 Const SDL_TRAYENTRY_SUBMENU = 1 Shl 2 ' 子菜单入口 ' 回调函数类型定义 Type SDL_TrayClickCallback As Sub( _ ByVal entry As SDL_TrayEntry, _ ByVal userdata As Any Ptr _ ) ' 核心函数声明 Declare Function SDL_CreateTray CDecl () As SDL_Tray Declare Sub SDL_DestroyTray CDecl (ByVal tray As SDL_Tray) Declare Function SDL_SetTrayIcon CDecl (ByVal tray As SDL_Tray, ByVal icon As SDL_Surface Ptr) As SDL_bool Declare Function SDL_SetTrayTooltip CDecl (ByVal tray As SDL_Tray, ByVal tooltip As ZString Ptr) As SDL_bool Declare Function SDL_CreateTrayMenu CDecl () As SDL_TrayMenu Declare Function SDL_InsertTrayEntryAt CDecl ( _ ByVal menu As SDL_TrayMenu, _ ByVal index As Integer, _ ByVal flags As SDL_TrayEntryFlags, _ ByVal label As ZString Ptr, _ ByVal userdata As Any Ptr _ ) As SDL_TrayEntry Declare Function SDL_CreateTraySubmenu CDecl (ByVal entry As SDL_TrayEntry) As SDL_TrayMenu Declare Sub SDL_SetTrayEntryCallback CDecl (ByVal entry As SDL_TrayEntry, ByVal callback As SDL_TrayClickCallback) Declare Sub SDL_SetTrayEntryChecked CDecl (ByVal entry As SDL_TrayEntry, ByVal checked As SDL_bool) Declare Function SDL_GetTrayEntryChecked CDecl (ByVal entry As SDL_TrayEntry) As SDL_bool Declare Sub SDL_SetTrayEntryEnabled CDecl (ByVal entry As SDL_TrayEntry, ByVal enabled As SDL_bool) Declare Function SDL_GetTrayMenu CDecl (ByVal tray As SDL_Tray) As SDL_TrayMenu Declare Sub SDL_SetTrayMenu CDecl (ByVal tray As SDL_Tray, ByVal menu As SDL_TrayMenu) Declare Sub SDL_UpdateTrays CDecl () ' 全局托盘实例 Dim Shared As SDL_Tray g_tray = NULL ' 全局退出标志 Dim Shared As SDL_bool g_quit = SDL_FALSE ' 菜单项点击回调:显示主窗口 Sub ShowWindowCallback(ByVal entry As SDL_TrayEntry, ByVal userdata As Any Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【托盘回调】用户点击了「显示窗口」") ' 模拟显示主窗口逻辑 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "→ 显示应用主窗口") End Sub ' 菜单项点击回调:切换静音状态 Sub ToggleMuteCallback(ByVal entry As SDL_TrayEntry, ByVal userdata As Any Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【托盘回调】用户点击了「静音模式」") ' 切换复选框状态 Dim As SDL_bool checked = SDL_GetTrayEntryChecked(entry) SDL_SetTrayEntryChecked(entry, Not checked) ' 刷新托盘显示 SDL_UpdateTrays() ' 模拟静音逻辑 If (Not checked) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "→ 开启静音模式") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "→ 关闭静音模式") End If End Sub ' 菜单项点击回调:退出应用 Sub ExitAppCallback(ByVal entry As SDL_TrayEntry, ByVal userdata As Any Ptr) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【托盘回调】用户点击了「退出」") g_quit = SDL_TRUE End Sub ' 创建系统托盘及菜单 Function CreateSystemTray() As SDL_bool ' 1. 创建托盘实例 g_tray = SDL_CreateTray() If (g_tray = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建托盘失败:%s", SDL_GetError()) Return SDL_FALSE End If ' 2. 设置托盘提示文本(鼠标悬浮显示) If (SDL_SetTrayTooltip(g_tray, StrPtr("SDL 托盘示例")) = SDL_FALSE) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "设置托盘提示失败:%s", SDL_GetError()) End If ' 3. 创建托盘主菜单 Dim As SDL_TrayMenu Ptr mainMenu = SDL_CreateTrayMenu() If (mainMenu = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建主菜单失败:%s", SDL_GetError()) SDL_DestroyTray(g_tray) Return SDL_FALSE End If ' 4. 添加菜单项:显示窗口(普通项) Dim As SDL_TrayEntry Ptr showWindowEntry = SDL_InsertTrayEntryAt( _ mainMenu, _ 0, _ SDL_TRAYENTRY_NORMAL, _ StrPtr("显示窗口"), _ NULL _ ) If (showWindowEntry <> NULL) Then SDL_SetTrayEntryCallback(showWindowEntry, @ShowWindowCallback) End If ' 5. 添加菜单项:分隔符 SDL_InsertTrayEntryAt( _ mainMenu, _ 1, _ SDL_TRAYENTRY_SEPARATOR, _ NULL, _ NULL _ ) ' 6. 添加菜单项:静音模式(复选框) Dim As SDL_TrayEntry Ptr muteEntry = SDL_InsertTrayEntryAt( _ mainMenu, _ 2, _ SDL_TRAYENTRY_CHECKBOX, _ StrPtr("静音模式"), _ NULL _ ) If (muteEntry <> NULL) Then SDL_SetTrayEntryChecked(muteEntry, SDL_FALSE) ' 默认未选中 SDL_SetTrayEntryCallback(muteEntry, @ToggleMuteCallback) End If ' 7. 添加菜单项:退出(普通项) Dim As SDL_TrayEntry Ptr exitEntry = SDL_InsertTrayEntryAt( _ mainMenu, _ 3, _ SDL_TRAYENTRY_NORMAL, _ StrPtr("退出"), _ NULL _ ) If (exitEntry <> NULL) Then SDL_SetTrayEntryCallback(exitEntry, @ExitAppCallback) End If ' 8. 将菜单关联到托盘 SDL_SetTrayMenu(g_tray, mainMenu) ' 9. 更新托盘显示 SDL_UpdateTrays() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "系统托盘创建成功") Return SDL_TRUE End Function ' 主程序 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 ' 创建系统托盘 If (CreateSystemTray() = SDL_FALSE) Then SDL_Quit() Exit Sub End If ' 主事件循环(保持应用运行,等待用户操作) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "应用后台运行中,点击托盘「退出」结束程序...") While (g_quit = SDL_FALSE) Dim As SDL_Event evt ' 处理 SDL 事件(托盘点击事件需通过事件循环分发) While (SDL_PollEvent(@evt)) If (evt.type = SDL_QUIT) Then g_quit = SDL_TRUE End If Wend SDL_Delay(100) ' 降低CPU占用 Wend ' 销毁托盘实例 If (g_tray <> NULL) Then SDL_DestroyTray(g_tray) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "系统托盘已销毁") End If ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 关键前置条件: 必须初始化 SDL 视频子系统(SDL_Init(SDL_INIT_VIDEO)),托盘依赖窗口系统资源; 托盘创建后需调用 SDL_UpdateTrays() 才能生效(修改菜单/图标后也需调用); 应用需保持事件循环运行,否则无法响应托盘点击事件。 菜单项类型说明: 标志常量 菜单项类型 用途 SDL_TRAYENTRY_NORMAL 普通菜单项 点击触发回调(如「显示窗口」「退出」) SDL_TRAYENTRY_CHECKBOX 复选框项 可选中/取消选中(如「静音模式」) SDL_TRAYENTRY_SEPARATOR 分隔符 视觉分隔不同功能的菜单项 SDL_TRAYENTRY_SUBMENU 子菜单入口 点击展开二级菜单 平台兼容性: 平台 支持情况 特殊说明 Windows 完全支持(所有功能) 托盘图标显示在通知区域,支持所有菜单项类型 macOS 完全支持(所有功能) 托盘图标显示在菜单栏右侧,样式适配macOS Linux 大部分支持(依赖桌面环境) GNOME/KDE 支持良好,轻量桌面可能部分功能失效 移动平台 不支持 无系统托盘概念 资源管理注意: 必须调用 SDL_DestroyTray() 销毁托盘实例,否则会导致资源泄漏(尤其 Windows 平台); 菜单项的用户数据(userdata)需自行管理生命周期,避免悬空指针; 托盘图标建议使用 16x16/32x32 尺寸的 PNG/BMP,保证不同 DPI 下显示清晰。 总结 核心优势: 跨平台统一的系统托盘接口,无需适配 Windows 的 Shell_NotifyIcon、macOS 的 NSStatusItem 等原生 API; 支持丰富的菜单类型(普通项、复选框、子菜单、分隔符),满足桌面应用的交互需求; 回调机制清晰,可精准响应用户对菜单项的点击操作; 与 SDL 事件循环无缝集成,保证应用后台运行时的响应性。 使用建议: 托盘创建后需关联菜单才能显示右键菜单,空托盘仅显示图标无交互; 复选框菜单项需手动调用 SDL_SetTrayEntryChecked() 切换状态,并调用 SDL_UpdateTrays() 刷新; 退出应用前必须销毁托盘实例,避免残留托盘图标(Windows 平台易出现此问题); 托盘图标建议提供多分辨率版本,适配不同系统的显示缩放比例。 关键点回顾: SDL_Tray 是托盘核心句柄,所有托盘操作均基于此; 修改托盘菜单/图标后必须调用 SDL_UpdateTrays() 才能生效; 菜单项点击回调需配合 SDL 事件循环才能触发,应用需保持事件循环运行; 不同平台的托盘样式有差异,但接口行为一致,无需额外适配。
      • 2026年-3月-7日
      • 1 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_文件对话框(CategoryDialog) 2026-3-7
      SDL3_API分类参考_文件对话框(CategoryDialog) 文件对话框子系统(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 事件队列同步到主线程。 文件过滤规则格式: 扩展名模式使用分号 ; 分隔(如 "*.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 操作、资源访问)。
      • 2026年-3月-7日
      • 0 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_消息框(CategoryMessagebox) 2026-3-7
      SDL3_API分类参考_消息框(CategoryMessagebox) 消息框子系统(CategoryMessagebox) SDL 提供了一套简洁的消息框 API,适用于展示轻量提示信息——比如程序启动时发生致命错误(无需搭建完整 UI 即可告知用户),或在自定义 UI 加载完成前向用户展示关键提示。 这些消息框会尽可能使用系统原生对话框样式,保证与操作系统的视觉一致性。 SDL 提供两种消息框接口: 自定义消息框(SDL_ShowMessageBox()):支持丰富的配置选项(如多按钮、自定义颜色、图标类型),并能返回用户的选择结果; 简易消息框(SDL_ShowSimpleMessageBox()):极简接口,仅需传入提示文本和标题,等待用户点击「确定」按钮即可,满足大部分基础提示场景。 函数 SDL_ShowMessageBox:显示自定义样式的消息框,接收 SDL_MessageBoxData 配置结构体,返回用户点击的按钮索引(失败返回非0,可通过 SDL_GetError() 获取错误) SDL_ShowSimpleMessageBox:显示简易消息框,指定消息类型(提示/警告/错误)、标题和内容,无返回值(阻塞至用户点击「确定」) 数据类型 SDL_MessageBoxButtonFlags:消息框按钮标志类型(用于标记默认按钮、退出按钮等,如 SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) SDL_MessageBoxFlags:消息框全局标志类型(用于指定消息框类型/样式,如 SDL_MESSAGEBOX_ERROR/SDL_MESSAGEBOX_WARNING) 结构体 SDL_MessageBoxButtonData:单个按钮的配置结构体,包含按钮标志、按钮索引、按钮文本 SDL_MessageBoxColor:消息框颜色结构体,包含红/绿/蓝(RGB)三个分量(取值 0~255) SDL_MessageBoxColorScheme:消息框配色方案结构体,定义按钮、背景、文本等区域的颜色 SDL_MessageBoxData:自定义消息框的核心配置结构体,包含全局标志、父窗口、标题、内容、按钮数组、配色方案等 枚举 SDL_MessageBoxColorType:消息框颜色类型枚举,标识配色方案中不同区域的颜色,常见值: SDL_MESSAGEBOX_COLOR_BACKGROUND:背景色 SDL_MESSAGEBOX_COLOR_TEXT:文本色 SDL_MESSAGEBOX_COLOR_BUTTON_BORDER:按钮边框色 SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND:按钮背景色 SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED:按钮选中色 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充枚举/类型/结构体声明(FreeBASIC 绑定可能缺失) Enum SDL_MessageBoxFlags SDL_MESSAGEBOX_ERROR = 1 Shl 0 ' 错误类型消息框 SDL_MESSAGEBOX_WARNING = 1 Shl 1 ' 警告类型消息框 SDL_MESSAGEBOX_INFORMATION = 1 Shl 2 ' 信息类型消息框 End Enum Enum SDL_MessageBoxButtonFlags SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 1 Shl 0 ' 回车默认按钮 SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 1 Shl 1 ' ESC 默认按钮 End Enum Enum SDL_MessageBoxColorType SDL_MESSAGEBOX_COLOR_BACKGROUND = 0 ' 背景色 SDL_MESSAGEBOX_COLOR_TEXT = 1 ' 文本色 SDL_MESSAGEBOX_COLOR_BUTTON_BORDER = 2 ' 按钮边框色 SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND = 3 ' 按钮背景色 SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED = 4 ' 按钮选中色 SDL_MESSAGEBOX_COLOR_MAX = 5 ' 颜色类型总数 End Enum Type SDL_MessageBoxColor r As UByte ' 红色分量 (0-255) g As UByte ' 绿色分量 (0-255) b As UByte ' 蓝色分量 (0-255) End Type Type SDL_MessageBoxColorScheme colors(0 To SDL_MESSAGEBOX_COLOR_MAX-1) As SDL_MessageBoxColor End Type Type SDL_MessageBoxButtonData flags As Uint32 ' 按钮标志 buttonid As Integer ' 按钮索引(自定义) text As ZString Ptr ' 按钮文本 End Type Type SDL_MessageBoxData flags As Uint32 ' 消息框全局标志 window As SDL_Window Ptr ' 父窗口(NULL 表示无父窗口) title As ZString Ptr ' 消息框标题 message As ZString Ptr ' 消息框内容 numbuttons As Integer ' 按钮数量 buttons As SDL_MessageBoxButtonData Ptr ' 按钮数组 colorScheme As SDL_MessageBoxColorScheme Ptr ' 配色方案(NULL 使用系统默认) End Type ' 函数声明 Declare Sub SDL_ShowSimpleMessageBox CDecl (ByVal flags As Uint32, ByVal title As ZString Ptr, ByVal message As ZString Ptr, ByVal window As SDL_Window Ptr) Declare Function SDL_ShowMessageBox CDecl (ByVal messageboxdata As SDL_MessageBoxData Ptr, ByRef buttonid As Integer) As Integer ' 示例1:显示简易消息框(提示/警告/错误) Sub ShowSimpleMessageBoxes() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例1:显示简易消息框】") ' 1. 信息提示框 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "显示信息提示框...") SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, _ StrPtr("操作成功"), _ StrPtr("文件已保存至默认路径!"), _ NULL) ' 2. 警告提示框 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "显示警告提示框...") SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, _ StrPtr("低电量警告"), _ StrPtr("当前电量不足 20%,请及时充电!"), _ NULL) ' 3. 错误提示框 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "显示错误提示框...") SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, _ StrPtr("初始化失败"), _ StrPtr("无法加载配置文件,请检查文件是否存在!"), _ NULL) End Sub ' 示例2:显示自定义消息框(多按钮 + 自定义配色) Sub ShowCustomMessageBox() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例2:显示自定义消息框】") ' 1. 定义按钮(确定/取消/跳过) Dim As SDL_MessageBoxButtonData buttons(2) ' 按钮0:确定(回车默认) buttons(0).flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT buttons(0).buttonid = 0 buttons(0).text = StrPtr("确定") ' 按钮1:取消(ESC 默认) buttons(1).flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT buttons(1).buttonid = 1 buttons(1).text = StrPtr("取消") ' 按钮2:跳过 buttons(2).flags = 0 buttons(2).buttonid = 2 buttons(2).text = StrPtr("跳过") ' 2. 自定义配色方案(可选) Dim As SDL_MessageBoxColorScheme colorScheme ' 背景色:浅灰色 colorScheme.colors(SDL_MESSAGEBOX_COLOR_BACKGROUND) = Type<SDL_MessageBoxColor>(240, 240, 240) ' 文本色:黑色 colorScheme.colors(SDL_MESSAGEBOX_COLOR_TEXT) = Type<SDL_MessageBoxColor>(0, 0, 0) ' 按钮背景色:浅蓝色 colorScheme.colors(SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND) = Type<SDL_MessageBoxColor>(180, 210, 255) ' 按钮选中色:深蓝色 colorScheme.colors(SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED) = Type<SDL_MessageBoxColor>(100, 140, 255) ' 按钮边框色:灰色 colorScheme.colors(SDL_MESSAGEBOX_COLOR_BUTTON_BORDER) = Type<SDL_MessageBoxColor>(150, 150, 150) ' 3. 配置消息框数据 Dim As SDL_MessageBoxData msgBoxData msgBoxData.flags = SDL_MESSAGEBOX_WARNING ' 警告类型 msgBoxData.window = NULL ' 无父窗口 msgBoxData.title = StrPtr("更新提示") ' 标题 msgBoxData.message = StrPtr("检测到新版本 v2.0,是否立即更新?") ' 内容 msgBoxData.numbuttons = 3 ' 按钮数量 msgBoxData.buttons = @buttons(0) ' 按钮数组 msgBoxData.colorScheme = @colorScheme ' 自定义配色 ' 4. 显示自定义消息框并获取用户选择 Dim As Integer selectedButtonId Dim As Integer result = SDL_ShowMessageBox(@msgBoxData, selectedButtonId) If (result = 0) Then ' 处理用户选择 Select Case selectedButtonId Case 0: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选择:确定(开始更新)") Case 1: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选择:取消(放弃更新)") Case 2: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "用户选择:跳过(稍后更新)") Case Else: SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "用户选择了未知按钮") End Select Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "显示自定义消息框失败:%s", SDL_GetError()) End If End Sub ' 示例3:带父窗口的消息框(模拟与游戏窗口关联) Sub ShowMessageBoxWithParent() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例3:带父窗口的消息框】") ' 创建一个临时窗口作为父窗口 Dim As SDL_Window Ptr window = SDL_CreateWindow( _ StrPtr("SDL 示例窗口"), _ SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, _ 640, 480, _ SDL_WINDOW_SHOWN _ ) If (window <> NULL) Then ' 显示关联父窗口的错误消息框 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, _ StrPtr("游戏错误"), _ StrPtr("无法初始化渲染器,请检查显卡驱动!"), _ window) ' 销毁窗口 SDL_DestroyWindow(window) End If 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 ' 运行示例 ShowSimpleMessageBoxes() ShowCustomMessageBox() ShowMessageBoxWithParent() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 关键前置条件: 显示消息框必须初始化 SDL 视频子系统(SDL_Init(SDL_INIT_VIDEO)),否则会调用失败; 消息框默认是模态对话框,会阻塞当前线程直至用户操作完成。 SDL_MessageBoxFlags 常用值: 标志常量 作用 系统表现 SDL_MESSAGEBOX_ERROR 错误类型 显示错误图标(如 Windows 的红色叉号) SDL_MESSAGEBOX_WARNING 警告类型 显示警告图标(如 Windows 的黄色感叹号) SDL_MESSAGEBOX_INFORMATION 信息类型 显示信息图标(如 Windows 的蓝色i) 按钮标志使用规则: SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT:设置为「回车」快捷键对应的按钮; SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT:设置为「ESC」快捷键对应的按钮; 一个消息框建议仅设置一个回车默认按钮和一个 ESC 默认按钮。 平台兼容性: ✅ Windows/macOS/Linux:完全支持自定义消息框和简易消息框,样式贴合系统原生; ✅ 移动平台(Android/iOS):简易消息框支持良好,自定义消息框会适配移动端样式; ❗ 部分嵌入式系统:可能仅支持简易消息框,自定义配色/多按钮可能失效。 总结 核心优势: 跨平台统一的消息框接口,无需适配不同系统的原生对话框 API(如 Windows 的 MessageBox、GTK 的 gtk_message_dialog); 支持从极简到高度自定义的消息框需求,兼顾易用性和灵活性; 自动适配系统原生样式,保证用户体验一致性; 支持关联父窗口,实现模态对话框的层级关联。 使用建议: 基础提示场景优先使用 SDL_ShowSimpleMessageBox()(代码简洁、兼容性好); 需要用户选择(如确认/取消)时使用 SDL_ShowMessageBox(); 自定义配色仅在特殊需求下使用,优先依赖系统默认配色(更符合用户习惯); 消息框文本建议简洁明了,避免过长内容影响阅读。 关键点回顾: 显示消息框必须初始化 SDL 视频子系统(SDL_INIT_VIDEO); SDL_ShowSimpleMessageBox 适用于单按钮提示,SDL_ShowMessageBox 适用于多按钮选择; 按钮标志可设置回车/ESC 快捷键,提升操作便捷性; 消息框为模态对话框,会阻塞调用线程直至用户操作完成。
      • 2026年-3月-7日
      • 1 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_电源管理(CategoryPower) 2026-3-7
      SDL3_API分类参考_电源管理(CategoryPower) 电源管理子系统(CategoryPower) SDL 提供了轻量的电源管理接口,核心功能是获取设备的电源状态信息,尤其适用于移动设备(如笔记本、平板、手机)上的游戏/应用开发。 该子系统仅包含一个核心函数:SDL_GetPowerInfo()。 典型应用场景 检测设备是否使用电池供电,若电池电量低,可降低游戏帧率、关闭特效以减少功耗,延长续航; 全屏运行时显示电池电量指示器; 电量极低时提醒用户保存游戏进度,避免数据丢失。 函数 SDL_GetPowerInfo:获取系统电源状态信息,返回 SDL_PowerState 枚举值;同时通过输出参数返回「剩余电池使用时间(秒)」和「电池电量百分比」(不支持的平台/设备返回对应无效值) 数据类型 (无) 结构体 (无) 枚举 SDL_PowerState:电源状态枚举,包含以下取值: SDL_POWERSTATE_UNKNOWN:无法确定电源状态(如无电池的台式机、不支持的系统) SDL_POWERSTATE_ON_BATTERY:设备正在使用电池供电(未插电) SDL_POWERSTATE_NO_BATTERY:设备无电池(如台式机) SDL_POWERSTATE_CHARGING:电池正在充电 SDL_POWERSTATE_CHARGED:电池已充满电 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充枚举和函数声明(FreeBASIC 绑定可能缺失) Enum SDL_PowerState SDL_POWERSTATE_UNKNOWN = 0 ' 未知状态 SDL_POWERSTATE_ON_BATTERY = 1 ' 电池供电 SDL_POWERSTATE_NO_BATTERY = 2 ' 无电池 SDL_POWERSTATE_CHARGING = 3 ' 充电中 SDL_POWERSTATE_CHARGED = 4 ' 已充满 End Enum Declare Function SDL_GetPowerInfo CDecl (ByRef seconds As Integer, ByRef percent As Integer) As SDL_PowerState ' 转换电源状态枚举为可读字符串 Function PowerStateToString(ByVal state As SDL_PowerState) As ZString Ptr Select Case state Case SDL_POWERSTATE_UNKNOWN: Return StrPtr("未知状态") Case SDL_POWERSTATE_ON_BATTERY: Return StrPtr("电池供电(未插电)") Case SDL_POWERSTATE_NO_BATTERY: Return StrPtr("无电池(台式机等)") Case SDL_POWERSTATE_CHARGING: Return StrPtr("充电中") Case SDL_POWERSTATE_CHARGED: Return StrPtr("电池已充满") Case Else: Return StrPtr("无效状态") End Select End Function ' 获取并打印电源信息 Sub PrintPowerInfo() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【当前电源状态信息】") ' 定义输出参数:剩余使用时间(秒)、电量百分比 Dim As Integer remainingSeconds, batteryPercent Dim As SDL_PowerState powerState = SDL_GetPowerInfo(remainingSeconds, batteryPercent) ' 打印电源状态 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电源状态:%s", *PowerStateToString(powerState)) ' 打印剩余时间(-1 表示无法获取) If (remainingSeconds = -1) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "剩余使用时间:无法获取") ElseIf (remainingSeconds = -2) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "剩余使用时间:无限(插电状态)") Else Dim As Integer hours = remainingSeconds \ 3600 Dim As Integer minutes = (remainingSeconds Mod 3600) \ 60 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "剩余使用时间:%d小时%d分钟", hours, minutes) End If ' 打印电量百分比(-1 表示无法获取) If (batteryPercent = -1) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电池电量:无法获取") Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电池电量:%d%%", batteryPercent) End If End Sub ' 根据电源状态调整应用配置(节能逻辑) Sub AdjustAppForPower() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【根据电源状态调整应用配置】") Dim As Integer remainingSeconds, batteryPercent Dim As SDL_PowerState powerState = SDL_GetPowerInfo(remainingSeconds, batteryPercent) ' 仅在电池供电时执行节能逻辑 If (powerState = SDL_POWERSTATE_ON_BATTERY) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "当前为电池供电模式,执行节能策略") ' 电量 > 50%:正常运行 If (batteryPercent > 50 And batteryPercent <> -1) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电量充足(%d%%):保持默认配置", batteryPercent) ' 电量 20% ~ 50%:降低帧率 ElseIf (batteryPercent >= 20 And batteryPercent <= 50) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电量中等(%d%%):帧率降低至 30 FPS", batteryPercent) ' 模拟设置帧率 ' SDL_SetWindowDisplayMode(window, &displayMode); ' displayMode.refresh_rate = 30; ' 电量 < 20%:深度节能 ElseIf (batteryPercent > 0 And batteryPercent < 20) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "电量低(%d%%):关闭特效 + 帧率降至 15 FPS", batteryPercent) ' 模拟关闭特效 ' DisableSpecialEffects(); ' 电量极低(< 10%):提醒保存 ElseIf (batteryPercent > 0 And batteryPercent < 10) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "电量极低(%d%%):请立即保存数据!", batteryPercent) End If Else SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "当前为插电/无电池模式:使用高性能配置") End If End Sub ' 定时监控电源状态(模拟实时检测) Sub MonitorPowerState() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【实时监控电源状态(5秒)】") Const MONITOR_DURATION As Integer = 5 ' 监控5秒 Const CHECK_INTERVAL As Integer = 1000 ' 每秒检测一次 For i As Integer = 1 To MONITOR_DURATION SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "=== 第 %d 秒检测 ===", i) PrintPowerInfo() SDL_Delay(CHECK_INTERVAL) Next SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "监控结束") End Sub ' 主程序 Sub Main() ' 初始化 SDL If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 PrintPowerInfo() AdjustAppForPower() MonitorPowerState() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 SDL_GetPowerInfo 返回值规则: 输出参数 无效值 含义说明 remainingSeconds -1 无法获取剩余时间(如设备不支持) remainingSeconds -2 剩余时间无限(设备插电、无电池) batteryPercent -1 无法获取电量百分比(如设备不支持、无电池) 平台支持说明: ✅ Windows/macOS/Linux:支持大部分笔记本/移动设备的电源状态检测; ✅ 移动平台(Android/iOS):完善支持电池状态、剩余时间、电量百分比; ❌ 无电池设备(台式机、服务器):返回 SDL_POWERSTATE_NO_BATTERY,电量/时间参数返回 -1; ❌ 部分嵌入式系统:可能返回 SDL_POWERSTATE_UNKNOWN(无电源管理接口)。 节能策略设计建议: 电量区间 建议操作 > 50% 高性能模式(满帧率、全特效) 20%~50% 平衡模式(降低帧率至 30 FPS、关闭部分特效) 10%~20% 节能模式(帧率降至 15 FPS、关闭所有特效) < 10% 紧急模式(提醒保存、暂停非核心功能) 调用频率建议: 无需高频调用(电源状态变化缓慢),建议 1~5 秒检测一次即可; 避免在游戏主循环中每帧调用,减少系统开销。 总结 核心优势: 跨平台统一的电源状态检测接口,无需适配不同系统的原生电源 API(如 Windows 的 GetSystemPowerStatus、Android 的 BatteryManager); 轻量易用,仅一个核心函数即可获取电源状态、剩余时间、电量百分比; 返回值规则清晰,边界条件(如无效值)处理明确,便于容错。 使用建议: 移动应用/游戏必须接入电源状态检测,根据电量动态调整性能配置,提升用户体验; 对返回的无效值(-1/-2)做好容错处理,避免程序崩溃; 电量极低时优先提醒用户保存数据,再执行节能逻辑; 插电状态下恢复高性能配置,保证体验。 关键点回顾: SDL_GetPowerInfo 是电源管理的核心函数,返回电源状态枚举,同时输出剩余时间和电量百分比; 仅 SDL_POWERSTATE_ON_BATTERY 状态下需要执行节能逻辑,其他状态可使用高性能配置; 无效值(-1/-2)需特殊处理,避免数值异常导致的逻辑错误; 检测频率建议 1~5 秒一次,无需高频调用。
      • 2026年-3月-7日
      • 0 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • SDL3_API分类参考_进程控制(CategoryProcess) 2026-3-7
      SDL3_API分类参考_进程控制(CategoryProcess) 进程控制子系统(CategoryProcess) SDL 提供了一套跨平台的进程控制接口,用于创建、管理和销毁操作系统级别的子进程,无需适配不同系统的原生进程 API(如 Windows 的 CreateProcess、Linux 的 fork/exec)。 核心使用流程 创建进程:通过 SDL_CreateProcess() 创建基础子进程,或通过 SDL_CreateProcessWithProperties() 创建带高级属性(如 IO 重定向、进程链)的子进程; 进程交互:使用 SDL_ReadProcess()、SDL_GetProcessInput()/SDL_GetProcessOutput() 读写子进程的输入/输出流; 进程管理:通过 SDL_WaitProcess() 获取进程退出状态,或用 SDL_KillProcess() 强制终止进程; 资源清理:无论进程是被杀死、自行退出还是仍在运行,都必须调用 SDL_DestroyProcess() 释放进程相关资源。 函数 SDL_CreateProcess:创建基础子进程,指定可执行文件路径和命令行参数,返回 SDL_Process 句柄(失败返回 NULL,可通过 SDL_GetError() 获取错误) SDL_CreateProcessWithProperties:创建带自定义属性的子进程(支持 IO 重定向、工作目录、环境变量等高级配置),返回 SDL_Process 句柄 SDL_DestroyProcess:销毁进程句柄,释放所有关联资源(即使进程仍在运行,也需调用此函数清理;不会自动终止进程) SDL_GetProcessInput:获取子进程的标准输入(stdin)流句柄,用于向子进程写入数据 SDL_GetProcessOutput:获取子进程的标准输出(stdout)或标准错误(stderr)流句柄,用于读取子进程输出 SDL_GetProcessProperties:获取已创建进程的属性信息(如 IO 配置、进程 ID、工作目录等) SDL_KillProcess:强制终止指定的子进程(向进程发送终止信号,不同系统实现不同:Windows 用 TerminateProcess,Linux/macOS 用 kill) SDL_ReadProcess:简化版子进程输出读取函数,直接从子进程标准输出读取指定长度的数据 SDL_WaitProcess:阻塞等待子进程退出,返回进程的退出码;若进程已退出,立即返回结果 数据类型 SDL_Process:进程句柄类型(封装了平台相关的进程信息,如 Windows 的 HANDLE、Linux 的 pid_t),用于标识和管理子进程 结构体 (无) 枚举 SDL_ProcessIO:进程 IO 配置枚举,用于指定子进程的输入/输出流模式,常见值: SDL_PROCESS_IO_INHERIT:继承父进程的 IO 流(默认) SDL_PROCESS_IO_PIPE:创建管道用于父子进程间 IO 通信 SDL_PROCESS_IO_NULL:重定向到空设备(忽略输入/输出) 宏 (无) FreeBASIC 示例代码 ' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库) #Include "SDL.bi" ' 补充类型和函数声明(FreeBASIC 绑定可能缺失) Type SDL_Process As Any Ptr ' SDL_ProcessIO 枚举定义 Enum SDL_ProcessIO SDL_PROCESS_IO_INHERIT = 0 ' 继承父进程IO SDL_PROCESS_IO_PIPE = 1 ' 创建管道通信 SDL_PROCESS_IO_NULL = 2 ' 重定向到空设备 End Enum ' 进程属性结构体(简化版,实际 SDL 定义更完整) Type SDL_ProcessProperties io_stdin As SDL_ProcessIO ' 标准输入配置 io_stdout As SDL_ProcessIO ' 标准输出配置 io_stderr As SDL_ProcessIO ' 标准错误配置 working_directory As ZString Ptr ' 工作目录 environment As ZString Ptr Ptr ' 环境变量 End Type ' 核心函数声明 Declare Function SDL_CreateProcess CDecl (ByVal path As ZString Ptr, ByVal args As ZString Ptr Ptr) As SDL_Process Declare Function SDL_CreateProcessWithProperties CDecl (ByVal path As ZString Ptr, ByVal args As ZString Ptr Ptr, ByVal props As SDL_ProcessProperties Ptr) As SDL_Process Declare Sub SDL_DestroyProcess CDecl (ByVal process As SDL_Process) Declare Function SDL_GetProcessInput CDecl (ByVal process As SDL_Process) As SDL_IOStream Ptr Declare Function SDL_GetProcessOutput CDecl (ByVal process As SDL_Process) As SDL_IOStream Ptr Declare Function SDL_GetProcessProperties CDecl (ByVal process As SDL_Process, ByVal props As SDL_ProcessProperties Ptr) As Integer Declare Function SDL_KillProcess CDecl (ByVal process As SDL_Process) As Integer Declare Function SDL_ReadProcess CDecl (ByVal process As SDL_Process, ByVal buffer As Any Ptr, ByVal size As Integer) As Integer Declare Function SDL_WaitProcess CDecl (ByVal process As SDL_Process, ByRef exit_code As Integer) As Integer ' 示例1:创建基础子进程并读取输出 Sub CreateBasicProcess() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例1:创建基础子进程】") ' 定义命令行参数(根据平台适配) Dim As ZString Ptr args(2) #If Defined(SDL_PLATFORM_WINDOWS) ' Windows:执行 cmd /c echo 测试内容 Dim As ZString * 256 exePath = "cmd.exe" args(0) = StrPtr("/c") args(1) = StrPtr("echo Hello from child process (Windows)!") args(2) = NULL #Elif Defined(SDL_PLATFORM_LINUX) Or Defined(SDL_PLATFORM_MACOS) ' Linux/macOS:执行 echo 测试内容 Dim As ZString * 256 exePath = "/bin/echo" args(0) = StrPtr("Hello from child process (Linux/macOS)!") args(1) = NULL #Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "不支持的平台") Exit Sub #EndIf ' 创建子进程 Dim As SDL_Process proc = SDL_CreateProcess(@exePath, @args(0)) If (proc = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建进程失败:%s", SDL_GetError()) Exit Sub End If SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "子进程创建成功") ' 读取子进程输出 Dim As UByte buffer(1023) Dim As Integer readSize = SDL_ReadProcess(proc, @buffer(0), 1024) If (readSize > 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "子进程输出:%.*s", readSize, @buffer(0)) ElseIf (readSize = 0) Then SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "子进程无输出") Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "读取子进程输出失败:%s", SDL_GetError()) End If ' 等待进程退出并获取退出码 Dim As Integer exitCode If (SDL_WaitProcess(proc, exitCode) = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "子进程正常退出,退出码:%d", exitCode) Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "等待进程退出失败:%s", SDL_GetError()) End If ' 销毁进程句柄(必须调用) SDL_DestroyProcess(proc) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "进程句柄已销毁") End Sub ' 示例2:创建带属性的进程(IO 重定向 + 自定义工作目录) Sub CreateProcessWithProps() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例2:创建带属性的子进程】") ' 配置进程属性 Dim As SDL_ProcessProperties props props.io_stdin = SDL_PROCESS_IO_NULL ' 标准输入重定向到空 props.io_stdout = SDL_PROCESS_IO_PIPE ' 标准输出创建管道 props.io_stderr = SDL_PROCESS_IO_PIPE ' 标准错误创建管道 props.working_directory = StrPtr(".") ' 工作目录为当前目录 props.environment = NULL ' 继承父进程环境变量 ' 定义命令(执行目录列表命令) Dim As ZString Ptr args(1) Dim As ZString * 256 exePath #If Defined(SDL_PLATFORM_WINDOWS) exePath = "cmd.exe" args(0) = StrPtr("/c dir") args(1) = NULL #Elif Defined(SDL_PLATFORM_LINUX) Or Defined(SDL_PLATFORM_MACOS) exePath = "/bin/ls" args(0) = StrPtr("-l") args(1) = NULL #Else Exit Sub #EndIf ' 创建带属性的进程 Dim As SDL_Process proc = SDL_CreateProcessWithProperties(@exePath, @args(0), @props) If (proc = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建带属性进程失败:%s", SDL_GetError()) Exit Sub End If ' 等待进程完成 Dim As Integer exitCode SDL_WaitProcess(proc, exitCode) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "带属性进程退出码:%d", exitCode) ' 销毁进程句柄 SDL_DestroyProcess(proc) End Sub ' 示例3:强制终止长时间运行的进程 Sub KillLongRunningProcess() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例3:强制终止子进程】") ' 创建一个长时间运行的进程 Dim As ZString Ptr args(1) Dim As ZString * 256 exePath #If Defined(SDL_PLATFORM_WINDOWS) ' Windows:执行 timeout 10(等待10秒) exePath = "timeout.exe" args(0) = StrPtr("10") args(1) = NULL #Elif Defined(SDL_PLATFORM_LINUX) Or Defined(SDL_PLATFORM_MACOS) ' Linux/macOS:执行 sleep 10(等待10秒) exePath = "/bin/sleep" args(0) = StrPtr("10") args(1) = NULL #Else Exit Sub #EndIf Dim As SDL_Process proc = SDL_CreateProcess(@exePath, @args(0)) If (proc = NULL) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建进程失败:%s", SDL_GetError()) Exit Sub End If ' 等待2秒后强制终止 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "等待2秒后终止进程...") SDL_Delay(2000) If (SDL_KillProcess(proc) = 0) Then SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "进程已强制终止") Else SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "终止进程失败:%s", SDL_GetError()) End If ' 等待进程退出(确认终止) Dim As Integer exitCode SDL_WaitProcess(proc, exitCode) ' 销毁进程句柄 SDL_DestroyProcess(proc) End Sub ' 主程序 Sub Main() ' 初始化 SDL If (SDL_Init(0) < 0) Then SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError()) Exit Sub End If ' 运行示例 CreateBasicProcess() CreateProcessWithProps() KillLongRunningProcess() ' 清理 SDL SDL_Quit() SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出") End Sub ' 运行主程序 Main() 核心知识点补充 跨平台进程创建差异: 平台 原生进程 API SDL 封装优势 Windows CreateProcess 无需处理 STARTUPINFO/PROCESS_INFORMATION 结构体 Linux fork + execve 无需手动处理子进程 fork 后的资源隔离 macOS fork + execvp 统一的错误处理和资源清理逻辑 SDL_ProcessIO 枚举使用场景: SDL_PROCESS_IO_INHERIT:子进程直接使用父进程的控制台/终端(适合简单命令执行); SDL_PROCESS_IO_PIPE:父子进程通过管道通信(适合需要读取/写入子进程输出/输入的场景); SDL_PROCESS_IO_NULL:忽略子进程的 IO(适合后台运行、无需交互的进程)。 关键注意事项: 资源清理:无论进程状态如何,必须调用 SDL_DestroyProcess(),否则会导致资源泄漏; 阻塞等待:SDL_WaitProcess() 是阻塞函数,若需非阻塞检测进程状态,可先调用 SDL_KillProcess() 或结合 SDL 事件循环; 权限问题:创建进程时需确保可执行文件路径有执行权限,工作目录有访问权限; 参数传递:命令行参数数组必须以 NULL 结尾(符合 C 语言参数传递规范)。 错误处理建议: 所有进程创建/操作函数失败时返回 NULL/非0,需通过 SDL_GetError() 获取具体错误信息; 对长时间运行的进程,建议增加超时逻辑(如 SDL_Delay() + SDL_KillProcess()); 读取子进程输出时,缓冲区大小需合理(避免溢出或截断)。 总结 核心优势: 跨平台统一的进程控制接口,无需适配不同系统的原生进程 API; 简化的 IO 重定向配置(通过 SDL_ProcessIO 枚举),无需手动创建管道/文件句柄; 完善的资源管理机制,SDL_DestroyProcess() 统一清理进程相关资源; 兼容主流平台的进程终止、等待逻辑,降低跨平台开发成本。 使用建议: 简单进程创建优先使用 SDL_CreateProcess(),需要高级配置时使用 SDL_CreateProcessWithProperties(); 读取子进程输出时,优先使用 SDL_ReadProcess()(简化接口),复杂 IO 交互使用 SDL_GetProcessOutput() 获取流句柄; 强制终止进程前,建议先尝试优雅退出(如向子进程发送信号),仅在必要时使用 SDL_KillProcess(); 始终在进程使用完毕后调用 SDL_DestroyProcess(),即使进程已退出。 关键点回顾: SDL_Process 是进程句柄核心类型,所有进程操作均基于此句柄; SDL_DestroyProcess() 必须调用,是避免资源泄漏的关键; SDL_ProcessIO 枚举控制进程 IO 模式,SDL_PROCESS_IO_PIPE 是父子进程通信的核心配置; SDL_WaitProcess() 阻塞等待进程退出,SDL_KillProcess() 强制终止进程,需配合使用以保证进程状态可控。
      • 2026年-3月-7日
      • 0 阅读
      • 0 评论
      VisualFreeBasic编程文档
    • 1
    • 2
    • 3
    博主栏壁纸
    博主头像 勇芳

    326 文章数
    0 评论量
    • QQ游戏大厅多开版_旧版_2012到2025版
    • 使用Sandboxie沙盒多开QQ游戏大厅
    • Sandboxie沙盒(隔离软件)
    人生倒计时
    最新评论
    链接
    • 公益·寻亲,让爱回家
    • Visual Basic6 语言和控件手册
    • CWindow类库帮助FreeBasic版
    • FreeBASIC 帮助文档中文版
    • Windows GDI 编程手册
    • Windows GDI+ 编程手册
    • SQLite3数据库API手册
    • WebBrowser控件编程手册
    • Win32API参考手册
    • Windows 编程宝典
    • WinHttp参考资料
    • WMI编程手册
    • VisualFreeBasic编程文档
    舔狗日记
    载入天数...载入时分秒...

    © 2025 勇芳软件工作室 版权所有

    ICP备案图标 浙ICP备11006222号-1 | 公安备案图标 33100402331731号

    powered by emlog 浙ICP备11006222号-1