通过窗口消息与远程内存访问其他进程的标准 SysTreeView32 控件。
使用方式与 win.ui.ctrl.treeview 相近,支持导航、遍历、查找、展开折叠、Unicode 文本读写及节点增删。
import winex.ctrl.treeview;
import console;
var tv,err = winex.ctrl.treeview(0x511500);
if(!tv){
console.error(err);
return;
}
console.log("节点总数:",tv.count);
for hItem in tv.each(){
console.log(hItem,tv.getItemText(hItem));
}
console.log("当前选中节点:",tv.getItemText());
console.log("当前节点路径:",tv.getItemPath());
tv.free();
窗口句柄会在窗口重新创建后变化,0x511500 仅为本次会话中的示例。
构造失败返回 null,err。如果目标以管理员身份运行,调用方也需要相应权限。
each(parent):只遍历直接子节点,省略 parent 表示根层。enum(callback,parent):深度遍历已经存在的子节点,回调参数为 (hItem,parent),返回 false 停止。getChildren(parent):获取直接子节点句柄数组。find("Object Classes", "子项文本"):按精确文本逐级查找,中间节点会被展开;也可先传父节点句柄。findPath("Object Classes\子项文本"):反斜杠分隔的路径查找。getItemPath(hItem):返回节点的完整文本路径,省略节点使用选中项。getFirst/getSelection/getChildItem/getParentItem/getNextSibling/getPrevSibling:返回节点句柄。节点句柄类型为 pointer,窗口句柄 hwnd 类型为数值。不得解引用目标进程中的节点指针。
遍历不自动展开尚未加载的节点。expandAll(parent) 先展开父节点,再递归展开新加载的子节点;不要轻易对大型外部树调用无参数 expandAll()。
import winex.ctrl.treeview;
var tv,err=winex.ctrl.treeview(0x511500);
if(!tv) return null,err;
var hItem=tv.getFirst();
var item=tv.getItem(hItem=hItem;mask=0x7F;stateMask=0xFFFF);
// item.text / state / iImage / iSelectedImage / cChildren / lParam
tv.free();
return item;
getItem(hItem) 默认读取文本。也可以传入 win.ui.ctrl.treeview.TVITEM() 或普通属性表。
只支持基本 TVITEMW 字段,不支持 TVITEMEX。
getItemText(hItem) 默认从 260 个 UTF-16 单元开始,遇到截断自动扩容,最大 32768 单元。
显式传入第二个长度参数时采用 Win32 截断语义,长度包含尾部终结符空间。空节点文本返回 "",失败返回 null,err。
setSelected(hItem):选中节点,省略参数清除选中。expand/collapse/toggle(hItem):展开、折叠、切换;省略节点使用选中项。ensureVisible(hItem):展开祖先并滚动到目标节点。setItemText(hItem,text):修改文本,空字符串可清空;仅传文本时修改选中节点。setItem({hItem=...;text=...;lParam=...}):自动推断基本字段的 mask,不修改输入表。getItemState/setItemState:读取或修改状态位,默认状态掩码为 0xF000。getChecked/setChecked/checkAll:复选框状态。getItemRect(hItem,true):获取节点文本矩形,坐标为控件客户区设备像素。hitTest(x,y,screen):返回节点句柄与 TVHT 标志;允许零坐标,screen=true 表示屏幕设备像素。insertItem/delItem/clear:增删节点,支持 children 子树;会实际改变目标程序的数据,谨慎使用。结构体与文本缓冲区都在目标进程内存中传递,调用结束会释放;不会返回已释放的远程文本地址。
setItemData/getItemData 保留本地树控件的语义:数据只保存在调用方,支持 aardio 对象,不是目标节点的原生 lParam。
访问原生 lParam 请使用 getItem({hItem=...;mask=4}) 或 setItem({hItem=...;lParam=...}),不要将目标地址当作本地地址使用。
free() 仅释放该绑定持有的进程控制句柄与临时资源,不关闭目标程序。
不要用继承的 close() 来释放绑定,它会关闭目标控件。释放后不要继续使用该绑定。
不支持外部窗口的 onnotify/onSelChanged 等事件;通知结构解析、本地 imageList 和本地窗口子类化不适用于此绑定。
本版支持 32 位目标进程,包括 64 位 Windows 中运行的 32 位应用。64 位目标明确返回 null,err。
ListView 通常使用固定 32 位的行列索引;适配远程结构体中的指针宽度后即可读写文本。
TreeView 的 HTREEITEM 则是指针宽度,TVM_GETNEXTITEM 返回节点句柄,后续消息又需要传回该句柄。
32 位调用方直接使用 SendMessage 不能完整传递任意 64 位节点句柄,单独定义 TVITEM64 并不足以解决问题。
后续如果需要支持 64 位树,可增加 64 位辅助消息调用通道;本版不引入这层依赖。