TreeView + ListView + Menu + Breadcrumb:双栏文件浏览器。
构建文件管理器(类 Windows Explorer):
• 目录树:TreeView 左侧导航(懒加载子目录)
• 文件列表:ListView 右侧内容(图标/详情视图)
• 右键菜单:Menu(新建/重命名/删除/复制)
• 面包屑:Breadcrumb 路径导航
• 工具栏:Toolbar(前进/后退/上级/刷新)
| 模块 | XUI API |
|---|---|
目录树 | xuiTreeViewCreate(懒加载/展开回调) |
文件列表 | xuiListViewCreate(虚拟化/多选) |
右键菜单 | xuiMenuCreate(Popup 层) |
面包屑 | xuiBreadcrumbCreate |
工具栏 | xuiToolbarCreate |
gcc -O2 -I. -o ch207.exe ch207_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch207.exe
// TreeView 展开回调(懒加载子目录)
void OnTreeExpand(xui_widget pTree,
int iNode, void* pUser)
{
const xui_tree_view_node_t* pNode =
xuiTreeViewGetNodeById(pTree, iNode);
const char* sPath = (const char*)pNode->pUser;
// 扫描子目录,构建节点数组
dir_entry_t* pDirs = ScanDirs(sPath);
int iCount = CountDirs(pDirs);
xui_tree_view_node_t* arrNodes = BuildNodes(pDirs, iNode, iCount);
xuiTreeViewSetNodes(pTree, arrNodes, iCount);
}
// 点击目录 → 更新文件列表
void OnTreeSelect(xui_widget pTree,
int iNode, void* pUser)
{
const xui_tree_view_node_t* pNode =
xuiTreeViewGetNodeById(pTree, iNode);
const char* sPath = (const char*)pNode->pUser;
file_entry_t* pFiles = ScanFiles(sPath);
int iCount = CountFiles(pFiles);
const char** arrNames = BuildNameArray(pFiles, iCount);
xuiListViewSetItems(pFileList, arrNames, iCount);
// 更新面包屑
xuiBreadcrumbClearItems(pCrumb);
AddPathSegments(pCrumb, sPath); // 逐段 AddItem
}将以下代码保存为 ch207_main.c,编译后运行即可看到文件管理器框架(目录树 + 文件列表):
#include "xge.h"
#include "xui.h"
static xui_context g_pCtx;
static int onFrame(void* pUser) {
(void)pUser;
xgeClear(0x1e1e2e);
xui_vec2_t pos;
xgeMouseGet(&pos.x, &pos.y);
xuiInputPointerMove(g_pCtx, pos.x, pos.y);
if (xgeMouseDown(XGE_MOUSE_LEFT))
xuiInputPointerDown(g_pCtx, pos.x, pos.y, 0);
else
xuiInputPointerUp(g_pCtx, pos.x, pos.y, 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 = 900; d.iHeight = 600;
d.sTitle = "ch207 - File Manager";
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, 900, 600);
xui_widget pRoot;
xuiPanelCreate(g_pCtx, &pRoot, NULL);
xuiWidgetSetRect(pRoot, (xui_rect_t){0, 0, 900, 600});
/* 目录树(左侧) */
xui_widget pTree;
xuiTreeViewCreate(g_pCtx, &pTree, NULL);
xuiWidgetAddChild(pRoot, pTree);
xuiWidgetSetRect(pTree, (xui_rect_t){0, 36, 240, 564});
xuiWidgetSetRect(pTree, (xui_rect_t){0, 0, 240, 564});
/* 文件列表(右侧) */
xui_widget pList;
xuiListViewCreate(g_pCtx, &pList, NULL);
xuiWidgetAddChild(pRoot, pList);
xuiWidgetSetRect(pList, (xui_rect_t){240, 36, 660, 564});
xuiWidgetSetRect(pList, (xui_rect_t){0, 0, 660, 564});
/* 工具栏 */
xui_widget pBar;
xuiPanelCreate(g_pCtx, &pBar, NULL);
xuiWidgetAddChild(pRoot, pBar);
xuiWidgetSetRect(pBar, (xui_rect_t){0, 0, 900, 36});
xuiWidgetSetRect(pBar, (xui_rect_t){0, 0, 900, 36});
xgeRun(onFrame, NULL);
xuiDestroy(g_pCtx);
xgeUnit();
return 0;
}