自绘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);登录后方可回帖



//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); 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;10){ winform.listbox.add("网页操作小助手.zip"); } //win.imageList winform.show(); win.loopMessage();