aardio 官方社区

用户名  找回密码
 注册会员

QQ登录

只需一步,快速开始

帖子
查看: 36423|回复: 4

分享listbox自绘鼠标经过item项的hover效果实现方式

[复制链接]

38

主题

129

回帖

1045

积分

荣誉会员

积分
1045
发表于 2018-9-16 16:06:29 | 显示全部楼层 |阅读模式
本帖最后由 popdes 于 2018-9-16 16:13 编辑

一直有想模仿下360浏览器上面的下载界面,今天有时间正好研究了下。

GIF3.gif

利用了listbox的GDI自绘范例,学习的时候发现drawItem.itemState中没有mouseHover这个状态,看来要自己判断了。
实现这个hover效果,考虑了以下两种方式

第一种方式:利用redraw()刷新启发重绘...,然后在自绘里面判断是否要绘制hover背景

关键代码如下:
  1. winform.listbox.wndproc = function(hwnd,message,wParam,lParam){
  2.     if(message == 0x200/*_WM_MOUSEMOVE*/){
  3.          
  4.         var x,y = win.getMessagePos();  
  5.         var item = winform.listbox.hitTest(x,y,true);
  6.         if(listboxsel == item){
  7.                 return ;
  8.         }else {
  9.             listboxsel = item;
  10.             
  11.             winform.listbox.redraw();
复制代码

虽然这种方式也实现了hover效果,但是,listbox由于刷新导致整个闪烁。 于是弃置。

第二种方式:利用

listbox.invalidate(__/*可选使用::RECT()对象指定客户区*/) = 使窗口绘图区无效

listbox.update();//更新指定区域

结合拦截鼠标位置信息,判断有效和无效item

完整代码如下:
  1. //GDI自绘
  2. import win.ui;
  3. /*DSG{{*/
  4. var winform = win.form(text="listbox自绘(GDI方式)";right=757;bottom=467)
  5. winform.add(
  6. 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}
  7. )
  8. /*}}*/

  9. winform.listbox.onMeasureItem = function(measureItem){
  10.     measureItem.itemHeight = 51;  
  11. }
  12. import win.imageList;
  13. import console
  14. console.open()

  15. var listboxsel = null;
  16. var beforesel = null;
  17. winform.listbox.onDrawItem = function(drawItem){
  18.      gdi.selectBrush(
  19.       
  20.         function(hdc,pen,brush){

  21.             var rc = drawItem.rcItem;
  22.             gdi.fillRect(hdc,0xFFFFFF,rc);
  23.             if (drawItem.itemID > 0) {  
  24.                 gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top);
  25.             }
  26.             
  27.             if (drawItem.itemState & 1/*_ODS_SELECTED*/) {  
  28.                 //gdi.fillGradient(hdc,rc,0xFFFFFF, 0xC3BCA9,1/*_GRADIENT_FILL_RECT_V*/)
  29.                 gdi.fillRect(hdc,0xFFF5E2,rc);
  30.             }else {
  31.                 if(listboxsel == (drawItem.itemID+1)){
  32.                     gdi.fillRect(hdc,0xEEB7FF,rc);
  33.                 }   
  34.             }
  35.             
  36.             //加图标测试
  37.             win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.left+20,rc.top+10);
  38.             
  39.             win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.width()/2+200,rc.top+10);
  40.             font = ::LOGFONT(weight=300;color=0x9C9C9C);
  41.             gdi.textOut(hdc,font,"打开",rc.width()/2+235, rc.top+20);
  42.             win.imageList.shell( 0/*_SHIL_JUMBO*/ ).draw(1,hdc,rc.width()/2+270,rc.top+10);
  43.             gdi.textOut(hdc,font,"文件夹",rc.width()/2+300, rc.top+20);
  44.             //加文字测试
  45.             var str = winform.listbox.getItemText(drawItem.itemID + 1);
  46.             var str2 = "9.88MB       -文件已删除"
  47.             var font = ::LOGFONT(weight=400;color=0x000000);
  48.             gdi.textOut(hdc,font,str,rc.left+60, rc.top+10);
  49.             font = ::LOGFONT(weight=300;color=0xB0B0B0);
  50.             gdi.textOut(hdc,font,str2,rc.left+60, rc.top+30);
  51.             
  52.          },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/)
  53. }
  54.   
  55. for(i=1;60){
  56.     winform.listbox.add("网页操作小助手.zip");
  57. }

  58. winform.listbox.wndproc = function(hwnd,message,wParam,lParam){
  59.     if(message == 0x200/*_WM_MOUSEMOVE*/){
  60.          
  61.         var x,y = win.getMessagePos();  
  62.         var item = winform.listbox.hitTest(x,y,true);
  63.         if(listboxsel == item){
  64.                 return ;
  65.         }else {
  66.             listboxsel = item;
  67.             if(beforesel == null){
  68.                 beforesel = listboxsel;
  69.                  
  70.             }else {
  71.                 winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0)
  72.                 beforesel = listboxsel;
  73.             }
  74.             winform.listbox.invalidate(winform.listbox.getItemRect(item))
  75.             winform.listbox.update();
  76.         }
  77.     }

  78. }

  79. winform.show();
  80. win.loopMessage();
复制代码

上面的代码也实现这个hover功能,效果比第一种方式好。基本无闪烁。可用。

试验之后总感觉实现一个hover的功能稍显复杂了, 不知道各位看官有没有更好的方案。再此拜谢!

后面的一些功能还在测试,等测试好了一并更新到以下楼层,就不在另外开贴了。
大概还有待测试的功能有:1,鼠标放到文件名地方出现提示文,2,鼠标放在【打开】和【文件夹】上面实现图标hover效果,3,每行最后增加一个删除按钮(类似tabs控件的右上角x号)

38

主题

129

回帖

1045

积分

荣誉会员

积分
1045
 楼主| 发表于 2018-9-17 22:39:09 | 显示全部楼层
