Chapter 133 · XUI 基础控件

Button 按钮

Button 支持语义色、图标布局、九宫格背景、徽章角标与可选中模式,是最常用的交互控件。

133

概念

Button 是触发操作的交互控件:
• 语义色:Default/Primary/Success/Warning/Danger 预设
• 图标:支持左/右/上/下/仅图标布局
• 徽章:右上角小红点或数字角标
• 可选中:SetSelectable 后变为 Toggle 按钮
• 九宫格:SetPatch 用图片做各态背景

API 速查

函数说明
int xuiButtonCreate(xui_context pCtx, xui_widget* ppW, const xui_button_desc_t* pDesc)创建按钮
int xuiButtonSetClick(xui_widget pW, xui_button_click_proc onClick, void* pUser)点击回调
int xuiButtonSetText(xui_widget pW, const char* sText)设置文本
int xuiButtonSetSemantic(xui_widget pW, int iSemantic)语义色
int xuiButtonSetIcon(xui_widget pW, xui_surface pSurf, xui_rect_t tSrc)设置图标
int xuiButtonSetIconLayout(xui_widget pW, int iPlace, float fSize, float fGap)图标布局
int xuiButtonSetColors(xui_widget pW, uint32_t iN, uint32_t iH, uint32_t iA, uint32_t iF, uint32_t iD)五态背景色
int xuiButtonSetSelectable(xui_widget pW, int bSelectable)可选中模式
int xuiButtonSetSelected(xui_widget pW, int bSelected)选中状态
int xuiButtonSetBadgeVisible(xui_widget pW, int bVisible)徽章显隐
int xuiButtonSetPatch(xui_widget pW, uint32_t iState, const xui_nine_patch_t* pPatch)九宫格背景

编译本章示例

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

示例:图标按钮 + 徽章

static void OnSave(xui_widget pW, void* pUser) {
    printf("Saving...\n");
}

xui_button_desc_t desc = { 0 };
desc.sText = "保存";

xui_widget pBtn;
xuiButtonCreate(pCtx, &pBtn, &desc);
xuiButtonSetClick(pBtn, OnSave, NULL);
xuiButtonSetSemantic(pBtn, 1); // Primary

// 图标在文字左侧
xuiButtonSetIcon(pBtn, pIconSurf, tIconSrc);
xuiButtonSetIconLayout(pBtn, 0, 16.0f, 6.0f);

// 显示徽章(未读提示)
xuiButtonSetBadgeVisible(pBtn, 1);
xuiButtonSetBadgeSize(pBtn, 8.0f);

xuiWidgetAddChild(pToolbar, pBtn);

完整代码

将以下代码保存为 ch133_main.c,编译后运行即可看到按钮点击效果:

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

static xui_context g_pCtx;

static void OnSave(xui_widget pW, void* pUser) {
    (void)pW; (void)pUser;
    printf("Save clicked!\n");
}

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    float mx, my;
    xgeMouseGet(&mx, &my);
    xuiInputPointerMove(g_pCtx, mx, my, 0);
    if (xgeMouseDown(XGE_MOUSE_LEFT))
        xuiInputPointerDown(g_pCtx, mx, my, 0, 1);
    if (!xgeMouseDown(XGE_MOUSE_LEFT) /* 释放边沿建议改用事件 */)
        xuiInputPointerUp(g_pCtx, mx, my, 0, 0);
    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  = "ch133 - Button";
    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_button_desc_t desc = { 0 };
    desc.sText = "Save";
    xui_widget pBtn;
    xuiButtonCreate(g_pCtx, &pBtn, &desc);
    xuiButtonSetClick(pBtn, OnSave, NULL);
    xuiButtonSetSemantic(pBtn, 1);
    xuiButtonSetBadgeVisible(pBtn, 1);
    xuiWidgetSetRect(pBtn,
        (xui_rect_t){ 300, 260, 200, 50 });

    xgeRun(onFrame, NULL);

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

代码讲解

  • xuiButtonCreate:创建按钮控件,通过 desc 设置初始文本。
  • xuiButtonSetClick:注册点击回调,用户点击时触发。
  • xuiButtonSetSemantic:设置语义色(Primary/Success/Danger 等)。
  • xuiButtonSetBadgeVisible:显示右上角徽章(未读提示)。
  • 输入注入:每帧将鼠标状态转发给 XUI 事件系统。

要点与陷阱

  • Semantic:预设语义色,无需手动 SetColors。
  • IconLayout:placement 0=左 1=右 2=上 3=下 4=仅图标。
  • Selectable:选中后 IsSelected 返回 true,再次点击取消。
  • Patch:按状态设置不同九宫格图片,优先级高于纯色。

进阶练习

  1. 工具栏按钮组:多个 Selectable 按钮实现互斥选中。
  2. 消息按钮:徽章显示未读数,点击后清零。
Button 按钮效果
图:Button 按钮渲染效果