news 2026/10/14 3:05:31

RGF_CJ 全局函数全解析:从应用生命周期、系统定时器到窗口与指针互操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RGF_CJ 全局函数全解析:从应用生命周期、系统定时器到窗口与指针互操作
  • 图形学
  • 桌面应用

【免费下载链接】RGF_CJ

RGF是仓颉Windows系统下的通用渲染框架(兼应用开发框架)。RGF仓颉版(后续简称"RGF")基于RGF(C/C++版)封装优化而来。RGF为开发者提供轻量化、安全、高性能以及高度一致性的2D渲染能力以及常用的桌面应用开发工具,并且提供对接Direct3D的相关接口,以满足开发者对3D画面渲染的需求。在Windows开发方面,RGF在子包内也提供开箱即用的Windows API,确保熟悉Win32的开发者快速上手。此外,RGF还提供一些常用功能的封装(如XAudio2、MF),以辅助开发者实现音频、摄像头等扩展功能的管理。

项目地址:https://gitcode.com/Cangjie-SIG/RGF_CJ
点击查看免费下载

本篇文章系统梳理 RGF_CJ(仓颉版 RGF 通用渲染框架)核心包rgf.rgf_core暴露的全部顶层函数(API 文档见 doc/api/rgf.rgf_core/函数.md),涵盖应用主流程(rsMain/rsInitialize/rsDestroy)、系统定时器、显示器查询、窗口类注册与批量布局、以及字符串/指针等 Win32 互操作工具函数。阅读后你将掌握 RGF_CJ 的全局函数命名约定、每个函数的参数与返回值语义、底层 Win32 调用链,并能独立拼装出一个完整的 RGF 桌面应用骨架。

全局函数三大家族:rs、ru、rw 前缀约定

rgf.rgf_core的公开函数按用途分为三个前缀家族,从源码 src/rgf_core/rgf_api.cj、src/rgf_core/rgf_utils.cj 与 src/rgf_core/rgf_base.cj 中可以清晰看出其分工:

前缀语义典型成员
rsRGF System,框架级系统函数:初始化/释放、主入口、定时器、进程结束、显示器查询rsMain、rsInitialize、rsDestroy、rsCreateSysTimer、rsEnd
ruRGF Utility,通用工具函数:字符串编码转换、指针互转、内存安全、位重解释、句柄转换ruStrToWStr、ruUllToPtr、ruSafeCStruct、ruRedefBit、ruToHwnd
rwRGF Window,窗口相关函数:窗口类注册/注销、批量移动、主窗口判断、默认窗口过程rwRegister、rwUnregister、rwBatchMove、rwIsMainWin

这三类函数共同构成了 RGF_CJ 面向应用层开放的"系统 API 面"。其中涉及句柄的类型别名定义见 doc/api/rgf.rgf_core/类型别名.md:RgfHwnd = UIntNative(窗口句柄)、RgfHdc = UIntNative(设备上下文)、RgfTimer = HANDLE(定时器句柄)。

应用生命周期管理:rsMain 主入口与三种运行模式

rsMain是 RGF_CJ 应用的主入口,内部封装了 Win32 消息循环的完整流程。官方注释特别说明:"本函数内部封装了 Win 的主要流程,若需要更高的自由度可参考此代码结构自行实现"。

函数签名与重载

// 完整形态:create 回调 + destroy 回调 + 运行模式(默认阻塞当前线程) public func rsMain(create: () -> Unit, destroy: () -> Unit, mode!: RunMode): Unit // 便捷重载:只提供 create,destroy 为空实现,默认 SysThreadAndWait @When[!debug] public func rsMain(create: () -> Unit): Unit // 便捷重载:create + destroy,默认 SysThreadAndWait @When[!debug] public func rsMain(create: () -> Unit, destroy: () -> Unit): Unit // 便捷重载:create + 显式 mode public func rsMain(create: () -> Unit, mode!: RunMode): Unit

参数说明:

参数类型描述
create()->Unit用于创建窗口相关资源的回调(窗口类注册、窗口创建、渲染资源初始化)
destroy()->Unit用于释放窗口相关资源的回调(窗口销毁、窗口类注销)
modeRunMode主函数运行模式,默认阻塞当前线程