追更一下:
估计有些人喜欢右侧的【打开】和【文件夹】一直显示着,所以这次主要把右侧功能区显示限制解除,并完善了下鼠标在右侧功能区的hover效果和点击效果。可以直接移动过去想点哪就点哪了。
增加启动即提示选择要显示的文件夹功能。

代码还没整理有点乱,看官们多包涵。

  1. //GDI自绘
  2. import fsys;
  3. import fsys.info;
  4. import fsys.file;
  5. import fsys.dlg;
  6. import win.imageList;
  7. import process;
  8. import fonts.fontAwesome;
  9. import win.ui;
  10. /*DSG{{*/
  11. var winform = win.form(text="listbox自绘(GDI方式)";right=778;bottom=445;border="dialog frame")
  12. winform.add(
  13. button={cls="button";text="增加行";left=0;top=385;right=779;bottom=436;db=1;dl=1;dr=1;z=2};
  14. 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}
  15. )
  16. /*}}*/

  17. var listboxsel = null;
  18. var beforesel = null;
  19. var colorsel = false;
  20. var opensel = false;
  21. var filesel = false;
  22. var filename;
  23. var boxTab = {};

  24. var dirPath;
  25. if( !io.exist(dirPath) ) dirPath = fsys.dlg.opendir()
  26. if(!dirPath) dirPath = "D:";

  27. //自定义列表项高度
  28. winform.listbox.onMeasureItem = function(measureItem,dpiScaleX,dpiScaleY){
  29.     measureItem.itemHeight = 81 * dpiScaleY;  
  30. }

  31. //自绘列表项
  32. winform.listbox.onDrawItem = function(drawItem,dpiScaleX,dpiScaleY){
  33.     //选择画刷
  34.     gdi.selectBrush(
  35.         
  36.         function(hdc,pen,brush){
  37.         
  38.                 //获取需要显示的数据
  39.             var strTab = winform.listbox.getItemText(drawItem.itemID + 1);
  40.             
  41.             //字符串转表对象( table )。
  42.             strTab = eval(strTab);
  43.             
  44.             var rc = drawItem.rcItem;
  45.             gdi.fillRect(hdc,0xFFFFFF,rc);
  46.             if (drawItem.itemID > 0) {  
  47.                 gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top);
  48.             }                 
  49.             if (drawItem.itemState & 1/*_ODS_SELECTED*/) {  
  50.                 gdi.fillRect(hdc,0xFFF5E2,rc);
  51.             }else {
  52.                 if(listboxsel == (drawItem.itemID+1)){
  53.                     gdi.fillRect(hdc,0xEEB7FF,rc);
  54.                 }            
  55.             }
  56.             
  57.             //字体
  58.             var font;
  59.                                                 
  60.             //删除文件
  61.             if(colorsel){
  62.                 var x,y = win.getMessagePos();  
  63.                 var item = winform.listbox.hitTest(x,y,true);

  64.                 if((drawItem.itemID+1) == item){
  65.                     font = ::LOGFONT(weight=700;color=0x6112FF;name='FontAwesome';h=-12*dpiScaleY);
  66.                     gdi.textOut(hdc,font,'\uF057',rc.width()/2+345*dpiScaleX, rc.top+20);
  67.                 }
  68.                 else {
  69.                     font = ::LOGFONT(weight=700;color=0x9C9C9C;name='FontAwesome';h=-12*dpiScaleY);
  70.                     gdi.textOut(hdc,font,'\uF057',rc.width()/2+345*dpiScaleX, rc.top+20);
  71.                 }
  72.             }else {
  73.                     font = ::LOGFONT(weight=700;color=0x9C9C9C;name='FontAwesome';h=-12*dpiScaleY);
  74.                     gdi.textOut(hdc,font,'\uF057',rc.width()/2+345*dpiScaleX, rc.top+20);
  75.             }
  76.             
  77.             if(opensel){
  78.                 var x,y = win.getMessagePos();  
  79.                 var item = winform.listbox.hitTest(x,y,true);

  80.                 if((drawItem.itemID+1) == item){
  81.                     font = ::LOGFONT(weight=500;color=0x6112FF;name='FontAwesome';h=-12*dpiScaleY);
  82.                     gdi.textOut(hdc,font,'\uF0F6 打开',rc.width()/2+190*dpiScaleX, rc.top+20);
  83.                 }else {
  84.                     font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-12*dpiScaleY);
  85.                     gdi.textOut(hdc,font,'\uF0F6 打开',rc.width()/2+190*dpiScaleX, rc.top+20);
  86.                     }
  87.                     
  88.             }else {
  89.                 font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-12*dpiScaleY);
  90.                 gdi.textOut(hdc,font,'\uF0F6 打开',rc.width()/2+190*dpiScaleX, rc.top+20);
  91.             }
  92.             
  93.             if(filesel){
  94.                 var x,y = win.getMessagePos();  
  95.                 var item = winform.listbox.hitTest(x,y,true);

  96.                 if((drawItem.itemID+1) == item){
  97.                         font = ::LOGFONT(weight=500;color=0x6112FF;name='FontAwesome';h=-12*dpiScaleY);
  98.                         gdi.textOut(hdc,font,'\uF115 文件夹',rc.width()/2+260*dpiScaleX, rc.top+20);
  99.                     }else {
  100.                     font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-12*dpiScaleY);
  101.                     gdi.textOut(hdc,font,'\uF115 文件夹',rc.width()/2+260*dpiScaleX, rc.top+20);
  102.                     }
  103.             }else {
  104.                     font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-12*dpiScaleY);
  105.                     gdi.textOut(hdc,font,'\uF115 文件夹',rc.width()/2+260*dpiScaleX, rc.top+20);
  106.             }

  107.             //文件图标
  108.             win.imageList.shell(0/*_SHIL_LARGE*/).draw(strTab.iImage,hdc,rc.left+20*dpiScaleX,rc.top+10*dpiScaleX);

  109.             //文件名
  110.             font = ::LOGFONT(weight=400;color=0x000000;h=-12*dpiScaleY);
  111.             //gdi.textOut(hdc,font,strTab.text,rc.left+60*dpiScaleX, rc.top+5*dpiScaleY);
  112.             gdi.drawText(hdc,font,strTab.text,::RECT(rc.left+60*dpiScaleX,rc.top,rc.right-rc.width()/2,rc.bottom),0x8000/*_DT_END_ELLIPSIS*/);

  113.             //文件大小
  114.             font = ::LOGFONT(weight=300;color=0xB0B0B0;h=-12*dpiScaleY);
  115.             gdi.textOut(hdc,font,strTab.size,rc.left+60*dpiScaleX, rc.top+20*dpiScaleY);
  116.             
  117.     },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/)
  118. }
  119.    
  120. winform.listbox.wndproc = function(hwnd,message,wParam,lParam){
  121.     select(message) {
  122.         case 0x200/*_WM_MOUSEMOVE*/ {
  123.             var x,y = win.getMessagePos();  
  124.             var item = winform.listbox.hitTest(x,y,true);
  125.             if(item == null){
  126.                 return ;
  127.             }
  128.             
  129.             var dpiScaleX,dpiScaleY  = winform.listbox.dpiScale(1,1);   
  130.               
  131.             if(listboxsel == item){   /* 若鼠标在同一行item内游动 */
  132.                     x,y = win.toClient(winform.listbox.hwnd,x,y);
  133.                     for(i=1;3;1){
  134.                             select(i) {
  135.                                     case 1 {        //open
  136.                                             var rc = winform.listbox.getItemRect(item);
  137.                                             rc.left = rc.width()/2+190*dpiScaleX;
  138.                                             rc.right = rc.left+60*dpiScaleX;
  139.                                             rc.top = rc.top+10*dpiScaleX;
  140.                                             rc.bottom = rc.bottom-10*dpiScaleX ;
  141.                                             
  142.                                             //判断鼠标游动的区间是不是在[删除]按钮范围
  143.                                             if( rc.contains(x,y) ){
  144.                                                 if(opensel == false){    //鼠标从[删除]按钮外部移动到内部区域
  145.                                                     opensel = true;
  146.                                                     //设置更新区,并更新
  147.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  148.                                                     winform.listbox.update();
  149.                                                     break ;
  150.                                                 }
  151.                                                 continue ; //一直在内部区域游动,则不更新
  152.                                             }else {
  153.                                                 if(opensel == true){ //鼠标从内到外
  154.                                                     opensel = false;
  155.                                                     //设置更新区,并更新
  156.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  157.                                                     winform.listbox.update();
  158.                                                     break ;
  159.                                                 }
  160.                                                 continue ; //一直在外部区域游动,则不更新
  161.                                             }
  162.                                                                     
  163.                                             
  164.                                     }
  165.                                     case 2 {        //file
  166.                                             var filerc = winform.listbox.getItemRect(item);
  167.                                             filerc.left = filerc.width()/2+260*dpiScaleX;
  168.                                             filerc.right = filerc.left+70*dpiScaleX;
  169.                                             filerc.top = filerc.top+10*dpiScaleX;
  170.                                             filerc.bottom = filerc.bottom-10*dpiScaleX ;
  171.                                             //判断鼠标游动的区间是不是在[删除]按钮范围
  172.                                             if( filerc.contains(x,y) ){
  173.                                                 if(filesel == false){    //鼠标从[删除]按钮外部移动到内部区域
  174.                                                     filesel = true;
  175.                                                     //设置更新区,并更新
  176.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  177.                                                     winform.listbox.update();
  178.                                                     break;
  179.                                                 }
  180.                                                 continue ; //一直在内部区域游动,则不更新
  181.                                             }else {
  182.                                                 if(filesel == true){ //鼠标从内到外
  183.                                                     filesel = false;
  184.                                                     //设置更新区,并更新
  185.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  186.                                                     winform.listbox.update();
  187.                                                     break ;
  188.                                                 }
  189.                                                 continue ; //一直在外部区域游动,则不更新
  190.                                             }
  191.                                             
  192.                                     }
  193.                                     case 3 {        //del
  194.                                             var delrc = winform.listbox.getItemRect(item);
  195.                                             delrc.left = delrc.width()/2+345*dpiScaleX;
  196.                                             delrc.top = delrc.top+10*dpiScaleX;
  197.                                             delrc.bottom = delrc.bottom-10*dpiScaleX ;
  198.                                             
  199.                                             //判断鼠标游动的区间是不是在[删除]按钮范围
  200.                                             if( delrc.contains(x,y) ){
  201.                                                 if(colorsel == false){    //鼠标从[删除]按钮外部移动到内部区域
  202.                                                     colorsel = true;
  203.                                                     //设置更新区,并更新
  204.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  205.                                                     winform.listbox.update();
  206.                                                     break;
  207.                                                 }
  208.                                                 continue ; //一直在内部区域游动,则不更新
  209.                                             }else {
  210.                                                 if(colorsel == true){ //鼠标从内到外
  211.                                                     colorsel = false;
  212.                                                     //设置更新区,并更新
  213.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  214.                                                     winform.listbox.update();
  215.                                                     break ;
  216.                                                 }
  217.                                                 continue ; //一直在外部区域游动,则不更新
  218.                                             }
  219.                                     }
  220.                             }
  221.                     }
  222.                         return ;
  223.                 }
  224.                 else {
  225.                     //设置hover效果
  226.                     listboxsel = item;
  227.                     if(beforesel == null){        //第一次执行,初始化
  228.                             beforesel = listboxsel;
  229.                            
  230.                     }else {
  231.                             //先关闭上次绘制区域
  232.                             if(beforesel){
  233.                                     winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0)        
  234.                             }
  235.                             beforesel = listboxsel;
  236.                     }
  237.                     //绘制当前区域
  238.                     winform.listbox.invalidate(winform.listbox.getItemRect(item));
  239.                     winform.listbox.update();
  240.                 }
  241.             }
  242.             case 0x202/*_WM_LBUTTONUP*/ {
  243.                     //删除功能
  244.                     if(colorsel){        /* 若鼠标在删除按钮区域内单击了 */
  245.                             var selindex = winform.listbox.selIndex
  246.                             var strTab = winform.listbox.getItemText(selindex);
  247.                             var tabStr = eval(strTab)
  248.                             var ret = winform.msgboxTest("您确定要删除 ["++tabStr.text++"] 文件吗?");
  249.                             if(ret){
  250.                                     winform.listbox.delete(selindex);
  251.                                     colorsel = false;
  252.                             }
  253.                             return ;
  254.                     };
  255.                     //打开文件
  256.                     if(opensel){        /* 若鼠标在打开按钮区域内单击了 */
  257.                             var selindex = winform.listbox.selIndex
  258.                             var strTab = winform.listbox.getItemText(selindex);
  259.                             var tabStr = eval(strTab)
  260.                             process.execute(tabStr.filePath);
  261.                             return ;
  262.                     }
  263.                     //打开文件夹
  264.                     if(filesel){        /* 若鼠标在打开按钮区域内单击了 */
  265.                             var selindex = winform.listbox.selIndex
  266.                             var strTab = winform.listbox.getItemText(selindex);
  267.                             var tabStr = eval(strTab)
  268.                             var path = io.splitpath(tabStr.filePath);
  269.                             process.execute(path.dir);
  270.                             return ;
  271.                     }
  272.             }
  273.     }
  274. }

  275. winform.button.oncommand = function(id,event){
  276.     var sstab = {};
  277.     table.assign(sstab,{ iImage = 0; text = "增加示例行"; size = "7.7 MB" });
  278.     winform.listbox.add(table.tostring(sstab))        
  279. }

  280. var files,,dirs = ..fsys.list(dirPath);
  281. for(i=1;#files){
  282.     filename = files[ i ];
  283.     var sfi = fsys.info.get(files[filename],0x10/*_SHGFI_USEFILEATTRIBUTES*/ | 0x4000/*_SHGFI_SYSICONINDEX*/ );
  284.    
  285.     var file = fsys.file(files[filename]);
  286.     if(!file){
  287.         continue;
  288.     }
  289.    
  290.     var fileSize =  file.size64().format();
  291.     table.assign(boxTab,{ iImage = sfi.iIcon; text = filename; size = fileSize ; filePath = files[filename] });
  292.     winform.listbox.add(table.tostring(boxTab))
  293. }


  294. winform.show();
  295. win.loopMessage();
