//explorer 文件树形视图 import fsys; import sys.volume; import fsys.info; import win.ui.ctrl.treeview; import win.imageList; namespace win.ui; class explorer{ ctor( treeview ){ this.treeview = treeview; this._form = treeview._parentForm; treeview.modifyStyle(0x2000/*_TVS_NOSCROLL*/|0x8000/*_TVS_NOHSCROLL*/); var x,y = treeview.getPos(); var hCombobox = ::User32.RealChildWindowFromPoint(this._form.hwnd,x + 50,y - 20); if( hCombobox ){ this.combobox = this._form.getCtrl(hCombobox); if(this.combobox[["cls"]]!="combobox") this.combobox = null; } this.setIconSize = function(size){ var shil = __shilImageList[ ..string.lower(size:"small") ] : 0; var imgList = ..win.imageList.shell( shil ); this.treeview.setImageList(imgList,0/*_TVSIL_NORMAL*/); if( this.imageList )this.imageList.destroy(); this.imageList = imgList; } this.setIconSize("small"); this.loadFile = function(path,wildcard,pattern){ this.wildcard = wildcard; this.pattern = pattern; this.treeview.clear(); return this.loadItemFile( ,path); } this.insertDir = function(name,path,hItem){ var sfi = ..fsys.info.get(path,0x4000/*_SHGFI_SYSICONINDEX*/|0x10/*_SHGFI_USEFILEATTRIBUTES*/,0x10/*_FILE_ATTRIBUTE_DIRECTORY*/); var hItem = this.treeview.insertItem({ text = name; iImage = sfi.iIcon; iSelectedImage = sfi.iIcon; cChildren = 1 }) if(hItem){ this.treeview.setItemData(hItem,path); return hItem; } } this.insertFile = function(name,path,hItem){ var isDir = ..fsys.isDir(path); var sfi = ..fsys.info.get(path,0x4000/*_SHGFI_SYSICONINDEX*/|0x10/*_SHGFI_USEFILEATTRIBUTES*/,0x80/*_FILE_ATTRIBUTE_NORMAL*/); var hItem = this.treeview.insertItem({ text = name; iImage = sfi.iIcon; iSelectedImage = sfi.iIcon; }) if(hItem){ this.treeview.setItemData(hItem,path); return hItem; } } this.insertItem = function(filename,hItem){ var path = ..io.joinpath(this.getFilePath(hItem),filename); if(..fsys.isDir(path)){ return this.insertDir(filename,path,hItem); } return this.insertFile(filename,path,hItem); } this.setItemText = function(hItem,text){ this.treeview.setItemText(hItem,text) } this.reloadFile = function(path,hItem){ this.treeview.clear(hItem); return this.loadItemFile(hItem,path); } this.loadItemFile = function(hItem,path){ var files,dirs; if( ( path === null ) && ( hItem === null ) ){ dirs = ..sys.volume.getLogicalDrives(); if(this.combobox) { this.combobox.items = dirs; this.combobox.oncommand = function(id,event){ if(event == 1/*_CBN_SELCHANGE*/){ var driver = owner.selText; if(#driver) this.loadFile(driver) } } } for(i=1;#dirs;1){ dirs[dirs[i]] = dirs[i] +"\"; } this.rootPath = null; } else{ path = ..fsys.path.addBackslash( ..io.fullpath(path) ); if(!..fsys.isDir(path) ) error("路径不是一个有效的目录",2); files,,dirs = ..fsys.list(path,this.pattern,this.wildcard); if(hItem===null) this.rootPath = path; if(this.translatePath){ var itemPath = this.treeview.getItemPath(hItem); files,dirs = this.translatePath(path,files,dirs); } if( (!#dirs) && (!#files) && hItem ){ treeview.setItem( hItem = hItem; cChildren = 0; mask = 0x40/*_TVIF_CHILDREN*/; ) return; } }; ..win.ui.waitCursor(true); var treeview = this.treeview; var getInfo = ..fsys.info.get; var toUtf16 = ..string.toUtf16; var tvItem = TVITEM(); tvItem.mask = 1/*_TVIF_TEXT*/ | 0x20/*_TVIF_SELECTEDIMAGE*/ | 2/*_TVIF_IMAGE*/ | 1/*_TVIF_TEXT*/ | 0x40/*_TVIF_CHILDREN*/ var inst = { pointer hParent = hItem; addr hInsertAfter; struct item = tvItem; } treeview.setRedraw(false); var filename; if(this.dirFirst){ for(i=1;#dirs){ filename = dirs[i]; var sfi = getInfo(dirs[ filename ],0x4000/*_SHGFI_SYSICONINDEX*/|0x10/*_SHGFI_USEFILEATTRIBUTES*/,0x10/*_FILE_ATTRIBUTE_DIRECTORY*/); tvItem.textPtr = toUtf16( filename ); tvItem.cChildren = 1; tvItem.iImage = sfi.iIcon; tvItem.iSelectedImage = sfi.iIcon; inst.hInsertAfter = ::SendMessageByStruct(treeview.hwnd,0x1132/*_TVM_INSERTITEMW*/,0,inst ); treeview.setItemData(topointer(inst.hInsertAfter),dirs[ filename ]); } } tvItem.mask = tvItem.mask &~0x40; for(i=1;#files){ filename = files[i]; var sfi = getInfo(files[filename],0x4000/*_SHGFI_SYSICONINDEX*/|0x10/*_SHGFI_USEFILEATTRIBUTES*/,0x80/*_FILE_ATTRIBUTE_NORMAL*/); tvItem.textPtr = toUtf16(filename); tvItem.iImage = sfi.iIcon; tvItem.iSelectedImage = sfi.iIcon; inst.hInsertAfter = ::SendMessageByStruct(treeview.hwnd,0x1132/*_TVM_INSERTITEMW*/,0,inst ); treeview.setItemData(topointer(inst.hInsertAfter),files[ filename ]); } if(!this.dirFirst){ tvItem.mask = tvItem.mask | 0x40; for(i=1;#dirs){ filename = dirs[i]; var sfi = getInfo(dirs[ filename ],0x4000/*_SHGFI_SYSICONINDEX*/|0x10/*_SHGFI_USEFILEATTRIBUTES*/,0x10/*_FILE_ATTRIBUTE_DIRECTORY*/); tvItem.textPtr = toUtf16( filename ); tvItem.cChildren = 1; tvItem.iImage = sfi.iIcon; tvItem.iSelectedImage = sfi.iIcon; inst.hInsertAfter = ::SendMessageByStruct(treeview.hwnd,0x1132/*_TVM_INSERTITEMW*/,0,inst ); treeview.setItemData(topointer(inst.hInsertAfter),dirs[ filename ]); } } treeview.setRedraw(true); ..win.ui.waitCursor(false); } this.getFilePath = function(hItem){ if( hItem === null ) return this.rootPath; var path = this.treeview.getItemData(hItem); if(type(path)!="string"){ path = ..io.joinpath(this.rootPath,this.treeview.getItemPath(hItem)); if( path && path[#path] == ':'# ) path = path +"\"; } return path; } this.getCurrentFilePath = function(){ var hItem = this.treeview.getSelection(); if( hItem ) return this.getFilePath(hItem); } this.treeview._onDestroy = function(){ this.treeview.setImageList(null,0/*_TVSIL_NORMAL*/); if( this.imageList )this.imageList.destroy() } this.treeview.prenotify = { [0xFFFFFE3A/*_TVN_ITEMEXPANDINGW*/] = function(id,code,ptr){ var nmtv = this.treeview.getNotifyMessage(code,ptr) if(nmtv.action & 2/*_TVE_EXPAND*/) { var hItem = nmtv.itemNew.hItem; if( ! this.treeview.isExpandedOnce(hItem) ) { this.treeview.clear(hItem); this.loadItemFile( hItem,this.getFilePath(hItem) ); if( this.onExpandedOnce ){ this.onExpandedOnce( hItem ); } } } }; [0xFFFFFFFE/*_NM_CLICK*/] = function(id,code,ptr){ var hItem,flags = this.treeview.hitTest() if( hItem && this.onClick && ( flags & 6/*_TVHT_ONITEMLABEL | _TVHT_ONITEMICON*/) ){ this.onClick( this.getFilePath(hItem),hItem ); } }; [0xFFFFFE3D/*_TVN_SELCHANGEDW*/] = function(id,code,ptr){ var hItem = this.treeview.getSelection() ; if( hItem && this.onSelChanged){ this.onSelChanged( this.getFilePath(hItem),hItem ); } }; [0xFFFFFFFD/*_NM_DBLCLK*/] = function(id,code,ptr){ var hItem,flags = this.treeview.hitTest() if( hItem && this.onDoubleClick && ( flags & 6/*_TVHT_ONITEMLABEL | _TVHT_ONITEMICON*/) ){ this.onDoubleClick( this.getFilePath(hItem),hItem ); } }; [0xFFFFFFFB/*_NM_RCLICK*/] = function(id,code,ptr){ var x,y = ..win.getMessagePos(); var hItem,flags = this.treeview.hitTest(x,y,true) if( hItem && this.onRightClick ){ this.onRightClick( this.getFilePath(hItem),hItem,x,y ); } }; }; this.dirFirst = true; ..table.gc(this,function(){ if( this.imageList )this.imageList.destroy(); this.imageList = null; }) } } namespace explorer{ TVITEM = ..win.ui.ctrl.treeview.TVITEM; __shilImageList = { large = 0/*SHIL_LARGE */; small = 1/*SHIL_SMALL */; extralarge = 2/*_SHIL_EXTRALARGE*/; syssmall = 3/*_SHIL_SYSSMALL*/; jumbo = 4/*_SHIL_JUMBO*/; } } /**intellisense() win.ui.explorer = 用于创建类似资源管理器的文件树形视图 win.ui.explorer(__) = 创建类似资源管理器的文件树形视图。\n请在参数中指定一个已创建的 treeview 视图对象。\n创建对象时会自动启用 treeview 控件的滚动条。\n默认会在树形视图控件顶部自动搜索下拉框用于显示驱动器列表。 win.ui.explorer() = !win_ui_explorer. end intellisense**/ /**intellisense(!win_ui_explorer) rootPath = 文件视图根目录路径 wildcard = 用于匹配要显示的文件名通配符 pattern = 用于匹配要显示的文件或目录名的模式串 combobox = 用于显示驱动器的下拉框,\n默认会在树形视图控件顶部自动搜索下拉框,也可以自行指定\n!combobox. loadFile( = 搜索文件并加载到树形视图 loadFile(.("目录路径","通配符","模式匹配") = 搜索文件并加载到树形视图\n不指定任何参数调用此函数时默认显示所有硬盘分区,\n除参数@1以外,其他参数可选\n参数@2使用模式匹配语法匹配文件名\n通配符默认值是"*.*",也可以传入通配符数组 reloadFile( = 重新加载指定目录下的文件 reloadFile(.("目录路径",节点句柄) = 重新加载指定目录下的文件到参数@2指定的节点,\n参数@2如果省略则刷新所有节点 getFilePath(.(hItem) = 返回节点文件路径,不指定节点句柄时返回根路径 setItemText(.(hItem,text) = 设置节点显示文本。\n参数 @hItem 指定树视图节点句柄。\n参数 @text 指定要显示的文本。 insertDir(.(name,path,hItemParent) = 插入目录节点。\n参数 @name 指定显示名称。\n参数 @path 指定节点绑定的目录路径。\n可选用 @hItemParent 指定父节点句柄,不指定 @hItem 时添加到根节点 insertFile(.(name,path,hItemParent) = 插入文件节点。\n参数 @name 指定显示名称。\n参数 @path 指定节点绑定的文件路径。\n可选用 @hItemParent 指定父节点句柄,不指定 @hItem 时添加到根节点 insertItem(.(filename,hItemParent) = 添加文件名或目录名到指定节点。\n可选用 @hItemParent 指定父节点句柄,不指定 @hItem 时添加到根节点 getCurrentFilePath() = 返回当前选中节点文件路径\n注意onClick事件触发时树形控件尚未更改选中状态 setIconSize("large") = 显示大图标\n可选参数有:large,small,extralarge,syssmall,jumbo onExpandedOnce = @.onExpandedOnce = function(hItem){ __/*第一次展开参数指定的节点*/ } onClick = @.onClick = function(filePath,hItem){ __/*用户单击节点或节点图标,此时尚未改变选中节点*/ } onSelChanged = @.onSelChanged = function(filePath,hItem){ __/*用户已改变选中节点*/ } onDoubleClick = @.onDoubleClick = function(filePath,hItem){ __/*用户双击节点或节点图标,此时尚未改变选中节点*/ } onRightClick = @.onRightClick = function(filePath,hItem,x,y){ __/*用户右键单击节点*/ } translatePath = function(dirPath,files,dirs){ __/*转换显示名称。\ndirPath 为当前目录路径。\nfiles,dirs 为 fsys.list 返回的文件名与子目录数组。\n数组同时包含显示名称与实际路径对照的名值对。\n必须返回相同结构的 files,dirs。*/ return files,dirs; } end intellisense**/