vlistEx 是基于 Windows SysListView32 深度扩展的高性能虚表组件,
专为 aardio 设计。通过 LVS_OWNERDATA 虚表机制,支持百万级数据流畅显示,
并提供远超原生控件的丰富功能。
通过 tableAdapter / customAdapter 将数据层与显示层解耦。
表格仅通过适配器的 getItem(row, col) 获取数据,支持数组、字典表或完全自定义回调。
// 普通数组数据 var data = { { "张三", 28, "技术部" }; { "李四", 34, "产品部" }; }; vlist.setTable(data, { "姓名", "年龄", "部门" }); // 字典表数据 var dict = { { name="张三"; age=28; dept="技术部" }; { name="李四"; age=34; dept="产品部" }; }; vlist.setTable(dict, { "name", "age", "dept" });
_COLTYPE)
通过 setColumnType(col, type, ...) 为每列定义渲染行为:
| 代码 | 类型名称 | 说明 | 典型用途 |
|---|---|---|---|
| -1 | 多行文本 | 自动换行,可配置垂直对齐 | 备注 · 描述 · 长文本 |
| 0 | 普通文本 | 默认类型,支持图文混排 | 姓名 · 编号 · 日期 |
| 1 | 下拉列表框 | 点击弹出下拉列表 | 枚举 · 分类 · 性别 |
| 2 | 图片 | 居中 / 缩放 / 填满 三种模式 | 头像 · 图标 · 缩略图 |
| 3 | 进度条 | 数值渲染为进度条,可自定义颜色 | 完成度 · 百分比 · 进度 |
| 4 | 图片开关 | 多状态切换,点击自动切换 | 启用/禁用 · 开关 |
| 5 | 图片按钮 | 带悬浮效果的按钮 | 编辑 · 删除 · 查看 |
| 6 | 纯自绘 | 完全由用户回调绘制 | 图表 · 仪表 · 复杂UI |
| 7 | 完全自定义 | 基于模型绘制任意元素组合 | 混合布局 · 卡片式 |
| 8 | 复选框 | 勾选框,支持单选/多选模式 | 多选 · 标记 · 权限 |
// 设置第4列为复选框(状态列) vlist.setColumnType(4, 8, 16, 0xFF2A7FAA, "在职", "离职", false); // 设置第5列为进度条 vlist.setColumnType(5, 3, 0xEEEEEE, 0x4CAF50, true, 4, false); // 设置第6列为图片按钮 vlist.setColumnType(6, 5, true, 0x2A7FAA, 0x1A5A7A, 0xFFFFFF, 0xFFFFFF);
NM_CUSTOMDRAW 分 6 阶段绘制,每阶段可触发回调拦截:
| # | 触发事件 | 绘制内容 | 控制方式 / 说明 |
|---|---|---|---|
| 1 | onDrawCellBg |
整个单元格背景(含边框区域) | 可拦截 · 跳过默认 |
| 2 | 系统内置 | 复选框 · 树形指示器 | 系统绘制 · 不可拦截 |
| 3 | onDrawCellRectBg |
单元格有效区域背景(内边距以内) | 可拦截 · 跳过默认 |
| 4 | onDrawCellRectContent |
文本 · 图片 · 进度条 · 开关 · 按钮 · 自定义 | 可拦截 · 跳过默认 |
| 5 | 系统内置 | 横线 · 竖线 · 行拖拽标记 | 系统绘制 · 不可拦截 |
| 6 | onDrawCellBorderEnd |
边框 / 装饰(收尾阶段) | 可拦截 · 跳过默认 |
// 自定义单元格背景 vlist.onDrawCellBg = function(row, col, hdc, rect, bkcolor, text) { if (row % 2 === 0) { ..gdi.fillRect(hdc, 0xF5F9FF, rect); // 斑马纹 return true; // 跳过默认绘制 } } // 自定义单元格内容 vlist.onDrawCellRectContent = function(row, col, hdc, rect, bkcolor, text, font, align, valign) { if (col === 3 && text === "技术部") { ..gdi.drawText(hdc, font, "🔧 " ++ text, rect, align | valign | 0x20); return true; } }
_metaProperty)
利用 aardio 元表特性,将方法封装为直观属性:
vlist.rowHeight = 30 等价于 vlist.setRowHeight(30)。
// 属性方式(推荐) vlist.rowHeight = 30; vlist.headerHeight = 40; vlist.padding = 6; vlist.textColor = 0x222222; // 方法方式(等价) vlist.setRowHeight(30); vlist.setHeaderHeight(40); vlist.PADDING = 6; vlist.font.color = 0x222222;
// 行高与表头 vlist.setRowHeight(28); vlist.setHeaderHeight(36); // 颜色主题 vlist.bkColor = 0xFFFFFF; vlist.selectedBkColor = 0xCCE5FF; vlist.selectedTextColor = 0x000000; vlist.lineColorH = 0xDDDDDD; vlist.lineColorV = 0xDDDDDD; // 内边距 vlist.padding = 6; // 统一内边距 vlist.padding = { left=4; top=2; right=4; bottom=2 }; // 分别设置 // 启用全行选择 vlist.fullRow = true; // 启用斑马纹 vlist.bkColor1 = 0xFFFFFF; vlist.bkColor2 = 0xF5F8FC;
// 设置列(字段名, 宽度, 对齐方式) vlist.setColumns( { "姓名", "年龄", "部门", "状态", "进度" }, { 100, 60, 120, 80, 100 }, { 0, 1, 0, 1, 0 } // 0左 1中 2右 ); // 单独设置列宽 vlist.setColumnWidth(1, 120); vlist.setColumnWidth({1, 3, 5}, {120, 80, 100}); // 自动适配列宽 vlist.fitColWidth(); // 全部列 vlist.fitColWidth(1, 20); // 单列,附加20px vlist.fitColWidth({1, 3}, 10); // 多列 // 自动填满父容器宽度 vlist.fillParent(3); // 第3列自动填满剩余宽度
// 设置数据(自动创建列) vlist.setTable(data, fields); // 追加数据 vlist.addTable(moreData); // 获取数据 var allData = vlist.getTable(); var rowData = vlist.getRowData(3); var cellText = vlist.getCellText(3, 2); // 修改数据 vlist.setCellText(3, 2, "新值"); vlist.setRowData(3, { "张三", 30, "技术部" }); // 插入/删除行 vlist.insertRow(3, { "新员工", 25, "市场部" }); vlist.addRow({ "末尾员工", 40, "人事部" }); vlist.delRow(5); vlist.delRow({2, 4, 6});
// 启用复选框(第一列) vlist.checkBox.show = true; vlist.checkBox.size = 16; // 获取/设置选中行 var sel = vlist.getSelected(); // 返回 {行号数组, 数据数组} vlist.setSelected(3); // 选中单行 vlist.setSelected({2, 4, 6}); // 选中多行 vlist.setSelected(); // 取消全部选中 // 复选框操作 var checked = vlist.getChecked(); // 返回 {行号数组, 数据数组} vlist.setChecked({1, 3, 5}); // 勾选指定行 vlist.setChecked(); // 取消全部勾选 // 根据文本选中/勾选 vlist.setSelectedByText("技术部", 3); // 在第三列查找"技术部"并选中 vlist.setCheckedByText("技术部", 3); // 在第三列查找"技术部"并勾选
// 启用树形结构 vlist.tree.show = true; vlist.tree.spaceWidth = 20; // 数据中设置层级(示例) var treeData = { { name="总部"; ["@treeLevel"]=0 }; // 根节点 { name=" 技术部"; ["@treeLevel"]=1 }; // 子节点 { name=" 前端组"; ["@treeLevel"]=2 }; // 孙节点 { name=" 后端组"; ["@treeLevel"]=2 }; { name=" 产品部"; ["@treeLevel"]=1 }; }; vlist.setTable(treeData, { "name" }); // 展开/折叠(通过设置数据实现) vlist.hideRow(2); // 隐藏指定行 vlist.hideRowAndSubRow(1); // 隐藏行及其所有子行 vlist.isHideRow(2); // 判断行是否隐藏
// 合并行1-2,列1-2 vlist.addMerge(1, 1, 2, 2); // 合并行3,列2-4 vlist.addMerge(3, 2, 3, 4); // 取消合并 vlist.delMerge(1, 1); // 取消指定单元格所在的合并 vlist.clearAllMerges(); // 取消所有合并 // 判断/获取合并信息 var isMerged = vlist.isMerged(1, 1); var mergeInfo = vlist.getMerge(1, 1); // 返回 {row1, col1, row2, col2}
// 启用列头点击排序 vlist.onSortColumn = true; // 手动排序(按第2列,降序,数值模式) vlist.sort(2, true, 2); // convert=2 数值模式 // 按文本排序(使用 Windows 自然排序) vlist.sort(1, false, 3, true); // stringMode=true 自然排序 // 自定义排序函数 vlist.onSortColumn = function(col, desc) { if (col === 1) { // 自定义排序逻辑 vlist.sort(col, desc, 3, true); } };
// 查找(返回第一个匹配) var result = vlist.find("张三", 1, 0, 1); // 在第1列查找"张三" // 查找全部 var all = vlist.find("技术", 1, 0, 3, true, true); // 模糊匹配 // 过滤(保留匹配行) vlist.filter("技术部", 3); // 只显示第三列为"技术部"的行 vlist.filter("技术", 3, true); // 模糊匹配 vlist.filter(); // 取消过滤,恢复全部数据 // 高级过滤(支持 >, <, >=, <=, !=, include 等) vlist.filterEx({ { 3, "startWith", "技术" }; // 第3列以"技术"开头 { 2, ">=", 25 }; // 第2列 >= 25 }, true); // true=或条件,false=且条件
// 点击事件 vlist.onClick = function(row, col, x, y, btnIdx) { winform.msgbox("点击了第" ++ row ++ "行第" ++ col ++ "列"); }; // 双击事件 vlist.onDblClick = function(row, col, x, y, btnIdx) { vlist.edit(row, col); // 双击编辑 }; // 右键点击 vlist.onRClick = function(row, col, x, y, btnIdx) { vlist.setSelected(row); // 右键选中行 }; // 行选择变化 vlist.onItemChanged = function(row) { statusBar.text = "当前选中: " ++ row; }; // 单元格编辑 vlist.onEditBegin = function(row, col) { return col === 2; // 只允许编辑第2列 }; // 拖拽行 vlist.onDragRow = function(dragRow, dragList) { return true; // 允许拖拽 }; vlist.onDragRowEnd = function(dragList, targetRow) { // 拖拽结束处理 return true; };
// 添加图片到缓存 vlist.addImg("avatar", "/res/avatar.png", false, 32, 32); // 单元格中使用图片(图文混排) vlist.setCellText(1, 1, '张三'); // 添加字体 vlist.addFont("title", { name="微软雅黑"; h=16; color=0xCC0000 }); vlist.addFont("highlight", { name="宋体"; h=12; color=0x0066CC }); // 单元格中使用字体 vlist.setCellText(1, 1, '');
// 导出 CSV vlist.saveToCsv("data.csv", true, true); // 带表头,UTF-8 // 导出为字符串 var csvStr = vlist.saveToCsv(); // 导入 CSV vlist.openCsv("data.csv", true, true); // 带表头,重建列 // 从字符串导入 vlist.openCsv(csvStr, true, true);
vlistEx 是设计精巧、功能丰富的自定义表格控件,展现了对 Windows 编程和 aardio 语言的深刻理解。 通过 虚表、适配器、列类型系统 和 丰富回调, 实现了高性能与高灵活性的统一。
设计充分体现 开闭原则(对扩展开放,对修改封闭), 可通过事件回调、列类型扩展、自定义适配器等方式实现各种定制需求。