Chapter 126 · XUI 框架架构

布局系统:Manual / Overlay

Manual 布局手动指定每个子控件的位置和大小;Overlay 布局让所有子控件堆叠在同一区域。

126

概念

XUI 布局系统决定父容器如何安排子控件的位置和大小:
• MANUAL (0):子控件位置/大小完全由开发者设定(绝对定位)
• OVERLAY (1):所有子控件填满父容器同一区域(层叠)
Manual 适合游戏 HUD、固定布局;Overlay 适合背景+前景叠加。

API 速查

宏/函数说明
XUI_LAYOUT_MANUAL手动布局 (0)
XUI_LAYOUT_OVERLAY叠加布局 (1)
int xuiWidgetSetLayout(xui_widget pWidget, int iLayout)设置布局模式
int xuiWidgetSetRect(xui_widget pWidget, xui_rect_t tRect)设置位置/大小
xui_rect_t xuiWidgetGetRect(xui_widget pWidget)获取位置/大小
XUI_LAYOUT_UNBOUNDED无约束尺寸 (1073741824.0)

编译本章示例

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

示例:HUD + 背景叠加

// Manual 布局:游戏 HUD
xuiWidgetSetLayout(pRoot, XUI_LAYOUT_MANUAL);

// 手动定位每个 HUD 元素
xuiWidgetSetRect(pHealthBar,
    (xui_rect_t){ 20, 20, 200, 24 });
xuiWidgetSetRect(pManaBar,
    (xui_rect_t){ 20, 50, 200, 24 });
xuiWidgetSetRect(pMinimap,
    (xui_rect_t){ 1080, 20, 180, 180 });

// Overlay 布局:背景 + 内容叠加
xuiWidgetSetLayout(pCard, XUI_LAYOUT_OVERLAY);

// 所有子控件自动填满父区域
xuiWidgetAddChild(pCard, pBgImage);
xuiWidgetAddChild(pCard, pGradient);
xuiWidgetAddChild(pCard, pText);
// 三者重叠显示,后添加的在上层

完整代码

将以下代码保存为 ch126_main.c,编译后运行即可看到 Manual 和 Overlay 布局效果:

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

static xui_context g_pCtx;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    xuiUpdate(g_pCtx, xgeGetDelta());
    xuiLayout(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  = "ch126 - Manual/Overlay";
    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);

    // 根控件使用 Manual 布局
    xui_widget pRoot;
    xuiWidgetCreate(g_pCtx, &pRoot);
    xuiWidgetSetLayout(pRoot, XUI_LAYOUT_MANUAL);

    // HUD 元素:绝对定位
    xui_widget pHealth, pMana;
    xuiWidgetCreate(g_pCtx, &pHealth);
    xuiWidgetCreate(g_pCtx, &pMana);
    xuiWidgetSetRect(pHealth,
        (xui_rect_t){ 20, 20, 200, 24 });
    xuiWidgetSetRect(pMana,
        (xui_rect_t){ 20, 50, 200, 24 });
    xuiWidgetAddChild(pRoot, pHealth);
    xuiWidgetAddChild(pRoot, pMana);

    // Overlay 卡片:层叠显示
    xui_widget pCard, pBg, pText;
    xuiWidgetCreate(g_pCtx, &pCard);
    xuiWidgetSetLayout(pCard, XUI_LAYOUT_OVERLAY);
    xuiWidgetSetRect(pCard,
        (xui_rect_t){ 500, 200, 250, 300 });
    xuiWidgetCreate(g_pCtx, &pBg);
    xuiWidgetCreate(g_pCtx, &pText);
    xuiWidgetAddChild(pCard, pBg);
    xuiWidgetAddChild(pCard, pText);
    xuiWidgetAddChild(pRoot, pCard);

    xgeRun(onFrame, NULL);

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

代码讲解

  • XUI_LAYOUT_MANUAL:子控件位置完全由 SetRect 决定,适合 HUD 固定布局。
  • XUI_LAYOUT_OVERLAY:所有子控件填满父区域并层叠,后添加的在上层。
  • xuiWidgetSetRect:设置控件的局部坐标和尺寸(相对于父控件)。
  • 组合使用:根用 Manual,内部卡片用 Overlay,实现复杂布局。

要点与陷阱

  • Manual:子控件 SetRect 是相对于父控件的局部坐标。
  • Overlay:子控件忽略自身 Rect,全部填满父区域。
  • UNBOUNDED:表示"不限制",用于 ScrollView 内容区。
  • 层级:Overlay 中后添加的子控件绘制在上层。

进阶练习

  1. 用 Manual 实现可拖拽窗口:拖动改变 Rect。
  2. 用 Overlay 实现卡片组件:图片 + 渐变 + 文字叠加。
布局系统:Manual / Overlay效果
图:布局系统:Manual / Overlay渲染效果