自绘listbox实现类似360浏览器下载界面功能
先上360的界面:
aardio里面有listbox的自绘示例,在此基础上先增加一点点功能看看效果
//GDI自绘 import win.ui; /*DSG{{*/ var winform = win.form(text="listbox自绘(GDI方式)";right=757;bottom=467) winform.add( listbox={cls="listbox";left=12;top=11;right=745;bottom=457;bgcolor=16777215;db=1;dl=1;dr=1;dt=1;items={};ownerDraw=1;vscroll=1;z=1} ) /*}}*/ winform.listbox.onMeasureItem = function(measureItem){ measureItem.itemHeight = 51; } import win.imageList; winform.listbox.onDrawItem = function(drawItem){ gdi.selectBrush( function(hdc,pen,brush){ var rc = drawItem.rcItem; gdi.fillRect(hdc,0xFFFFFF,rc); if (drawItem.itemID > 0) { gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top); } if (drawItem.itemState & 1/*_ODS_SELECTED*/) { //gdi.fillGradient(hdc,rc,0xFFFFFF, 0xC3BCA9,1/*_GRADIENT_FILL_RECT_V*/) gdi.fillRect(hdc,0xFFF5E2,rc); } //加图标测试 win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.left+20,rc.top+10); //加文字测试 var str = winform.listbox.getItemText(drawItem.itemID + 1); var str2 = "9.88MB -文件已删除" var font = ::LOGFONT(weight=400;color=0x000000); gdi.textOut(hdc,font,str,rc.left+60, rc.top+10); font = ::LOGFONT(weight=300;color=0xB0B0B0); gdi.textOut(hdc,font,str2,rc.left+60, rc.top+30); },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/) } for(i=1;10){ winform.listbox.add("网页操作小助手.zip"); } //win.imageList winform.show(); win.loopMessage();
效果如下:
添加listbox鼠标经过item项hover背景效果。
这个功能,试验了两种方式,
第一种方式:利用redraw()刷新启发重绘...,然后在自绘里面判断是否要绘制hover背景
关键代码如下:
var listboxsel = null; var beforesel = null; winform.listbox.onDrawItem = function(drawItem){ gdi.selectBrush( function(hdc,pen,brush){ var rc = drawItem.rcItem; gdi.fillRect(hdc,0xFFFFFF,rc); if (drawItem.itemID > 0) { gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top); } if (drawItem.itemState & 1/*_ODS_SELECTED*/) { //gdi.fillGradient(hdc,rc,0xFFFFFF, 0xC3BCA9,1/*_GRADIENT_FILL_RECT_V*/) gdi.fillRect(hdc,0xFFF5E2,rc); }else { if(listboxsel == (drawItem.itemID+1)){ gdi.fillRect(hdc,0xEEB7FF,rc); } } //加图标测试 win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.left+20,rc.top+10); win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.width()/2+200,rc.top+10); font = ::LOGFONT(weight=300;color=0x9C9C9C); gdi.textOut(hdc,font,"打开",rc.width()/2+235, rc.top+20); win.imageList.shell( 0/*_SHIL_JUMBO*/ ).draw(1,hdc,rc.width()/2+270,rc.top+10); gdi.textOut(hdc,font,"文件夹",rc.width()/2+300, rc.top+20); //加文字测试 var str = winform.listbox.getItemText(drawItem.itemID + 1); var str2 = "9.88MB -文件已删除" var font = ::LOGFONT(weight=400;color=0x000000); gdi.textOut(hdc,font,str,rc.left+60, rc.top+10); font = ::LOGFONT(weight=300;color=0xB0B0B0); gdi.textOut(hdc,font,str2,rc.left+60, rc.top+30); },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/) } for(i=1;60){ winform.listbox.add("网页操作小助手.zip"); } winform.listbox.wndproc = function(hwnd,message,wParam,lParam){ if(message == 0x200/*_WM_MOUSEMOVE*/){ var x,y = win.getMessagePos(); var item = winform.listbox.hitTest(x,y,true); if(listboxsel == item){ return ; }else { listboxsel = item; winform.listbox.redraw(); /* if(beforesel == null){ beforesel = listboxsel; }else { winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0) beforesel = listboxsel; } winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); */ } } }
虽然这种方式也实现了hover效果,但是,listbox由于刷新导致整个闪烁。
第二种方式: 利用
listbox.invalidate(__/*可选使用::RECT()对象指定客户区*/) = 使窗口绘图区无效
listbox.update();//更新指定区域
结合拦截鼠标位置信息,判断有效和无效item
完整代码如下:
//GDI自绘 import win.ui; /*DSG{{*/ var winform = win.form(text="listbox自绘(GDI方式)";right=757;bottom=467) winform.add( listbox={cls="listbox";left=12;top=11;right=745;bottom=457;bgcolor=16777215;clipch=1;db=1;dl=1;dr=1;dt=1;items={};ownerDraw=1;vscroll=1;z=1} ) /*}}*/ winform.listbox.onMeasureItem = function(measureItem){ measureItem.itemHeight = 51; } import win.imageList; import console console.open() var listboxsel = null; var beforesel = null; winform.listbox.onDrawItem = function(drawItem){ gdi.selectBrush( function(hdc,pen,brush){ var rc = drawItem.rcItem; gdi.fillRect(hdc,0xFFFFFF,rc); if (drawItem.itemID > 0) { gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top); } if (drawItem.itemState & 1/*_ODS_SELECTED*/) { //gdi.fillGradient(hdc,rc,0xFFFFFF, 0xC3BCA9,1/*_GRADIENT_FILL_RECT_V*/) gdi.fillRect(hdc,0xFFF5E2,rc); }else { if(listboxsel == (drawItem.itemID+1)){ gdi.fillRect(hdc,0xEEB7FF,rc); } } //加图标测试 win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.left+20,rc.top+10); win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.width()/2+200,rc.top+10); font = ::LOGFONT(weight=300;color=0x9C9C9C); gdi.textOut(hdc,font,"打开",rc.width()/2+235, rc.top+20); win.imageList.shell( 0/*_SHIL_JUMBO*/ ).draw(1,hdc,rc.width()/2+270,rc.top+10); gdi.textOut(hdc,font,"文件夹",rc.width()/2+300, rc.top+20); //加文字测试 var str = winform.listbox.getItemText(drawItem.itemID + 1); var str2 = "9.88MB -文件已删除" var font = ::LOGFONT(weight=400;color=0x000000); gdi.textOut(hdc,font,str,rc.left+60, rc.top+10); font = ::LOGFONT(weight=300;color=0xB0B0B0); gdi.textOut(hdc,font,str2,rc.left+60, rc.top+30); },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/) } for(i=1;60){ winform.listbox.add("网页操作小助手.zip"); } winform.listbox.wndproc = function(hwnd,message,wParam,lParam){ if(message == 0x200/*_WM_MOUSEMOVE*/){ var x,y = win.getMessagePos(); var item = winform.listbox.hitTest(x,y,true); if(listboxsel == item){ return ; }else { listboxsel = item; if(beforesel == null){ beforesel = listboxsel; }else { winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0) beforesel = listboxsel; } winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); } } } winform.show(); win.loopMessage();
上面的代码也实现这个hover功能,效果比第一种方式好。基本无闪烁。
浏览目录文件,添加到listbox中,并显示其图标和大小等信息
//GDI自绘 import win.ui; import fonts.fontAwesome; /*DSG{{*/ var winform = win.form(text="listbox自绘(GDI方式)";right=757;bottom=467) winform.add( listbox={cls="listbox";left=12;top=11;right=745;bottom=457;bgcolor=16777215;clipch=1;db=1;dl=1;dr=1;dt=1;items={};ownerDraw=1;vscroll=1;z=1} ) /*}}*/ winform.listbox.onMeasureItem = function(measureItem){ measureItem.itemHeight = 51; } import win.imageList; import console console.open() var listboxsel = null; var beforesel = null; import fsys; import fsys.info; import fsys.file; var filename; var boxTab = {}; var files,,dirs = ..fsys.list("D:\360安全浏览器下载"); for(i=1;#files) { filename = files[i]; var sfi = fsys.info.get(files[filename],0x10/*_SHGFI_USEFILEATTRIBUTES*/ | 0x4000/*_SHGFI_SYSICONINDEX*/ ); var fileSize = tonumber(fsys.file(files[filename]).size64()); if(fileSize/1024 >= 1){ if(fileSize/1024/1024 >= 1){ sizes = tostring(math.round(fileSize/1024/1024,2))++" MB"; }else { sizes = tostring(math.round(fileSize/1024,2))++" KB"; } }else { sizes = tostring(fileSize)++" B"; } table.mixin(boxTab,{ iImage = sfi.iIcon; text = string.toUnicode(filename); size = sizes }); winform.listbox.add(table.tostring(boxTab)) } winform.listbox.onDrawItem = function(drawItem){ gdi.selectBrush( function(hdc,pen,brush){ //获取并分解需要显示的数据(字符串转表) var strTab = eval(winform.listbox.getItemText(drawItem.itemID + 1)) var rc = drawItem.rcItem; gdi.fillRect(hdc,0xFFFFFF,rc); if (drawItem.itemID > 0) { gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top); } if (drawItem.itemState & 1/*_ODS_SELECTED*/) { gdi.fillRect(hdc,0xFFF5E2,rc); }else { if(listboxsel == (drawItem.itemID+1)){ gdi.fillRect(hdc,0xEEB7FF,rc); } } //加图标测试 win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(strTab.iImage,hdc,rc.left+20,rc.top+10); win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.width()/2+200,rc.top+10); var font = ::LOGFONT(weight=300;color=0x9C9C9C); gdi.textOut(hdc,font,"打开",rc.width()/2+235, rc.top+20); win.imageList.shell( 0/*_SHIL_JUMBO*/ ).draw(1,hdc,rc.width()/2+270,rc.top+10); gdi.textOut(hdc,font,"文件夹",rc.width()/2+300, rc.top+20); font = ::LOGFONT(weight=700;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20); //加文字测试 font = ::LOGFONT(weight=400;color=0x000000); gdi.textOut(hdc,font,strTab.text,rc.left+60, rc.top+10); font = ::LOGFONT(weight=300;color=0xB0B0B0); gdi.textOut(hdc,font,strTab.size,rc.left+60, rc.top+30); },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/) } winform.listbox.wndproc = function(hwnd,message,wParam,lParam){ if(message == 0x200/*_WM_MOUSEMOVE*/){ var x,y = win.getMessagePos(); var item = winform.listbox.hitTest(x,y,true); if(item == null){ return ; } if(listboxsel == item){ return ; }else { listboxsel = item; if(beforesel == null){ beforesel = listboxsel; }else { if(beforesel){ winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0) } beforesel = listboxsel; } winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); } } } winform.show(); win.loopMessage();
增加右侧[删除]按键功能和按键动态效果(鼠标经过hover变色).
//GDI自绘 import win.ui; import fonts.fontAwesome; /*DSG{{*/ var winform = win.form(text="listbox自绘(GDI方式)";right=778;bottom=445;border="dialog frame") winform.add( button={cls="button";text="增加行";left=0;top=385;right=779;bottom=436;z=2}; listbox={cls="listbox";left=0;top=0;right=779;bottom=376;bgcolor=16777215;clipch=1;db=1;dl=1;dr=1;dt=1;items={};ownerDraw=1;vscroll=1;z=1} ) /*}}*/ winform.listbox.onMeasureItem = function(measureItem){ measureItem.itemHeight = 51; } import win.imageList; import console console.open() var listboxsel = null; var beforesel = null; var colorsel = false; import fsys; import fsys.info; import fsys.file; var filename; var boxTab = {}; var files,,dirs = ..fsys.list("D:\BaiduNetdiskDownload"); for(i=1;#files) { filename = files[i]; var sfi = fsys.info.get(files[filename],0x10/*_SHGFI_USEFILEATTRIBUTES*/ | 0x4000/*_SHGFI_SYSICONINDEX*/ ); var fileSize = tonumber(fsys.file(files[filename]).size64()); if(fileSize/1024 >= 1){ if(fileSize/1024/1024 >= 1){ sizes = tostring(math.round(fileSize/1024/1024,2))++" MB"; }else { sizes = tostring(math.round(fileSize/1024,2))++" KB"; } }else { sizes = tostring(fileSize)++" B"; } table.mixin(boxTab,{ iImage = sfi.iIcon; text = filename; size = sizes }); winform.listbox.add(table.tostring(boxTab)) } winform.listbox.onDrawItem = function(drawItem){ gdi.selectBrush( function(hdc,pen,brush){ //获取并分解需要显示的数据(字符串转表) var strTab = eval(winform.listbox.getItemText(drawItem.itemID + 1)) var rc = drawItem.rcItem; gdi.fillRect(hdc,0xFFFFFF,rc); if (drawItem.itemID > 0) { gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top); } if (drawItem.itemState & 1/*_ODS_SELECTED*/) { gdi.fillRect(hdc,0xFFF5E2,rc); if(colorsel){ font = ::LOGFONT(weight=700;color=0x6112FF;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20); }else { font = ::LOGFONT(weight=700;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20); } }else { if(listboxsel == (drawItem.itemID+1)){ gdi.fillRect(hdc,0xEEB7FF,rc); } } //加图标测试 win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(strTab.iImage,hdc,rc.left+20,rc.top+10); win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.width()/2+200,rc.top+10); var font = ::LOGFONT(weight=300;color=0x9C9C9C;); gdi.textOut(hdc,font,"打开",rc.width()/2+235, rc.top+20); win.imageList.shell( 0/*_SHIL_JUMBO*/ ).draw(1,hdc,rc.width()/2+270,rc.top+10); gdi.textOut(hdc,font,"文件夹",rc.width()/2+300, rc.top+20); //加文字测试 font = ::LOGFONT(weight=400;color=0x000000); gdi.textOut(hdc,font,strTab.text,rc.left+60, rc.top+10); font = ::LOGFONT(weight=300;color=0xB0B0B0); gdi.textOut(hdc,font,strTab.size,rc.left+60, rc.top+30); },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/) } winform.listbox.wndproc = function(hwnd,message,wParam,lParam){ select(message) { case 0x200/*_WM_MOUSEMOVE*/ { var x,y = win.getMessagePos(); var item = winform.listbox.hitTest(x,y,true); if(item == null){ return ; } if(listboxsel == item){ /* 若鼠标在同一行item内游动 */ /* 首先,判断是否要显示[删除]按钮,通过判断鼠标是不是在选中item行内 */ if(listboxsel == winform.listbox.selIndex){ x,y = win.toClient(winform.listbox.hwnd,x,y); var rc = winform.listbox.getItemRect(item); rc.left = rc.width()/2+345; rc.top = rc.top+20; rc.bottom = rc.bottom-20 ; //判断鼠标游动的区间是不是在[删除]按钮范围 if( ::PtInRect(rc,x,y) ){ if(colorsel == false){ //鼠标从[删除]按钮外部移动到内部区域 colorsel = true; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); return; } return ; //一直在内部区域游动,则不更新 }else { if(colorsel == true){ //鼠标从内到外 colorsel = false; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); return ; } return ; //一直在外部区域游动,则不更新 } } return ; }else { //设置hover效果 listboxsel = item; if(beforesel == null){ //第一次执行,初始化 beforesel = listboxsel; }else { //先关闭上次绘制区域 if(beforesel){ winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0) } beforesel = listboxsel; } //绘制当前区域 winform.listbox.invalidate(winform.listbox.getItemRect(item)); winform.listbox.update(); } } case 0x202/*_WM_LBUTTONUP*/ { if(colorsel){ /* 若鼠标在删除按钮区域内单击了 */ var selindex = winform.listbox.selIndex var strTab = winform.listbox.getItemText(selindex); var tabStr = eval(strTab) var ret = winform.msgboxTest("您确定要删除 ["++tabStr.text++"] 文件吗?"); if(ret){ winform.listbox.delete(selindex); colorsel = false; } } } else { } } } winform.button.oncommand = function(id,event){ var sstab = {}; table.mixin(sstab,{ iImage = 0; text = "增加示例行"; size = "7.7 MB" }); winform.listbox.add(table.tostring(sstab)) } winform.show(); win.loopMessage();
修改界面中[删除] / [打开] / [文件夹] 鼠标样式效果,并增加对应功能.
修改界面: 不选中项目的时候,不出现 功能 按键.
//GDI自绘 import win.ui; import fonts.fontAwesome; /*DSG{{*/ var winform = win.form(text="listbox自绘(GDI方式)";right=778;bottom=445;border="dialog frame") winform.add( button={cls="button";text="增加行";left=0;top=385;right=779;bottom=436;z=2}; listbox={cls="listbox";left=0;top=0;right=779;bottom=376;bgcolor=16777215;clipch=1;db=1;dl=1;dr=1;dt=1;items={};ownerDraw=1;vscroll=1;z=1} ) /*}}*/ winform.listbox.onMeasureItem = function(measureItem){ measureItem.itemHeight = 51; } import win.imageList; import process; var listboxsel = null; var beforesel = null; var colorsel = false; var opensel = false; var filesel = false; import fsys; import fsys.info; import fsys.file; var filename; var boxTab = {}; var files,,dirs = ..fsys.list("D:\BaiduNetdiskDownload"); for(i=1;#files) { filename = files[i]; var sfi = fsys.info.get(files[filename],0x10/*_SHGFI_USEFILEATTRIBUTES*/ | 0x4000/*_SHGFI_SYSICONINDEX*/ ); var fileSize = tonumber(fsys.file(files[filename]).size64()); if(fileSize/1024 >= 1){ if(fileSize/1024/1024 >= 1){ sizes = tostring(math.round(fileSize/1024/1024,2))++" MB"; }else { sizes = tostring(math.round(fileSize/1024,2))++" KB"; } }else { sizes = tostring(fileSize)++" B"; } table.mixin(boxTab,{ iImage = sfi.iIcon; text = filename; size = sizes ; filePath = files[filename] }); winform.listbox.add(table.tostring(boxTab)) } winform.listbox.onDrawItem = function(drawItem){ gdi.selectBrush( function(hdc,pen,brush){ //获取并分解需要显示的数据(字符串转表) var strTab = eval(winform.listbox.getItemText(drawItem.itemID + 1)) var rc = drawItem.rcItem; gdi.fillRect(hdc,0xFFFFFF,rc); if (drawItem.itemID > 0) { gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top); } if (drawItem.itemState & 1/*_ODS_SELECTED*/) { gdi.fillRect(hdc,0xFFF5E2,rc); //删除文件 if(colorsel){ font = ::LOGFONT(weight=700;color=0x6112FF;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20); }else { font = ::LOGFONT(weight=700;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20); } //打开文件 if(opensel){ font = ::LOGFONT(weight=500;color=0x6112FF;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF0F6 打开',rc.width()/2+190, rc.top+20); }else { font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF0F6 打开',rc.width()/2+190, rc.top+20); } //打开文件夹 if(filesel){ font = ::LOGFONT(weight=500;color=0x6112FF;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF115 文件夹',rc.width()/2+260, rc.top+20); }else { font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF115 文件夹',rc.width()/2+260, rc.top+20); } }else { if(listboxsel == (drawItem.itemID+1)){ gdi.fillRect(hdc,0xEEB7FF,rc); } } //文件图标 win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(strTab.iImage,hdc,rc.left+20,rc.top+10); //文件名 font = ::LOGFONT(weight=400;color=0x000000); gdi.textOut(hdc,font,strTab.text,rc.left+60, rc.top+10); //文件大小 font = ::LOGFONT(weight=300;color=0xB0B0B0); gdi.textOut(hdc,font,strTab.size,rc.left+60, rc.top+30); },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/) } winform.listbox.wndproc = function(hwnd,message,wParam,lParam){ select(message) { case 0x200/*_WM_MOUSEMOVE*/ { var x,y = win.getMessagePos(); var item = winform.listbox.hitTest(x,y,true); if(item == null){ return ; } if(listboxsel == item){ /* 若鼠标在同一行item内游动 */ /* 首先,判断是否要显示[删除]按钮,通过判断鼠标是不是在选中item行内 */ if(listboxsel == winform.listbox.selIndex){ x,y = win.toClient(winform.listbox.hwnd,x,y); for(i=1;3;1){ select(i) { case 1 { //open var rc = winform.listbox.getItemRect(item); rc.left = rc.width()/2+190; rc.right = rc.left+60; rc.top = rc.top+10; rc.bottom = rc.bottom-10 ; //判断鼠标游动的区间是不是在[删除]按钮范围 if( ::PtInRect(rc,x,y) ){ if(opensel == false){ //鼠标从[删除]按钮外部移动到内部区域 opensel = true; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break ; } continue ; //一直在内部区域游动,则不更新 }else { if(opensel == true){ //鼠标从内到外 opensel = false; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break ; } continue ; //一直在外部区域游动,则不更新 } } case 2 { //file var filerc = winform.listbox.getItemRect(item); filerc.left = filerc.width()/2+260; filerc.right = filerc.left+70; filerc.top = filerc.top+10; filerc.bottom = filerc.bottom-10 ; //判断鼠标游动的区间是不是在[删除]按钮范围 if( ::PtInRect(filerc,x,y) ){ if(filesel == false){ //鼠标从[删除]按钮外部移动到内部区域 filesel = true; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break; } continue ; //一直在内部区域游动,则不更新 }else { if(filesel == true){ //鼠标从内到外 filesel = false; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break ; } continue ; //一直在外部区域游动,则不更新 } } case 3 { //del var delrc = winform.listbox.getItemRect(item); delrc.left = delrc.width()/2+345; delrc.top = delrc.top+20; delrc.bottom = delrc.bottom-20 ; //判断鼠标游动的区间是不是在[删除]按钮范围 if( ::PtInRect(delrc,x,y) ){ if(colorsel == false){ //鼠标从[删除]按钮外部移动到内部区域 colorsel = true; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break; } continue ; //一直在内部区域游动,则不更新 }else { if(colorsel == true){ //鼠标从内到外 colorsel = false; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break ; } continue ; //一直在外部区域游动,则不更新 } } } } } return ; }else { //设置hover效果 listboxsel = item; if(beforesel == null){ //第一次执行,初始化 beforesel = listboxsel; }else { //先关闭上次绘制区域 if(beforesel){ winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0) } beforesel = listboxsel; } //绘制当前区域 winform.listbox.invalidate(winform.listbox.getItemRect(item)); winform.listbox.update(); } } case 0x202/*_WM_LBUTTONUP*/ { //删除功能 if(colorsel){ /* 若鼠标在删除按钮区域内单击了 */ var selindex = winform.listbox.selIndex var strTab = winform.listbox.getItemText(selindex); var tabStr = eval(strTab) var ret = winform.msgboxTest("您确定要删除 ["++tabStr.text++"] 文件吗?"); if(ret){ winform.listbox.delete(selindex); colorsel = false; } return ; }; //打开文件 if(opensel){ /* 若鼠标在打开按钮区域内单击了 */ var selindex = winform.listbox.selIndex var strTab = winform.listbox.getItemText(selindex); var tabStr = eval(strTab) process.execute(tabStr.filePath); return ; } //打开文件夹 if(filesel){ /* 若鼠标在打开按钮区域内单击了 */ var selindex = winform.listbox.selIndex var strTab = winform.listbox.getItemText(selindex); var tabStr = eval(strTab) var path = io.splitpath(tabStr.filePath); process.execute(path.dir); return ; } } else { } } } winform.button.oncommand = function(id,event){ var sstab = {}; table.mixin(sstab,{ iImage = 0; text = "增加示例行"; size = "7.7 MB" }); winform.listbox.add(table.tostring(sstab)) } winform.show(); win.loopMessage();
也许有些人就是喜欢文件和文件夹功能一直显示着,那么可以使用下面的代码
删除了必须选中才能执行 打开 和文件夹 的功能,好处是鼠标点哪就执行哪个。
自绘里面增加了一些判断,展示更好的动态效果。
//GDI自绘 import win.ui; import fonts.fontAwesome; /*DSG{{*/ var winform = win.form(text="listbox自绘(GDI方式)";right=778;bottom=445;border="dialog frame") winform.add( button={cls="button";text="增加行";left=0;top=385;right=779;bottom=436;z=2}; listbox={cls="listbox";left=0;top=0;right=779;bottom=376;bgcolor=16777215;clipch=1;db=1;dl=1;dr=1;dt=1;items={};msel=1;ownerDraw=1;vscroll=1;z=1} ) /*}}*/ winform.listbox.onMeasureItem = function(measureItem){ measureItem.itemHeight = 51; } import win.imageList; import process; var listboxsel = null; var beforesel = null; var colorsel = false; var opensel = false; var filesel = false; import fsys; import fsys.info; import fsys.file; import fsys.dlg; var filename; var boxTab = {}; var dirPath; if( !io.exist(dirPath) ) { dirPath = fsys.dlg.opendir() } if(!dirPath){ dirPath = "D:\"; } var files,,dirs = ..fsys.list(dirPath); for(i=1;#files) { filename = files[ i ]; var sfi = fsys.info.get(files[filename],0x10/*_SHGFI_USEFILEATTRIBUTES*/ | 0x4000/*_SHGFI_SYSICONINDEX*/ ); var file = fsys.file(files[filename],"r"); var fileSize = tonumber(file.size64()); file.close();//不关掉后面删除就会出错 if(fileSize/1024 >= 1){ if(fileSize/1024/1024 >= 1){ sizes = tostring(math.round(fileSize/1024/1024,2))++" MB"; }else { sizes = tostring(math.round(fileSize/1024,2))++" KB"; } }else { sizes = tostring(fileSize)++" B"; } table.mixin(boxTab,{ iImage = sfi.iIcon; text = filename; size = sizes ; filePath = files[filename] }); winform.listbox.add(table.tostring(boxTab)) } winform.listbox.onDrawItem = function(drawItem){ gdi.selectBrush( function(hdc,pen,brush){ //获取并分解需要显示的数据(字符串转表) var strTab = eval(winform.listbox.getItemText(drawItem.itemID + 1)) var rc = drawItem.rcItem; gdi.fillRect(hdc,0xFFFFFF,rc); if (drawItem.itemID > 0) { gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top); } if (drawItem.itemState & 1/*_ODS_SELECTED*/) { gdi.fillRect(hdc,0xFFF5E2,rc); }else { if(listboxsel == (drawItem.itemID+1)){ gdi.fillRect(hdc,0xEEB7FF,rc); } } //删除文件 if(colorsel){ var x,y = win.getMessagePos(); var item = winform.listbox.hitTest(x,y,true); if((drawItem.itemID+1) == item){ font = ::LOGFONT(weight=700;color=0x6112FF;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20); }else { font = ::LOGFONT(weight=700;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20); } }else { font = ::LOGFONT(weight=700;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20); } if(opensel){ var x,y = win.getMessagePos(); var item = winform.listbox.hitTest(x,y,true); if((drawItem.itemID+1) == item){ font = ::LOGFONT(weight=500;color=0x6112FF;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF0F6 打开',rc.width()/2+190, rc.top+20); }else { font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF0F6 打开',rc.width()/2+190, rc.top+20); } }else { font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF0F6 打开',rc.width()/2+190, rc.top+20); } if(filesel){ var x,y = win.getMessagePos(); var item = winform.listbox.hitTest(x,y,true); if((drawItem.itemID+1) == item){ font = ::LOGFONT(weight=500;color=0x6112FF;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF115 文件夹',rc.width()/2+260, rc.top+20); }else { font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF115 文件夹',rc.width()/2+260, rc.top+20); } }else { font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-16); gdi.textOut(hdc,font,'\uF115 文件夹',rc.width()/2+260, rc.top+20); } //文件图标 win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(strTab.iImage,hdc,rc.left+20,rc.top+10); //文件名 font = ::LOGFONT(weight=400;color=0x000000); gdi.textOut(hdc,font,strTab.text,rc.left+60, rc.top+10); //文件大小 font = ::LOGFONT(weight=300;color=0xB0B0B0); gdi.textOut(hdc,font,strTab.size,rc.left+60, rc.top+30); },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/) } winform.listbox.wndproc = function(hwnd,message,wParam,lParam){ select(message) { case 0x200/*_WM_MOUSEMOVE*/ { var x,y = win.getMessagePos(); var item = winform.listbox.hitTest(x,y,true); if(item == null){ return ; } if(listboxsel == item){ /* 若鼠标在同一行item内游动 */ x,y = win.toClient(winform.listbox.hwnd,x,y); for(i=1;3;1){ select(i) { case 1 { //open var rc = winform.listbox.getItemRect(item); rc.left = rc.width()/2+190; rc.right = rc.left+60; rc.top = rc.top+10; rc.bottom = rc.bottom-10 ; //判断鼠标游动的区间是不是在[删除]按钮范围 if( ::PtInRect(rc,x,y) ){ if(opensel == false){ //鼠标从[删除]按钮外部移动到内部区域 opensel = true; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break ; } continue ; //一直在内部区域游动,则不更新 }else { if(opensel == true){ //鼠标从内到外 opensel = false; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break ; } continue ; //一直在外部区域游动,则不更新 } } case 2 { //file var filerc = winform.listbox.getItemRect(item); filerc.left = filerc.width()/2+260; filerc.right = filerc.left+70; filerc.top = filerc.top+10; filerc.bottom = filerc.bottom-10 ; //判断鼠标游动的区间是不是在[删除]按钮范围 if( ::PtInRect(filerc,x,y) ){ if(filesel == false){ //鼠标从[删除]按钮外部移动到内部区域 filesel = true; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break; } continue ; //一直在内部区域游动,则不更新 }else { if(filesel == true){ //鼠标从内到外 filesel = false; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break ; } continue ; //一直在外部区域游动,则不更新 } } case 3 { //del var delrc = winform.listbox.getItemRect(item); delrc.left = delrc.width()/2+345; delrc.top = delrc.top+20; delrc.bottom = delrc.bottom-20 ; //判断鼠标游动的区间是不是在[删除]按钮范围 if( ::PtInRect(delrc,x,y) ){ if(colorsel == false){ //鼠标从[删除]按钮外部移动到内部区域 colorsel = true; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break; } continue ; //一直在内部区域游动,则不更新 }else { if(colorsel == true){ //鼠标从内到外 colorsel = false; //设置更新区,并更新 winform.listbox.invalidate(winform.listbox.getItemRect(item)) winform.listbox.update(); break ; } continue ; //一直在外部区域游动,则不更新 } } } } return ; }else { //设置hover效果 listboxsel = item; if(beforesel == null){ //第一次执行,初始化 beforesel = listboxsel; }else { //先关闭上次绘制区域 if(beforesel){ winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0) } beforesel = listboxsel; } //绘制当前区域 winform.listbox.invalidate(winform.listbox.getItemRect(item)); winform.listbox.update(); } } case 0x202/*_WM_LBUTTONUP*/ { //删除功能 if(colorsel){ /* 若鼠标在删除按钮区域内单击了 */ var selindex = winform.listbox.selIndex var strTab = winform.listbox.getItemText(selindex); var tabStr = eval(strTab) var ret = winform.msgboxTest("您确定要删除 ["++tabStr.text++"] 文件吗?"); if(ret){ winform.listbox.delete(selindex); colorsel = false; } return ; }; //打开文件 if(opensel){ /* 若鼠标在打开按钮区域内单击了 */ var selindex = winform.listbox.selIndex var strTab = winform.listbox.getItemText(selindex); var tabStr = eval(strTab) process.execute(tabStr.filePath); return ; } //打开文件夹 if(filesel){ /* 若鼠标在打开按钮区域内单击了 */ var selindex = winform.listbox.selIndex var strTab = winform.listbox.getItemText(selindex); var tabStr = eval(strTab) var path = io.splitpath(tabStr.filePath); process.execute(path.dir); return ; } } case 0x20A/*_WM_MOUSEWHEEL*/{ var wheelDelta = raw.convert({int wParam=wParam },{word vk;word delta}).delta; if( wheelDelta > 0 ){ ::SendMessageInt(winform.listbox.hwnd, 0x115/*_WM_VSCROLL*/, 0, 0); }else { ::SendMessageInt(winform.listbox.hwnd, 0x115/*_WM_VSCROLL*/, 1, 0); } return 0; }; else { } } } winform.button.oncommand = function(id,event){ var sstab = {}; table.mixin(sstab,{ iImage = 0; text = "增加示例行"; size = "7.7 MB" }); winform.listbox.add(table.tostring(sstab)) } winform.show(); win.loopMessage();
如果文件名太长怎么办?
我们可以进行判断和截取。
//文件名 font = ::LOGFONT(weight=400;color=0x000000); if(string.len(strTab.text)>45){ gdi.textOut(hdc,font,string.left(strTab.text,3,true)++"..."++string.right(strTab.text,19,true),rc.left+60, rc.top+10); }else { gdi.textOut(hdc,font,strTab.text,rc.left+60, rc.top+10); }
利用string.left(str,len,true)实现按照字符数进行截取。
如果要用图片作为icon图标, 那么
var bmp = gdip.bitmap("/"++strTab.iImage); var gap = gdip.graphics(hdc); gap.drawImageRect(bmp,rc.left+10,rc.top+10,30,30);
登录后方可回帖