Chapter 159 · XUI 弹出层与反馈

MessageBox 消息框

MessageBox 模态/非模态对话框,支持图标类型、标准按钮组合、自定义按钮、结果回调。

159

概念

MessageBox 是标准对话框,用于确认、警告、错误提示:
• 独立句柄:使用 xui_msgbox 类型,非 widget 树节点
• 类型图标:Info / Warning / Error / Question
• 按钮组合:OK / OK+Cancel / Yes+No / Yes+No+Cancel
• 自定义按钮:任意文本 + 值,灵活适配业务
• 模态:阻塞底层交互直到关闭

API 速查

函数说明
int xuiMsgBoxCreate(xui_context pCtx, xui_msgbox* ppBox, const xui_msgbox_desc_t* pDesc)创建消息框
void xuiMsgBoxDestroy(xui_msgbox pBox)销毁
int xuiMsgBoxSetText(xui_msgbox pBox, const char* sTitle, const char* sMessage)标题与内容
int xuiMsgBoxSetType(xui_msgbox pBox, int iType)图标类型
int xuiMsgBoxSetButtons(xui_msgbox pBox, int iButtons)标准按钮组合
int xuiMsgBoxSetCustomButtons(xui_msgbox pBox, const xui_msgbox_button_t* pBtns, int iCount)自定义按钮
int xuiMsgBoxSetResult(xui_msgbox pBox, xui_msgbox_result_proc onResult, void* pUser)结果回调
int xuiMsgBoxSetModal(xui_msgbox pBox, int bModal)模态模式
int xuiMsgBoxSetOpen(xui_msgbox pBox, int bOpen)打开/关闭

编译本章示例

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

示例:确认删除对话框

xui_msgbox_desc_t desc = { 0 };

xui_msgbox pBox;
xuiMsgBoxCreate(pCtx, &pBox, &desc);

xuiMsgBoxSetText(pBox, "确认删除",
    "确定要删除选中的 3 个文件吗?此操作不可撤销。");
xuiMsgBoxSetType(pBox, 1);       // Warning
xuiMsgBoxSetButtons(pBox, 2);    // Yes + No
xuiMsgBoxSetModal(pBox, 1);
xuiMsgBoxSetResult(pBox, OnMsgBoxResult, NULL);

// 显示
xuiMsgBoxSetOpen(pBox, 1);

static void OnMsgBoxResult(xui_msgbox pBox, int iButton, void* pUser) {
    if (iButton == 1) {  // Yes
        DoDeleteFiles();
    }
    xuiMsgBoxSetOpen(pBox, 0);
}

完整代码

将以下代码保存为 ch159_main.c,编译后运行即可看到消息框效果:

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

static xui_context g_pCtx;
static xui_msgbox g_pBox;

static void onResult(xui_msgbox pBox, int iBtn, void* p) {
    (void)p;
    printf("用户点击按钮: %d\n", iBtn);
    xuiMsgBoxSetOpen(pBox, 0);
}

static void onBtnClick(xui_widget pW, void* p) {
    (void)pW; (void)p;
    xuiMsgBoxSetOpen(g_pBox, 1);
}

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    float mx, my;
    xgeMouseGet(&mx, &my);
    xuiInputPointerMove(g_pCtx, mx, my);
    if (xgeMouseDown(XGE_MOUSE_LEFT))
        xuiInputPointerDown(g_pCtx, 0);
    else
        xuiInputPointerUp(g_pCtx, 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 = "ch159 - MessageBox";
    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_button_desc_t btn = { 0 };
    btn.sText = "删除文件";
    xui_widget pBtn;
    xuiButtonCreate(g_pCtx, &pBtn, &btn);
    xuiWidgetSetRect(pBtn, (xui_rect_t){0, 0, 150, 36});
    xuiButtonSetClick(pBtn, onBtnClick, NULL);
    xuiWidgetAddChild(pRoot, pBtn);

    /* 创建消息框 */
    xui_msgbox_desc_t mbd = { 0 };
    xuiMsgBoxCreate(g_pCtx, &g_pBox, &mbd);
    xuiMsgBoxSetText(g_pBox, "确认删除", "确定要删除选中的文件吗?");
    xuiMsgBoxSetType(g_pBox, 1);
    xuiMsgBoxSetButtons(g_pBox, 2);
    xuiMsgBoxSetModal(g_pBox, 1);
    xuiMsgBoxSetResult(g_pBox, onResult, NULL);

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

代码讲解

  • 独立句柄:MessageBox 使用 xui_msgbox 类型,不加入控件树。
  • SetType=1:Warning 图标,0=Info 2=Error 3=Question。
  • SetButtons=2:Yes+No 组合,结果回调返回按钮索引。
  • Modal:模态模式显示半透明遮罩,阻塞底层交互。

要点与陷阱

  • 非 Widget:MessageBox 使用独立句柄 xui_msgbox,不加入控件树。
  • 生命周期:Create 后可反复 SetOpen(1/0) 显示/隐藏,Destroy 释放。
  • 自定义按钮:xui_msgbox_button_t 包含文本 + 值 + 是否默认。
  • 模态阻塞:模态模式下底层控件不可交互,适合确认操作。

进阶练习

  1. 多按钮对话框:保存 / 不保存 / 取消 三按钮退出确认。
  2. 错误详情框:自定义按钮"查看详情"展开堆栈信息。
MessageBox 消息框效果
图:MessageBox 消息框渲染效果