Chapter 145 · XUI 容器与导航

Scrollbar 滚动条

XUI 滚动条内嵌于 ScrollView / TreeView / TableView 等可滚动控件,通过策略、模式、度量、颜色进行定制。

145

概念

XUI 没有独立的 Scrollbar 控件——滚动条作为可滚动控件的内部组件存在。核心配置项:
• Policy:显示策略(始终显示 / 自动 / 隐藏)
• Mode:渲染模式(经典带按钮 / 简约覆盖式)
• Metrics:滚动条宽度、最小滑块尺寸、按钮尺寸
• Colors:轨道色、滑块色、悬停/按下/焦点/禁用色

API 速查

函数说明
int xuiScrollViewSetScrollbarPolicy(xui_widget pW, int iPX, int iPY)X/Y 轴策略
int xuiScrollViewGetScrollbarPolicy(xui_widget pW, int* pPX, int* pPY)查询策略
int xuiScrollViewSetScrollbarMode(xui_widget pW, int iMode)滚动条模式
int xuiScrollViewSetMetrics(xui_widget pW, float fSize, float fMinThumb, float fBtn)度量参数
int xuiScrollViewSetColors(xui_widget pW, ...)滚动条颜色
int xuiScrollViewSetButtonColors(xui_widget pW, uint32_t iBtn, uint32_t iIcon)按钮颜色
int xuiScrollViewSetCornerMode(xui_widget pW, int iMode)角落模式
int xuiScrollViewSetCornerColors(xui_widget pW, uint32_t iCorner, uint32_t iGrip)角落颜色

编译本章示例

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

示例:自定义滚动条外观

// 策略:X 轴隐藏,Y 轴自动
xuiScrollViewSetScrollbarPolicy(pScroll, 0, 1);

// 简约模式(覆盖式,无按钮)
xuiScrollViewSetScrollbarMode(pScroll, 1);

// 度量:宽 8px,最小滑块 30px,按钮 0
xuiScrollViewSetMetrics(pScroll, 8.0f, 30.0f, 0.0f);

// 颜色:Track / Thumb / Hover / Active / Focus / Disabled
xuiScrollViewSetColors(pScroll,
    0x00000000,  // 透明轨道
    0x80FFFFFF,  // 半透明白色滑块
    0xC0FFFFFF,  // 悬停
    0xFFFFFFFF,  // 按下
    0x804FD8C2,  // 焦点
    0x40FFFFFF); // 禁用

完整代码

将以下代码保存为 ch145_main.c,编译后运行即可看到自定义滚动条效果:

#include "xge.h"
#include "xui.h"
#include <stdio.h>

static xui_context g_pCtx;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    float mx, my;
    xgeMouseGet(&mx, &my);
    xuiInputPointerMove(g_pCtx, mx, my);
    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 = "ch145 - Scrollbar";
    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);

    /* 根容器 */
    xui_widget pRoot;
    xuiWidgetCreate(g_pCtx, &pRoot);
xuiWidgetSetLayoutType(pRoot, XUI_LAYOUT_COLUMN);
    xuiWidgetSetRect(pRoot, (xui_rect_t){0, 0, 800, 600});
    xuiWidgetSetPadding(pRoot, 40, 40, 40, 40);
    xuiSetRootWidget(g_pCtx, pRoot);

    /* 滚动视图 + 自定义滚动条 */
    xui_scroll_view_desc_t svd = { 0 };
    xui_widget pScroll;
    xuiScrollViewCreate(g_pCtx, &pScroll, &svd);
    xuiWidgetSetRect(pScroll, (xui_rect_t){0, 0, 400, 500});
    xuiScrollViewSetContentSize(pScroll, 400, 3000);
    xuiScrollViewSetWheelStep(pScroll, 40.0f);
    xuiWidgetAddChild(pRoot, pScroll);

    /* 滚动条外观配置 */
    xuiScrollViewSetScrollbarPolicy(pScroll, 0, 2); // Y轴始终显示
    xuiScrollViewSetScrollbarMode(pScroll, 1); // 覆盖式
    xuiScrollViewSetMetrics(pScroll, 8.0f, 30.0f, 0.0f);
    xuiScrollViewSetColors(pScroll,
        0x00000000, 0x80FFFFFF, 0xC0FFFFFF,
        0xFFFFFFFF, 0x804FD8C2, 0x40FFFFFF);

    /* 填充内容 */
    xui_widget pContent = xuiScrollViewGetContentWidget(pScroll);
    xuiWidgetSetLayout(pContent, XUI_LAYOUT_COLUMN);
    static char buf[80][32];
    for (int i = 0; i < 80; i++) {
        sprintf(buf[i], "Row %d", i + 1);
        xui_label_desc_t lb = { 0 };
        lb.sText = buf[i];
        xui_widget pLb;
        xuiLabelCreate(g_pCtx, &pLb, &lb);
        xuiWidgetSetRect(pLb, (xui_rect_t){0, 0, 380, 34});
        xuiWidgetAddChild(pContent, pLb);
    }

    xgeRun(onFrame, NULL);
    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • Policy=2:Y 轴始终显示滚动条,方便观察自定义外观。
  • Mode=1:覆盖式滚动条浮于内容上方,不占布局空间。
  • Metrics:宽 8px、最小滑块 30px、无按钮,简洁风格。
  • Colors:透明轨道 + 半透明白色滑块,悬停/按下时增强不透明度。

要点与陷阱

  • Policy 值:0 = 隐藏,1 = 自动(内容溢出时显示),2 = 始终显示。
  • Mode:0 = 经典(占布局空间),1 = 覆盖(浮于内容上方)。
  • MinThumbSize:防止内容极长时滑块过小难以拖拽。
  • 通用性:TreeView / TableView / Canvas 均有同名滚动条 API。

进阶练习

  1. 实现 macOS 风格覆盖式滚动条:Mode=1 + 透明轨道 + 圆角滑块。
  2. 双向滚动时配置 CornerMode 处理角落区域。
Scrollbar 滚动条效果
图:Scrollbar 滚动条渲染效果