Chapter 140 · XUI 基础控件

TextEdit 多行编辑

TextEdit 多行文本编辑器,支持自动换行、行号、选区、查找替换、撤销重做与滚动。

140

概念

TextEdit 是功能完整的多行编辑器:
• WordWrap:自动换行
• LineNumbers:行号侧栏
• Find/Replace:内置查找替换面板
• Undo/Redo:操作历史
• Scroll:内置水平/垂直滚动条

API 速查

函数说明
int xuiTextEditCreate(xui_context pCtx, xui_widget* ppW, const xui_text_edit_desc_t* pDesc)创建多行编辑
int xuiTextEditSetText(xui_widget pW, const char* sText)设置文本
const char* xuiTextEditGetText(xui_widget pW)获取文本
int xuiTextEditSetWordWrap(xui_widget pW, int bWrap)自动换行
int xuiTextEditSetLineNumbers(xui_widget pW, int bVisible, float fWidth)行号
int xuiTextEditSetSelection(xui_widget pW, int iStart, int iEnd)设置选区
int xuiTextEditFindNext(xui_widget pW, const xui_find_options_t* pOpt)查找下一个
int xuiTextEditReplaceAll(xui_widget pW, const xui_find_options_t* pOpt, int* pCount)全部替换
int xuiTextEditUndo(xui_widget pW)撤销
int xuiTextEditRedo(xui_widget pW)重做
int xuiTextEditGetLineCount(xui_widget pW)行数
int xuiTextEditSetScroll(xui_widget pW, float fX, float fY)滚动位置

编译本章示例

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

示例:日志查看器

xui_text_edit_desc_t desc = { 0 };
xui_widget pEdit;
xuiTextEditCreate(pCtx, &pEdit, &desc);

// 只读 + 行号 + 自动换行
xuiTextEditSetReadonly(pEdit, 1);
xuiTextEditSetLineNumbers(pEdit, 1, 48.0f);
xuiTextEditSetWordWrap(pEdit, 1);

// 追加日志
char buf[4096];
snprintf(buf, sizeof(buf), "%s[INFO] Frame %d\n",
    xuiTextEditGetText(pEdit), iFrame);
xuiTextEditSetText(pEdit, buf);

// 滚动到底部
xuiTextEditSetScroll(pEdit, 0,
    xuiTextEditGetLineCount(pEdit) * 20.0f);

// 查找功能
xui_find_options_t opt = { .sPattern = "ERROR" };
xuiTextEditFindNext(pEdit, &opt);

完整代码

将以下代码保存为 ch140_main.c,编译后运行即可看到多行文本编辑器:

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

static xui_context g_pCtx;
static xui_widget  g_pEdit;
static int         g_nFrame = 0;

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);

    // 每 60 帧追加一行日志
    if (++g_nFrame % 60 == 0) {
        char buf[4096];
        snprintf(buf, sizeof(buf),
            "%s[INFO] Frame %d\n",
            xuiTextEditGetText(g_pEdit),
            g_nFrame);
        xuiTextEditSetText(g_pEdit, buf);
    }

    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  = "ch140 - TextEdit";
    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_text_edit_desc_t desc = { 0 };
    xuiTextEditCreate(g_pCtx, &g_pEdit, &desc);
    xuiTextEditSetLineNumbers(g_pEdit, 1, 48.0f);
    xuiTextEditSetWordWrap(g_pEdit, 1);
    xuiWidgetSetRect(g_pEdit,
        (xui_rect_t){ 50, 50, 700, 500 });

    xgeRun(onFrame, NULL);

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

代码讲解

  • xuiTextEditCreate:创建多行文本编辑器。
  • xuiTextEditSetLineNumbers:显示行号侧栏,指定宽度。
  • xuiTextEditSetWordWrap:启用自动换行。
  • xuiTextEditSetText:设置/追加文本内容。
  • 内置功能:支持查找替换、撤销重做、滚动条。

要点与陷阱

  • Readonly:只读模式禁止编辑,适合日志/预览。
  • LineNumbers:第二参数为行号栏宽度。
  • FindOptions:支持正则、大小写敏感、全词匹配。
  • 性能:超大文本(>100K 行)考虑 CodeEdit 控件。

进阶练习

  1. 笔记应用:多行编辑 + 自动保存 + 查找替换。
  2. 代码片段查看:只读 + 行号 + 等宽字体。
TextEdit 多行编辑效果
图:TextEdit 多行编辑渲染效果