Chapter 122 · XUI 框架架构

上下文创建

xuiCreate / xuiDestroy 管理 XUI 上下文生命周期,xuiUpdate 驱动帧更新,xuiSetViewportSize 同步窗口尺寸。

122

概念

xui_context 是 XUI 的核心对象,管理所有控件、样式、资源、输入状态。 一个应用通常只有一个 context(多窗口可多个)。
每帧流程:Input → Update → Layout → Render。

API 速查

函数说明
int xuiCreate(xui_context* ppContext)创建上下文
void xuiDestroy(xui_context pContext)销毁上下文
int xuiUpdate(xui_context pContext, float fDelta)帧更新(动画/输入)
int xuiSetViewportSize(xui_context pContext, float fWidth, float fHeight)设置视口尺寸
xui_vec2_t xuiGetViewportSize(xui_context pContext)获取视口尺寸
int xuiSetVirtualDpi(xui_context pContext, float fDpiScale)设置 DPI 缩放
int xuiLayout(xui_context pContext)执行布局计算
int xuiRender(xui_context pContext, xui_surface pTarget, const xui_rect_i_t* pRects, int iRectCount)渲染到目标

编译本章示例

gcc -O2 -I. -o ch122.exe ch122_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch122.exe

示例:完整帧循环

// 初始化
xui_context pCtx;
xuiCreate(&pCtx);
xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(pCtx, &tXgeProxy);
xuiSetViewportSize(pCtx, 1280, 720);
xuiSetVirtualDpi(pCtx, 1.0f);

// 每帧循环
void onFrame(void) {
    float dt = xgeGetDelta();

    // 1. 转发输入(见第 191 章)
    forwardInput(pCtx);

    // 2. 更新(动画、状态机)
    xuiUpdate(pCtx, dt);

    // 3. 布局(计算控件位置/大小)
    xuiLayout(pCtx);

    // 4. 渲染(仅脏区域)
    if (xuiHasDamage(pCtx)) {
        xui_rect_i_t rects[16];
        int n = xuiGetDamageRects(pCtx,
            rects, 16);
        xuiRender(pCtx, NULL, rects, n);
        xuiClearDamage(pCtx);
    }
}

// 窗口大小变化时
xuiSetViewportSize(pCtx, newW, newH);

// 退出
xuiDestroy(pCtx);

完整代码

将以下代码保存为 ch122_main.c,编译后运行即可看到完整 XUI 帧循环:

#include "xge.h"
#include "xui.h"

static xui_context g_pCtx;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);

    float dt = xgeGetDelta();
    xuiUpdate(g_pCtx, dt);
    xuiLayout(g_pCtx);

    // 仅在有脏区域时渲染
    if (xuiHasDamage(g_pCtx)) {
        xuiRender(g_pCtx, NULL, NULL, 0);
    }
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch122 - XUI Context";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);

    // 创建上下文 + 设置代理 + 视口
    xuiCreate(&g_pCtx);
    extern const xui_proxy_t tXgeProxy;
    xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
    xuiSetViewportSize(g_pCtx, 800, 600);
    xuiSetVirtualDpi(g_pCtx, 1.0f);

    xgeRun(onFrame, NULL);

    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • xuiCreate + xuiSetProxy:创建上下文并绑定渲染后端,这是所有 XUI 程序的第一步。
  • xuiSetViewportSize:设置逻辑视口尺寸,布局系统依此计算控件位置。
  • xuiSetVirtualDpi:DPI 缩放因子,高分屏设为 1.5 或 2.0。
  • 帧循环顺序:Update(动画/状态) → Layout(布局) → Render(渲染),顺序不可调换。
  • xuiHasDamage:无脏区域时跳过渲染,节省 GPU 开销。

要点与陷阱

  • 帧顺序:必须 Input → Update → Layout → Render。
  • Delta:xuiUpdate 需要帧间隔(秒),驱动动画。
  • DPI:高 DPI 屏幕设置 DpiScale(如 1.5/2.0)。
  • 脏渲染:HasDamage 为 false 时跳过渲染,节省 GPU。

进阶练习

  1. 实现按需渲染:无交互时不渲染,节省功耗。
  2. 多 context:主窗口 + 浮动工具窗各自独立。
上下文创建效果
图:上下文创建渲染效果