复制代码

38

主题

129

回帖

1045

积分

荣誉会员

积分
1045
 楼主| 发表于 2018-9-16 18:16:18 | 显示全部楼层
第一更:
浏览目录文件,添加到listbox中,并显示其系统图标和文件大小等信息
1537092326841860.png

完整代码如下: (测试的话,自己手动把目录路径改改再运行)
  1. //GDI自绘
  2. import win.ui;
  3. /*DSG{{*/
  4. var winform = win.form(text="listbox自绘(GDI方式)";right=757;bottom=467)
  5. winform.add(
  6. 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}
  7. )
  8. /*}}*/

  9. winform.listbox.onMeasureItem = function(measureItem){
  10.     measureItem.itemHeight = 51;  
  11. }
  12. import win.imageList;
  13. import console
  14. console.open()

  15. var listboxsel = null;
  16. var beforesel = null;

  17. import fsys;
  18. import fsys.info;
  19. import fsys.file;
  20. var filename;
  21. var boxTab = {};

  22. var files,,dirs = ..fsys.list("D:\360安全浏览器下载");
  23. for(i=1;#files)
  24. {
  25.         filename = files[ i ];
  26.         var sfi = fsys.info.get(files[filename],0x10/*_SHGFI_USEFILEATTRIBUTES*/ | 0x4000/*_SHGFI_SYSICONINDEX*/ );
  27.         var fileSize = tonumber(fsys.file(files[filename]).size64());
  28.         if(fileSize/1024 >= 1){
  29.             if(fileSize/1024/1024 >= 1){
  30.                 sizes = tostring(math.round(fileSize/1024/1024,2))++" MB";
  31.             }else {
  32.                 sizes = tostring(math.round(fileSize/1024,2))++" KB";
  33.             }
  34.                
  35.         }else {
  36.             sizes = tostring(fileSize)++" B";
  37.         }
  38.        
  39.         table.assign(boxTab,{ iImage = sfi.iIcon; text = string.toUtf16(filename); size = sizes });
  40.         winform.listbox.add(table.tostring(boxTab))
  41. }

  42. winform.listbox.onDrawItem = function(drawItem){
  43.      gdi.selectBrush(
  44.      
  45.         function(hdc,pen,brush){
  46.             //获取并分解需要显示的数据(字符串转表)
  47.                         var strTab = eval(winform.listbox.getItemText(drawItem.itemID + 1))
  48.             var rc = drawItem.rcItem;
  49.                     gdi.fillRect(hdc,0xFFFFFF,rc);
  50.                     if (drawItem.itemID > 0) {  
  51.                             gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top);
  52.                     }
  53.                    
  54.                     if (drawItem.itemState & 1/*_ODS_SELECTED*/) {  
  55.                             gdi.fillRect(hdc,0xFFF5E2,rc);
  56.                     }else {
  57.                             if(listboxsel == (drawItem.itemID+1)){
  58.                                     gdi.fillRect(hdc,0xEEB7FF,rc);
  59.                             }       
  60.                     }
  61.                    
  62.                     //加图标测试       
  63.                     win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(strTab.iImage,hdc,rc.left+20,rc.top+10);
  64.                    
  65.                     win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.width()/2+200,rc.top+10);
  66.                     var font = ::LOGFONT(weight=300;color=0x9C9C9C);
  67.                     gdi.textOut(hdc,font,"打开",rc.width()/2+235, rc.top+20);
  68.                     win.imageList.shell( 0/*_SHIL_JUMBO*/ ).draw(1,hdc,rc.width()/2+270,rc.top+10);
  69.                     gdi.textOut(hdc,font,"文件夹",rc.width()/2+300, rc.top+20);
  70.                     //加文字测试
  71.                     font = ::LOGFONT(weight=400;color=0x000000);
  72.                     gdi.textOut(hdc,font,strTab.text,rc.left+60, rc.top+10);
  73.                     font = ::LOGFONT(weight=300;color=0xB0B0B0);
  74.                     gdi.textOut(hdc,font,strTab.size,rc.left+60, rc.top+30);
  75.                    
  76.                    },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/)
  77. }

  78. winform.listbox.wndproc = function(hwnd,message,wParam,lParam){
  79.         if(message == 0x200/*_WM_MOUSEMOVE*/){
  80.                
  81.                 var x,y = win.getMessagePos();  
  82.         var item = winform.listbox.hitTest(x,y,true);
  83.         if(item == null){
  84.                 return ;
  85.         }
  86.         if(listboxsel == item){
  87.                         return ;
  88.                 }else {
  89.                         listboxsel = item;
  90.                         if(beforesel == null){
  91.                                 beforesel = listboxsel;
  92.                                
  93.                         }else {
  94.                                 if(beforesel){
  95.                                         winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0)       
  96.                                 }
  97.                                 beforesel = listboxsel;
  98.                         }
  99.                         winform.listbox.invalidate(winform.listbox.getItemRect(item))
  100.                         winform.listbox.update();
  101.                 }
  102.         }

  103. }

  104. winform.show();
  105. win.loopMessage();
