自绘listbox实现类似360浏览器下载界面功能

By admin at 2018-09-16 • 1人收藏 • 2427人看过

先上360的界面:

image.png

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();

效果如下:

image.png

10 个回复 | 最后更新于 2024-04-12
2018-09-16   #1

image.png

//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();


2018-09-16   #2

添加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功能,效果比第一种方式好。基本无闪烁。

GIF2.gif

2018-09-16   #3

每行文件图标调用系统默认图标的方式:

import fsys.info;
//加图标测试
var sfi = fsys.info.get("D:\360安全浏览器下载\inst.exe", 0x4000/*_SHGFI_SYSICONINDEX*/ | 0x10/*_SHGFI_DISPLAYNAME*/);
    		
win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(sfi.iIcon,hdc,rc.left+20,rc.top+10);

image.png

2018-09-16   #4

浏览目录文件,添加到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();

image.png

2018-09-17   #5

增加右侧[删除]按键功能和按键动态效果(鼠标经过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();

GIF33.gif

2018-09-17   #6

修改界面中[删除] / [打开] / [文件夹] 鼠标样式效果,并增加对应功能.

修改界面: 不选中项目的时候,不出现 功能 按键.

GIF.gif

//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();


2018-09-17   #7

也许有些人就是喜欢文件和文件夹功能一直显示着,那么可以使用下面的代码

删除了必须选中才能执行 打开 和文件夹 的功能,好处是鼠标点哪就执行哪个。

自绘里面增加了一些判断,展示更好的动态效果。

image.png

//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();


2018-09-17   #8

如果文件名太长怎么办?

我们可以进行判断和截取。

//文件名
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);


把listbox玩出花了

2024-04-12   #10

登录后方可回帖

登 录
信息栏
 私人小站

本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网


才仁机械


网站地图SiteMap

Loading...