RunMode 三种模式

mode参数取值定义在 doc/api/rgf.rgf_core/枚举/RunMode.md:

枚举值语义说明
CJMainThread直接基于仓颉主线程在主线程上直接运行消息循环,无需额外线程
SysThreadAndAsyn新建系统线程,异步不阻塞UI 线程独立运行,调用rsMain的线程继续向下执行
SysThreadAndWait新建系统线程,并等待执行结束UI 线程运行期间阻塞调用线程,直到窗口全部关闭

默认模式随编译条件切换

从源码 src/rgf_core/rgf_base.cj#L1358-L1400 可以看出,两个便捷重载的默认模式依赖编译条件:

  • @When[!debug](非调试构建,即发行版):默认RunMode.SysThreadAndWait,创建独立系统 UI 线程并阻塞等待;
  • @When[debug](调试构建):默认RunMode.CJMainThread,直接在仓颉主线程上跑窗口逻辑。

这是因为在调试环境下仓颉侧部分功能在系统线程上表现异常,主线程模式便于断点与调试。

底层流程:rsMainInner 消息循环

rsMain的真正实现在rsMainInner(src/rgf_core/rgf_base.cj#L1234-L1293),其执行顺序为:

  1. 获取模块句柄:调用wGetModuleHandleW得到HINSTANCE;
  2. 初始化 RGF 绘制库:CJMainThread模式复用全局初始化自动机持有的上下文,其余模式调用rsInitialize();
  3. 构造全局上下文:context = Context(contextPtr, hInst);
  4. 执行 create 回调:rgfCreateFunc()调用用户传入的create;
  5. 进入消息循环:while(haveMainWin.load())循环执行wGetMessageW→ 错误处理(bRet < 0抛WinException)→WM_QUIT(bRet == 0)跳出 → 过滤无效窗口消息 →wTranslateMessage→wDispatchMessageW。当主窗口被销毁(haveMainWin为 false)时循环自动退出;
  6. 执行 destroy 回调:rsDestroyFunc()调用用户destroy,并顺带清理所有记录在案、未被释放的窗口类(rwClearAllWinClass);
  7. 释放上下文与绘制库:置空context,非主线程模式下调用rsDestroy(contextPtr);
  8. 清理全局依赖并允许再次进入。

注意:rsMain内部通过AtomicBool互斥保证"主 UI 线程只能初始化一次";重复进入会抛出异常,异常文本见常量rgfErrorMainUiThreadinited("RGF 的主 UI 线程已被初始化!",见 doc/api/rgf.rgf_core/变量与常量.md)。

实战骨架:来自测试工程的标准用法

仓库测试工程 test/CT/base/src/main.cj 给出了标准应用骨架:

func TestCall(): Int64 { rsModRefToCurrDir() // 将程序存储路径作为相对路径起点 let mainWin: rwTest = rwTest() let winClass: WinContext = WinContext() rsMain( {=> // create:创建窗口相关资源 // 1. 注册窗口类 rwRegister(winClass, "GF_", WinClassStyle.DblClks | WinClassStyle.HRedraw | WinClassStyle.VRedraw ) // 2. 创建 Direct2D 窗口 mainWin.createWin(winClass, "test", Int32.Min, Int32.Min, 500, 500, 0, WinStyleEx.e2n(WinStyleEx.Default), WinStyle.e2n(WinStyle.OverlappedWindow), substrate: Substrate.Direct2D, layered: false ) }, {=> // destroy:释放窗口相关资源 // 3. 确保窗口被释放(安全释放) // 4. 注销窗口类 rwUnregister(winClass) } ) return 0 } main(): Int64 { TestCall() return 0 }

SysThreadAndAsyn 模式与 ruFinished/rsEnd 的配合

当选择RunMode.SysThreadAndAsyn时,rsMain立即返回,主线程可继续做自己的事(如摄像头采集、后台计算),此时用ruFinished()判断 UI 是否已结束。文档明确说明:ruFinished 一般用于rsMainmode 为SysThreadAndAsyn的情况下,用于检查并阻塞其它线程。

public func ruFinished(): Bool // false 正在执行;true 执行完成

其实现(src/rgf_core/rgf_base.cj#L1419-L1421)为return !isInInner(),即内部"进入标志"被清除(消息循环结束并exitInner())后返回 true。

rsEnd(exitCode: UInt32)用于强制结束进程,底层直接调用wExitProcess(exitCode)(src/rgf_core/rgf_utils.cj#L364-L366),参数exitCode为进程退出码。摄像头测试工程 test/HLT/camera/src/main.cj 演示了完整的组合用法:

rsMain({=> /* 注册窗口类、创建窗口 */ }, mode: RunMode.SysThreadAndAsyn) // 主线程继续执行摄像头采集逻辑 let camera = CameraManager() if(camera.initialize()){ if(camera.loadDevices() && camera.deviceCount > 0){ let fmts = camera.getDeviceFormats(0) if(fmts.size > 0 && camera.select(0, fmts[0].size)){ while(!ruFinished()){ // UI 未结束期间持续采集 if(let Some(frame) <- camera.frameLock()){ mainWin.updateFrame(frame, fmts[0].size) camera.frameUnLock() } sleep(Duration.millisecond * 30) // 帧率 30fps } } camera.unselect() } camera.shutdown() } main(): Int64 { TestCall() rsEnd(0) // 仓颉中 SysThreadAndAsyn / SysThreadAndWait 模式下,调试时可能导致误报 return 0 }

全局上下文:rsInitialize / rsDestroy / rsGetContext / rsModRefToCurrDir

初始化与释放

函数签名说明
rsInitializepublic func rsInitialize(): ContextPtrRGF 绘制库全局初始化,返回全局上下文 Token。文档强调:本函数创建的上下文环境需要使用rsDestroy()方法释放
rsDestroypublic func rsDestroy(token: ContextPtr): BoolRGF 绘制库全局释放,返回是否成功释放

两者分别是对 FFI 函数rApiInitialize与rApiDestroy的薄封装(src/rgf_core/rgf_api.cj#L111-L119),在rsMain内部被自动调用;只有当你绕过rsMain自建消息循环时才需要手动成对调用。注意:CJMainThread模式下rsMain不会手动释放上下文("交给 GC 处理"),其余模式在消息循环退出后自动调用rsDestroy。

获取全局上下文

public func rsGetContext(): Option<Context>

返回当前全局上下文Context(doc/api/rgf.rgf_core/结构体/Context.md 中定义的技术上下文结构体),其内部持有 RGF 底层上下文指针与程序模块句柄hInst。由于rsMain未运行时上下文不存在,返回类型是Option<Context>(src/rgf_core/rgf_utils.cj#L192-L194)。rwRegister内部即通过context.getOrThrow().hInst获取程序实例句柄来完成窗口类注册。

模块路径配置

public func rsModRefToCurrDir(): Unit

"模块当前路径配置"——将当前程序的存储路径作为相对路径的起始点。底层调用rApiSetCurrentDirectoryToExe()(src/rgf_core/rgf_api.cj#L101)。测试工程中它总是出现在rsMain之前,用于保证后续以相对路径加载图片、字体、配置文件时不受"当前工作目录"影响。

系统定时器:rsCreateSysTimer / rsDestroySysTimer

RGF_CJ 提供基于 Win32Timer Queue(CreateTimerQueueTimer/DeleteTimerQueueTimer)的系统定时器,适合底层周期任务。

public func rsCreateSysTimer( callback: CFunc<(CPointer<Unit>, UInt8) -> Unit>, parameter: CPointer<Unit>, dueTime: UInt32, period: UInt32 ): RgfTimer
参数类型描述
callbackCFunc<(CPointer<Unit>, UInt8) -> Unit>定时回调(@CLambda 表达式,即 C 调用约定的函数指针)
parameterCPointer<Unit>回调函数的参数(透传给回调)
dueTimeUInt32首次执行等待时间(毫秒)
periodUInt32每次间隔时间(毫秒)

返回:成功返回定时器句柄RgfTimer(即HANDLE);失败抛出WinException。

销毁接口:

public func rsDestroySysTimer(timer: RgfTimer): Unit
参数类型描述
timerRgfTimer定时器句柄

⚠️ 文档特别提示:凡是本函数创建的定时器,都需要销毁。从实现看(src/rgf_core/rgf_utils.cj#L286-L316),rsCreateSysTimer通过wCreateTimerQueueTimer创建,标志位为WT_EXECUTEDEFAULT | WT_EXECUTELONGFUNCTION(允许长任务在专用线程池线程执行);rsDestroySysTimer调用wDeleteTimerQueueTimer,失败即抛WinException(wGetLastError())。因此务必在应用退出前成对销毁,避免句柄泄漏。

若你只是做 UI 动画级别的延时/周期任务,仓库还提供了更轻量的RTimer(基于std.sync.timer改进,支持after/once/repeat/repeatDuring/repeatTimes与 Burst 追赶模式),见 src/protected/timer/rgf_timer.cj 及 doc/api/rgf.rgf_utils/类/RTimer.md。

显示器查询:rsGetMonitorFromPoint 三个重载

rsGetMonitorFromPoint获取桌面坐标系下某点所在的显示器工作区(rcWork,即排除任务栏后的可用区域)宽高,返回Rect。共有三个重载,坐标来源不同:

public func rsGetMonitorFromPoint(x: Int32, y: Int32): Rect // 桌面坐标系下的 X/Y 轴值 public func rsGetMonitorFromPoint(pos: Point): Rect // 整数位置值 public func rsGetMonitorFromPoint(pos: FPoint): Rect // 浮点位置值

底层实现(src/rgf_core/rgf_utils.cj#L202-L231)依次调用:

  1. wEnumDisplayMonitors枚举所有显示器;
  2. wPtInRect判断点是否落在某显示器监视矩形内;
  3. wGetMonitorInfoW取得该显示器的MONITORINFO,取其rcWork(工作区)作为结果;找不到匹配显示器时抛WinException。

Point/FPoint重载最终都转换为(Int32, Int32)形式(FPoint直接截断浮点为整数)。典型场景:多显示器环境下把窗口定位到鼠标所在的显示器,或计算窗口居中坐标。

窗口类管理:rwRegister / rwUnregister

RGF_CJ 封装了 Win32 窗口类(WNDCLASS)的注册与注销,配合WinContext使用(窗口上下文类,见 doc/api/rgf.rgf_core/类/WinContext.md)。

public func rwRegister( ctxt: WinContext, className: String, style: UInt32, hbrBackground!: Int32 = 5 // 默认 NULL_BRUSH ): Bool
参数类型描述
ctxtWinContext窗口上下文,注册成功后内部会记录底层窗口类指针与类名
classNameString窗口类名
styleUInt32窗口风格(可用WinClassStyle枚举组合,如DblClks | HRedraw | VRedraw)
hbrBackgroundInt32窗口背景画刷,默认NULL_BRUSH(值为 5),即不自动擦背景

注销接口:

public func rwUnregister(ctxt: WinContext): Bool
参数类型描述
ctxtWinContext需要注销的窗口上下文

文档两条硬性提示:

  • 非本类注册的窗口类需要手动注入窗口过程函数,否则 RGF 窗口类无法捕获系统事件——即只有通过rwRegister注册的类,RGF 才能自动把 Win32 消息路由到绑定式事件体系;
  • 凡注册的窗口类都应该由rwUnregister注销。

实现细节(src/rgf_core/rgf_api.cj#L134-L163):rwRegister内部把className通过ruStrToWStr转成宽字符串,调用 FFIrApiRegisterWinClass,成功后把(className, ctxt)记录进全局staticWinClassMap;rwUnregister调用rApiUnregisterWinClass并从 map 中移除。这就是rsMain退出时rwClearAllWinClass能自动善后的依据。

窗口操作:批量移动、主窗口判断、句柄反查与默认过程

rwBatchMove —— 一次系统调用批量布局窗口

public func rwBatchMove(batch: Array<(RgfHwnd, Int32, Int32, Int32, Int32)>): Bool public func rwBatchMove(batch: Array<(WinPure, Int32, Int32, Int32, Int32)>): Bool public func rwBatchMove(batch: Array<(IWinMethod, Int32, Int32, Int32, Int32)>): Bool

batch为移动对象信息数组,每个元组含义统一为[0]: 目标;[1] X 坐标;[2] Y 坐标;[3] 宽度;[4] 高度,区别仅在于目标的表达形式:

重载元组第一个元素类型
重载一RgfHwnd(窗口句柄,UIntNative)
重载二WinPure(RGF 窗口核心类,见 doc/api/rgf.rgf_core/类/WinPure.md)
重载三IWinMethod(窗口常用方法接口,见 doc/api/rgf.rgf_core/接口/IWinMethod.md)

返回:是否全部成功。实现(src/rgf_core/rgf_utils.cj#L322-L358)采用 Win32 延迟定位三步曲:wBeginDeferWindowPos(数量)→ 逐项wDeferWindowPos(hdwp, ..., x, y, w, h, SWP_NOZORDER | SWP_NOOWNERZORDER)→wEndDeferWindowPos(hdwp)一次性提交。任何一步失败(返回 null)立即返回false。相比逐窗口MoveWindow,这种方式能减少多次重排闪烁,适合多窗口联动布局。

rwIsMainWin —— 判断主窗口

public func rwIsMainWin(rw: WinPure): Bool public func rwIsMainWin(hWnd: RgfHwnd): Bool public func rwIsMainWin(rw: IWinMethod): Bool

判断窗口是否为 RGF 主窗口(主窗口退出则消息循环跳出,参见rsMainInner中的haveMainWin条件)。三种重载的语义等价:句柄版直接与全局mainWinHwnd比较;WinPure版在状态达到GFState.Initialized后查底层;IWinMethod版委托给句柄版(src/rgf_core/rgf_utils.cj#L254-L275)。

rwGetRgfClass —— 句柄反查窗口类

public func rwGetRgfClass(rgfHwnd: RgfHwnd): Option<WinPure>

通过 RGF 窗口句柄反查其对应的WinPure窗口类实例(返回Option,句柄无效时为None),底层由gfClassFromHandlePermanent从 RGF 维护的句柄映射中查找(src/rgf_core/rgf_utils.cj#L185-L187)。可用于在事件回调中把收到的原生句柄还原为窗口对象。

rwDefWindowProc —— 默认窗口过程包装

public func rwDefWindowProc(hWnd: RgfHwnd, uMsg: UInt32, wParam: UInt64, lParam: Int64)

DefWindowProc的包装函数(src/rgf_core/rgf_utils.cj#L148-L150),将 RGF 句柄经ruToHwnd转换后转发给wDefWindowProcW。当你在自建窗口过程中处理了消息、需要把未处理消息交还系统默认处理时调用,四个参数与 Win32DefWindowProcW(hWnd, uMsg, wParam, lParam)一一对应。

字符串与编码互操作:ruStrToWStr / ruWStrToStr / ruFree / ruWStrlen / ruStrToCStr

Win32 API 普遍使用 UTF-16 宽字符(LPWSTR),而仓颉String是 UTF-8 语义字符串。RGF_CJ 提供一组编码转换工具,全部位于 src/rgf_core/rgf_api.cj:

函数签名说明
ruStrToWStrpublic func ruStrToWStr(str: String): LPWSTR仓颉字符串 → C 宽字符串(含编码转换)。本函数创建的字符串需要使用ruFree释放
ruWStrToStrpublic func ruWStrToStr(str: LPWSTR): StringC 宽字符串 → 仓颉字符串(含编码转换),内部自动释放中转缓冲
ruFreepublic func ruFree(cPtr: CPointer<Unit>): Unit释放宽字符串,专门用于释放ruStrToWStr申请的内存空间
ruWStrlenpublic func ruWStrlen(wcharPtr: LPWSTR): UInt32获取 C 宽字符串长度(宽字符数),底层调用rApiWcharslen
ruStrToCStrpublic func ruStrToCStr<T>(str: String, callback: (cStr: LPWSTR) -> T)字符串编码转换与自动释放:转换 → 执行回调 → 自动释放,免去手动ruFree

内存管理要点:ruStrToWStr的实现是"mallocCString→rApiCharStrToWcharStr转换 →free临时 CString",返回的宽字符串指针由 RGF 底层分配;ruWStrToStr反向转换时会自动释放内部临时缓冲。因此成对记忆是:

  • 手动模式:let w = ruStrToWStr(str)… 用完后ruFree(CPointer<Unit>(w));
  • 自动模式:ruStrToCStr(str) { cStr => /* 使用 cStr */ },回调返回后自动释放(内部调用rApiReleaseWcharStr)。

指针与句柄互操作:ruUllToPtr / ruLlToPtr / ruToHwnd / ruToHdc

RGF_CJ 的 RGF 侧句柄(RgfHwnd/RgfHdc)本质是UIntNative整数,而 Win32 FFI 需要CPointer/HWND/HDC,因此提供两组转换:

// 数值 ↔ 裸指针 public func ruUllToPtr(ptrVal: UIntNative): CPointer<Unit> // 无符号数值 → C 侧指针(标注 @FastNative) public func ruLlToPtr(ptrVal: IntNative): CPointer<Unit> // 有符号数值 → C 侧指针 // RGF 句柄 ↔ Win32 句柄 public func ruToHwnd(rgfHwnd: RgfHwnd): HWND // 内部实现:HWND(ruUllToPtr(rgfHwnd)) public func ruToHdc(rgfHdc: RgfHdc): HDC // 内部实现:HDC(ruUllToPtr(rgfHdc))
  • ruUllToPtr:用于明确指针地址值时,将地址恢复为指针(如从lParam/wParam中解出的句柄值还原成指针);
  • ruLlToPtr:有符号版本,文档标注"极少数情况下使用";
  • ruToHwnd/ruToHdc:是rwBatchMove、rwDefWindowProc、rwIsMainWin等窗口函数的公共底层(src/rgf_core/rgf_utils.cj#L169-L179)。

底层内存工具:ruSafeCStruct / ruRedefBit

这两组工具面向需要直接操作 C 结构体内存的场景。

ruSafeCStruct —— CType 内存的自动创建与释放

public func ruSafeCStruct<T, RT>(count: Int64, callback: (data: CPointer<T>) -> RT) where T <: CType

自动创建count个T类型(T <: CType,即 C 兼容结构体)的连续内存,传入回调使用,回调返回后自动LibC.free(src/rgf_core/rgf_utils.cj#L138-L143)。典型场景:构造RECT、MONITORINFO、MSG等 Win32 结构体传给 FFI 时无需手动管理内存。

ruRedefBit —— 比特级数据重解释

public func ruRedefBit<T1, T2>(v: T1): T2 where T1 <: LittleEndianOrder<T1> & CType, T2 <: LittleEndianOrder<T2> & CType

从内存比特层面重解释数据值(类似 C++ 的联合体 type-punning)。实现思路(src/rgf_core/rgf_utils.cj#L156-L161):取T1/T2中较大的尺寸分配字节缓冲,v.writeLittleEndian(buffer)写入,再T2.readLittleEndian(buffer)读出,即完成"同一段比特,换个类型解释"。要求两个类型都实现LittleEndianOrder且为CType。可用于在整数/浮点/位域结构之间互转,例如把UInt32重新解释为浮点或位域结构。

全局函数的错误处理与最佳实践

异常机制

RGF_CJ 的全局函数在底层失败时统一抛出WinException(Windows 系统相关异常,见 doc/api/rgf.rgf_core/异常/WinException.md),错误码来自wGetLastError()。触发点包括:

  • rsCreateSysTimer创建失败;
  • rsDestroySysTimer注销失败;
  • rsGetMonitorFromPoint未找到点所在显示器;
  • rsMain重复初始化(抛普通Exception,文案rgfErrorMainUiThreadinited);
  • 系统线程创建失败等。

生命周期配对清单

成对关系说明
rsInitialize↔rsDestroy手动自建消息循环时成对使用;rsMain内部已自动处理
rsMain(create, destroy)create 中建资源,destroy 中rwUnregister等
rsCreateSysTimer↔rsDestroySysTimer创建的定时器都必须销毁
ruStrToWStr↔ruFree手动转换必须手动释放;或用ruStrToCStr自动释放
rwRegister↔rwUnregister注册的窗口类都应由rwUnregister注销

使用建议

  1. 入口总是先rsModRefToCurrDir(),再进rsMain,保证相对路径资源加载稳定(测试工程均如此);
  2. 单纯 UI 动画计时优先用RTimer,系统级定时任务才用rsCreateSysTimer;
  3. 多窗口同时移动用rwBatchMove一次提交,避免逐窗移动的闪烁;
  4. SysThreadAndAsyn模式下务必用ruFinished()协调主线程与 UI 线程的退出时序,并在main末尾rsEnd(0)兜底结束进程(调试状态下可避免误报)。

总结

rgf.rgf_core的全局函数构成了 RGF_CJ 应用的"地基层":rsMain+RunMode定义应用形态与线程模型,rsInitialize/rsDestroy/rsGetContext管理全局上下文,rsCreateSysTimer/rsDestroySysTimer提供系统定时能力,rsGetMonitorFromPoint服务多显示器布局,rwRegister/rwUnregister/rwBatchMove/rwIsMainWin等封装窗口类与窗口管理,ru*系列则打通仓颉与 Win32 之间的字符串、指针和句柄互操作。结合 test/CT/base/src/main.cj 与 test/HLT/camera/src/main.cj 两个参考工程,你可以快速搭建自己的 RGF_CJ 桌面应用骨架。

  • 图形学
  • 桌面应用

【免费下载链接】RGF_CJ

RGF是仓颉Windows系统下的通用渲染框架(兼应用开发框架)。RGF仓颉版(后续简称"RGF")基于RGF(C/C++版)封装优化而来。RGF为开发者提供轻量化、安全、高性能以及高度一致性的2D渲染能力以及常用的桌面应用开发工具,并且提供对接Direct3D的相关接口,以满足开发者对3D画面渲染的需求。在Windows开发方面,RGF在子包内也提供开箱即用的Windows API,确保熟悉Win32的开发者快速上手。此外,RGF还提供一些常用功能的封装(如XAudio2、MF),以辅助开发者实现音频、摄像头等扩展功能的管理。

项目地址:https://gitcode.com/Cangjie-SIG/RGF_CJ
点击查看免费下载

相关推荐

上一篇:BoxPacker快速上手:用PHP算出每件商品进哪个箱子的装箱方案
下一篇:IINA 免费开源 macOS 视频播放器完整上手指南:格式全通、字幕自动配、音乐模式一键切换

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 3:04:28

C++手写数据结构实战:动态数组、哈希表、AVL树与图算法

简介&#xff1a;《Implementing Useful Algorithms in C》由Dmytro Kedyk撰写&#xff0c;面向具备一定C基础、希望深入掌握算法设计与工程实现的开发者与计算机专业学生。全书从算法正确性证明、渐进记法与机器模型等基本原则切入&#xff0c;系统讲解数据类型选择、内存管理…

作者头像 李华
网站建设 2026/10/14 3:03:02

Google地球网页版:WebGL渲染、瓦片加载与API嵌入实战

简介&#xff1a;这份资源面向对地理信息系统与Web前端开发感兴趣的初学者及开发者&#xff0c;提供一份可直接在浏览器中运行的Google地球网页版实现&#xff0c;帮助理解HTML与JavaScript如何驱动交互式3D地球模型。压缩包内共1个文件&#xff0c;为单个html页面&#xff0c;…

作者头像 李华
网站建设 2026/10/14 3:02:49

Apache OpenDAL DBFS 服务接入与配置实战指南

数据存储后端 【免费下载链接】opendal Apache OpenDAL: One Layer, All Storage. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/op/opendal 点击查看 免费下载 本篇指南围绕 Apache OpenDAL 的 opendal-service-dbfs 服务实现展开&#xff0c;讲解如何通过统一的数据…

作者头像 李华
网站建设 2026/10/14 3:01:01

Python代码格式化工具Black:终结团队风格之争的实战指南

代码格式化这件事&#xff0c;我一度觉得是程序员的“信仰战争”。团队里最浪费时间的几件事&#xff0c;开需求评审算一个&#xff0c;讨论缩进、引号、换行风格也能算一个——有人坚持单引号&#xff0c;有人力推双引号&#xff0c;有人写函数参数像掏口袋一样一个一个往外掏…

作者头像 李华