复制代码

38

主题

129

回帖

1045

积分

荣誉会员

积分
1045
 楼主| 发表于 2018-9-17 12:59:07 | 显示全部楼层
第二更: 增加右侧[删除]按钮和功能,并增加此按钮的动态hover效果.
GIF33.gif
  1. //GDI自绘
  2. import win.ui;
  3. import fonts.fontAwesome;
  4. /*DSG{{*/
  5. var winform = win.form(text="listbox自绘(GDI方式)";right=778;bottom=445;border="dialog frame")
  6. winform.add(
  7. button={cls="button";text="增加行";left=0;top=385;right=779;bottom=436;z=2};
  8. 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}
  9. )
  10. /*}}*/

  11. winform.listbox.onMeasureItem = function(measureItem){
  12.     measureItem.itemHeight = 51;  
  13. }
  14. import win.imageList;
  15. import console
  16. console.open()

  17. var listboxsel = null;
  18. var beforesel = null;
  19. var colorsel = false;

  20. import fsys;
  21. import fsys.info;
  22. import fsys.file;
  23. var filename;
  24. var boxTab = {};

  25. var files,,dirs = ..fsys.list("D:\BaiduNetdiskDownload");
  26. for(i=1;#files)
  27. {
  28.         filename = files[ i ];
  29.         var sfi = fsys.info.get(files[filename],0x10/*_SHGFI_USEFILEATTRIBUTES*/ | 0x4000/*_SHGFI_SYSICONINDEX*/ );
  30.         var fileSize = tonumber(fsys.file(files[filename]).size64());
  31.         if(fileSize/1024 >= 1){
  32.             if(fileSize/1024/1024 >= 1){
  33.                 sizes = tostring(math.round(fileSize/1024/1024,2))++" MB";
  34.             }else {
  35.                 sizes = tostring(math.round(fileSize/1024,2))++" KB";
  36.             }
  37.                
  38.         }else {
  39.             sizes = tostring(fileSize)++" B";
  40.         }
  41.        
  42.         table.assign(boxTab,{ iImage = sfi.iIcon; text = filename; size = sizes });
  43.         winform.listbox.add(table.tostring(boxTab))
  44. }

  45. winform.listbox.onDrawItem = function(drawItem){
  46.      gdi.selectBrush(
  47.      
  48.         function(hdc,pen,brush){
  49.             //获取并分解需要显示的数据(字符串转表)
  50.                         var strTab = eval(winform.listbox.getItemText(drawItem.itemID + 1))
  51.             var rc = drawItem.rcItem;
  52.                     gdi.fillRect(hdc,0xFFFFFF,rc);
  53.                     if (drawItem.itemID > 0) {  
  54.                             gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top);
  55.                     }
  56.                    
  57.                     if (drawItem.itemState & 1/*_ODS_SELECTED*/) {  
  58.                             gdi.fillRect(hdc,0xFFF5E2,rc);
  59.                             if(colorsel){
  60.                                     font = ::LOGFONT(weight=700;color=0x6112FF;name='FontAwesome';h=-16);
  61.                                     gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20);
  62.                             }else {
  63.                                     font = ::LOGFONT(weight=700;color=0x9C9C9C;name='FontAwesome';h=-16);
  64.                                     gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20);
  65.                             }
  66.                            
  67.                     }else {
  68.                             if(listboxsel == (drawItem.itemID+1)){
  69.                                     gdi.fillRect(hdc,0xEEB7FF,rc);
  70.                             }       
  71.                     }
  72.                    
  73.                     //加图标测试       
  74.                     win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(strTab.iImage,hdc,rc.left+20,rc.top+10);
  75.                     win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(0,hdc,rc.width()/2+200,rc.top+10);
  76.                     var font = ::LOGFONT(weight=300;color=0x9C9C9C;);
  77.                     gdi.textOut(hdc,font,"打开",rc.width()/2+235, rc.top+20);
  78.                     win.imageList.shell( 0/*_SHIL_JUMBO*/ ).draw(1,hdc,rc.width()/2+270,rc.top+10);
  79.                     gdi.textOut(hdc,font,"文件夹",rc.width()/2+300, rc.top+20);

  80.                     //加文字测试
  81.                     font = ::LOGFONT(weight=400;color=0x000000);
  82.                     gdi.textOut(hdc,font,strTab.text,rc.left+60, rc.top+10);
  83.                     font = ::LOGFONT(weight=300;color=0xB0B0B0);
  84.                     gdi.textOut(hdc,font,strTab.size,rc.left+60, rc.top+30);
  85.                    
  86.                    },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/)
  87. }

  88. winform.listbox.wndproc = function(hwnd,message,wParam,lParam){
  89.     select(message) {
  90.             case 0x200/*_WM_MOUSEMOVE*/ {
  91.                     var x,y = win.getMessagePos();  
  92.                 var item = winform.listbox.hitTest(x,y,true);
  93.                 if(item == null){
  94.                         return ;
  95.                 }
  96.                
  97.                     if(listboxsel == item){        /* 若鼠标在同一行item内游动 */
  98.                             /* 首先,判断是否要显示[删除]按钮,通过判断鼠标是不是在选中item行内 */
  99.                     if(listboxsel == winform.listbox.selIndex){
  100.                             x,y = win.toClient(winform.listbox.hwnd,x,y);
  101.                                         var rc = winform.listbox.getItemRect(item);
  102.                                         rc.left = rc.width()/2+345;
  103.                                         rc.top = rc.top+20;
  104.                                         rc.bottom = rc.bottom-20 ;
  105.                                         //判断鼠标游动的区间是不是在[删除]按钮范围
  106.                                         if( ::PtInRect(rc,x,y) ){
  107.                                                 if(colorsel == false){        //鼠标从[删除]按钮外部移动到内部区域
  108.                                                         colorsel = true;
  109.                                                         //设置更新区,并更新
  110.                                                         winform.listbox.invalidate(winform.listbox.getItemRect(item))
  111.                                                         winform.listbox.update();
  112.                                                         return;       
  113.                                                 }
  114.                                                 return ; //一直在内部区域游动,则不更新
  115.                                         }else {
  116.                                                 if(colorsel == true){        //鼠标从内到外
  117.                                                         colorsel = false;
  118.                                                         //设置更新区,并更新
  119.                                                         winform.listbox.invalidate(winform.listbox.getItemRect(item))
  120.                                                         winform.listbox.update();
  121.                                                         return ;
  122.                                                 }
  123.                                                 return ; //一直在外部区域游动,则不更新
  124.                                         }        
  125.                     }
  126.                     return ;
  127.                         }else {
  128.                                 //设置hover效果
  129.                                 listboxsel = item;
  130.                                 if(beforesel == null){        //第一次执行,初始化
  131.                                         beforesel = listboxsel;
  132.                                        
  133.                                 }else {
  134.                                         //先关闭上次绘制区域
  135.                                         if(beforesel){
  136.                                                 winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0)       
  137.                                         }
  138.                                         beforesel = listboxsel;
  139.                                 }
  140.                                 //绘制当前区域
  141.                                 winform.listbox.invalidate(winform.listbox.getItemRect(item));
  142.                                 winform.listbox.update();
  143.                         }
  144.             }
  145.             case 0x202/*_WM_LBUTTONUP*/ {
  146.                     if(colorsel){        /* 若鼠标在删除按钮区域内单击了 */
  147.                                 var selindex = winform.listbox.selIndex
  148.                                 var strTab = winform.listbox.getItemText(selindex);
  149.                                 var tabStr = eval(strTab)
  150.                                 var ret = winform.msgboxTest("您确定要删除 ["++tabStr.text++"] 文件吗?");
  151.                                 if(ret){
  152.                                         winform.listbox.delete(selindex);
  153.                                         colorsel = false;
  154.                                 }
  155.                         }
  156.             }
  157.             else {
  158.             }
  159.     }
  160. }

  161. winform.button.oncommand = function(id,event){
  162.     var sstab = {};
  163.         table.assign(sstab,{ iImage = 0; text = "增加示例行"; size = "7.7 MB" });
  164.         winform.listbox.add(table.tostring(sstab))       
  165. }

  166. winform.show();
  167. win.loopMessage();
复制代码

38

主题

129

回帖

1045

积分

荣誉会员

积分
1045
 楼主| 发表于 2018-9-17 15:00:46 | 显示全部楼层
最后一更:
修改界面中[删除] / [打开] / [文件夹] 鼠标样式效果,并增加对应功能.
修改界面: 不选中项目的时候,不出现 功能 按键.

本次测试基本结束了. 后面有时间继续简化下, 看看能不能封装下.
其他的一些界面问题就不再写了.

GIF.gif

  1. //GDI自绘
  2. import win.ui;
  3. import fonts.fontAwesome;
  4. /*DSG{{*/
  5. var winform = win.form(text="listbox自绘(GDI方式)";right=778;bottom=445;border="dialog frame")
  6. winform.add(
  7. button={cls="button";text="增加行";left=0;top=385;right=779;bottom=436;z=2};
  8. 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}
  9. )
  10. /*}}*/

  11. winform.listbox.onMeasureItem = function(measureItem){
  12.     measureItem.itemHeight = 51;  
  13. }

  14. import win.imageList;
  15. import process;

  16. var listboxsel = null;
  17. var beforesel = null;
  18. var colorsel = false;
  19. var opensel = false;
  20. var filesel = false;

  21. import fsys;
  22. import fsys.info;
  23. import fsys.file;
  24. var filename;
  25. var boxTab = {};

  26. var files,,dirs = ..fsys.list("D:\BaiduNetdiskDownload");
  27. for(i=1;#files)
  28. {
  29.         filename = files[ i ];
  30.         var sfi = fsys.info.get(files[filename],0x10/*_SHGFI_USEFILEATTRIBUTES*/ | 0x4000/*_SHGFI_SYSICONINDEX*/ );
  31.         var fileSize = tonumber(fsys.file(files[filename]).size64());
  32.         if(fileSize/1024 >= 1){
  33.             if(fileSize/1024/1024 >= 1){
  34.                 sizes = tostring(math.round(fileSize/1024/1024,2))++" MB";
  35.             }else {
  36.                 sizes = tostring(math.round(fileSize/1024,2))++" KB";
  37.             }
  38.                
  39.         }else {
  40.             sizes = tostring(fileSize)++" B";
  41.         }
  42.        
  43.         table.assign(boxTab,{ iImage = sfi.iIcon; text = filename; size = sizes ; filePath = files[filename] });
  44.         winform.listbox.add(table.tostring(boxTab))
  45. }

  46. winform.listbox.onDrawItem = function(drawItem){
  47.      gdi.selectBrush(
  48.      
  49.         function(hdc,pen,brush){
  50.             //获取并分解需要显示的数据(字符串转表)
  51.                         var strTab = eval(winform.listbox.getItemText(drawItem.itemID + 1))
  52.             var rc = drawItem.rcItem;
  53.                     gdi.fillRect(hdc,0xFFFFFF,rc);
  54.                     if (drawItem.itemID > 0) {  
  55.                             gdi.drawLine(hdc,rc.left, rc.top,rc.right, rc.top);
  56.                     }                
  57.                     if (drawItem.itemState & 1/*_ODS_SELECTED*/) {  
  58.                             gdi.fillRect(hdc,0xFFF5E2,rc);
  59.                             //删除文件
  60.                             if(colorsel){
  61.                                     font = ::LOGFONT(weight=700;color=0x6112FF;name='FontAwesome';h=-16);
  62.                                     gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20);
  63.                             }else {
  64.                                     font = ::LOGFONT(weight=700;color=0x9C9C9C;name='FontAwesome';h=-16);
  65.                                     gdi.textOut(hdc,font,'\uF057',rc.width()/2+345, rc.top+20);
  66.                             }
  67.                             //打开文件
  68.                             if(opensel){
  69.                                     font = ::LOGFONT(weight=500;color=0x6112FF;name='FontAwesome';h=-16);
  70.                                     gdi.textOut(hdc,font,'\uF0F6 打开',rc.width()/2+190, rc.top+20);
  71.                             }else {
  72.                                     font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-16);
  73.                                     gdi.textOut(hdc,font,'\uF0F6 打开',rc.width()/2+190, rc.top+20);
  74.                             }
  75.                             //打开文件夹
  76.                             if(filesel){
  77.                                     font = ::LOGFONT(weight=500;color=0x6112FF;name='FontAwesome';h=-16);
  78.                                     gdi.textOut(hdc,font,'\uF115 文件夹',rc.width()/2+260, rc.top+20);
  79.                             }else {
  80.                                     font = ::LOGFONT(weight=300;color=0x9C9C9C;name='FontAwesome';h=-16);
  81.                                     gdi.textOut(hdc,font,'\uF115 文件夹',rc.width()/2+260, rc.top+20);
  82.                             }
  83.                     }else {
  84.                             if(listboxsel == (drawItem.itemID+1)){
  85.                                     gdi.fillRect(hdc,0xEEB7FF,rc);
  86.                             }       
  87.                     }

  88.                     //文件图标
  89.                     win.imageList.shell( 0/*_SHIL_LARGE*/ ).draw(strTab.iImage,hdc,rc.left+20,rc.top+10);
  90.                     //文件名
  91.                     font = ::LOGFONT(weight=400;color=0x000000);
  92.                     gdi.textOut(hdc,font,strTab.text,rc.left+60, rc.top+10);
  93.                     //文件大小
  94.                     font = ::LOGFONT(weight=300;color=0xB0B0B0);
  95.                     gdi.textOut(hdc,font,strTab.size,rc.left+60, rc.top+30);
  96.                    
  97.                    },drawItem.hDC,0xF5FDFF/*背景色*/,0xEEEEEE/*画笔色*/)
  98. }

  99. winform.listbox.wndproc = function(hwnd,message,wParam,lParam){
  100.     select(message) {
  101.         case 0x200/*_WM_MOUSEMOVE*/ {
  102.             var x,y = win.getMessagePos();  
  103.             var item = winform.listbox.hitTest(x,y,true);
  104.             if(item == null){
  105.                 return ;
  106.             }
  107.             
  108.             if(listboxsel == item){   /* 若鼠标在同一行item内游动 */
  109.                 /* 首先,判断是否要显示[删除]按钮,通过判断鼠标是不是在选中item行内 */
  110.                 if(listboxsel == winform.listbox.selIndex){
  111.                     x,y = win.toClient(winform.listbox.hwnd,x,y);
  112.                     for(i=1;3;1){
  113.                             select(i) {
  114.                                     case 1 {        //open
  115.                                             var rc = winform.listbox.getItemRect(item);
  116.                                             rc.left = rc.width()/2+190;
  117.                                             rc.right = rc.left+60;
  118.                                             rc.top = rc.top+10;
  119.                                             rc.bottom = rc.bottom-10 ;
  120.                                             //判断鼠标游动的区间是不是在[删除]按钮范围
  121.                                             if( ::PtInRect(rc,x,y) ){
  122.                                                 if(opensel == false){    //鼠标从[删除]按钮外部移动到内部区域
  123.                                                     opensel = true;
  124.                                                     //设置更新区,并更新
  125.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  126.                                                     winform.listbox.update();
  127.                                                     break ;
  128.                                                 }
  129.                                                 continue ; //一直在内部区域游动,则不更新
  130.                                             }else {
  131.                                                 if(opensel == true){ //鼠标从内到外
  132.                                                     opensel = false;
  133.                                                     //设置更新区,并更新
  134.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  135.                                                     winform.listbox.update();
  136.                                                     break ;
  137.                                                 }
  138.                                                 continue ; //一直在外部区域游动,则不更新
  139.                                             }
  140.                                                                    
  141.                                            
  142.                                     }
  143.                                     case 2 {        //file
  144.                                             var filerc = winform.listbox.getItemRect(item);
  145.                                             filerc.left = filerc.width()/2+260;
  146.                                             filerc.right = filerc.left+70;
  147.                                             filerc.top = filerc.top+10;
  148.                                             filerc.bottom = filerc.bottom-10 ;
  149.                                             //判断鼠标游动的区间是不是在[删除]按钮范围
  150.                                             if( ::PtInRect(filerc,x,y) ){
  151.                                                 if(filesel == false){    //鼠标从[删除]按钮外部移动到内部区域
  152.                                                     filesel = true;
  153.                                                     //设置更新区,并更新
  154.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  155.                                                     winform.listbox.update();
  156.                                                     break;
  157.                                                 }
  158.                                                 continue ; //一直在内部区域游动,则不更新
  159.                                             }else {
  160.                                                 if(filesel == true){ //鼠标从内到外
  161.                                                     filesel = false;
  162.                                                     //设置更新区,并更新
  163.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  164.                                                     winform.listbox.update();
  165.                                                     break ;
  166.                                                 }
  167.                                                 continue ; //一直在外部区域游动,则不更新
  168.                                             }
  169.                                            
  170.                                     }
  171.                                     case 3 {        //del
  172.                                             var delrc = winform.listbox.getItemRect(item);
  173.                                             delrc.left = delrc.width()/2+345;
  174.                                             delrc.top = delrc.top+20;
  175.                                             delrc.bottom = delrc.bottom-20 ;
  176.                                             //判断鼠标游动的区间是不是在[删除]按钮范围
  177.                                             if( ::PtInRect(delrc,x,y) ){
  178.                                                 if(colorsel == false){    //鼠标从[删除]按钮外部移动到内部区域
  179.                                                     colorsel = true;
  180.                                                     //设置更新区,并更新
  181.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  182.                                                     winform.listbox.update();
  183.                                                     break;
  184.                                                 }
  185.                                                 continue ; //一直在内部区域游动,则不更新
  186.                                             }else {
  187.                                                 if(colorsel == true){ //鼠标从内到外
  188.                                                     colorsel = false;
  189.                                                     //设置更新区,并更新
  190.                                                     winform.listbox.invalidate(winform.listbox.getItemRect(item))
  191.                                                     winform.listbox.update();
  192.                                                     break ;
  193.                                                 }
  194.                                                 continue ; //一直在外部区域游动,则不更新
  195.                                             }
  196.                                     }
  197.                             }
  198.                     }
  199.                 }
  200.                 return ;
  201.                         }else {
  202.                                 //设置hover效果
  203.                                 listboxsel = item;
  204.                                 if(beforesel == null){        //第一次执行,初始化
  205.                                         beforesel = listboxsel;
  206.                                        
  207.                                 }else {
  208.                                         //先关闭上次绘制区域
  209.                                         if(beforesel){
  210.                                                 winform.listbox.invalidate(winform.listbox.getItemRect(beforesel),0)       
  211.                                         }
  212.                                         beforesel = listboxsel;
  213.                                 }
  214.                                 //绘制当前区域
  215.                                 winform.listbox.invalidate(winform.listbox.getItemRect(item));
  216.                                 winform.listbox.update();
  217.                         }
  218.             }
  219.             case 0x202/*_WM_LBUTTONUP*/ {
  220.                     //删除功能
  221.                     if(colorsel){        /* 若鼠标在删除按钮区域内单击了 */
  222.                                 var selindex = winform.listbox.selIndex
  223.                                 var strTab = winform.listbox.getItemText(selindex);
  224.                                 var tabStr = eval(strTab)
  225.                                 var ret = winform.msgboxTest("您确定要删除 ["++tabStr.text++"] 文件吗?");
  226.                                 if(ret){
  227.                                         winform.listbox.delete(selindex);
  228.                                         colorsel = false;
  229.                                 }
  230.                                 return ;
  231.                         };
  232.                         //打开文件
  233.                         if(opensel){        /* 若鼠标在打开按钮区域内单击了 */
  234.                                 var selindex = winform.listbox.selIndex
  235.                                 var strTab = winform.listbox.getItemText(selindex);
  236.                                 var tabStr = eval(strTab)
  237.                                 process.execute(tabStr.filePath);
  238.                                 return ;
  239.                         }
  240.                         //打开文件夹
  241.                         if(filesel){        /* 若鼠标在打开按钮区域内单击了 */
  242.                                 var selindex = winform.listbox.selIndex
  243.                                 var strTab = winform.listbox.getItemText(selindex);
  244.                                 var tabStr = eval(strTab)
  245.                                 var path = io.splitpath(tabStr.filePath);
  246.                                 process.execute(path.dir);
  247.                                 return ;
  248.                         }
  249.             }
  250.             else {
  251.             }
  252.     }
  253. }

  254. winform.button.oncommand = function(id,event){
  255.     var sstab = {};
  256.         table.assign(sstab,{ iImage = 0; text = "增加示例行"; size = "7.7 MB" });
  257.         winform.listbox.add(table.tostring(sstab))       
  258. }

  259. winform.show();
  260. win.loopMessage();
复制代码

评分

参与人数 1 +20 收起 理由
Danboy + 20 很给力!

查看全部评分

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

手机版|未经许可严禁引用或转载本站文章|aardio.com|aardio 官方社区 ( 皖ICP备09012014号 )

GMT+8, 2025-6-4 21:40 , Processed in 0.070979 second(s), 29 queries .

Powered by Discuz! X3.5

Copyright © 2001-2024 Tencent Cloud.

快速回复 返回顶部 返回列表