plus模拟美化和替换listview的滚动条

By admin at 2020-04-09 • 1人收藏 • 287人看过

这个是针对listview的滚动条的。 上次是针对listbox来的,不要搞混了。

listview和listbox不一样的地方在于它有header头,而且编写过程中发现,listview即使项目已经移动到了底部,此时仍然发送sendmessage下移消息它仍然会继续下移, 所以,这个代码比listbox要多一个判断:是不是已经显示了所有的项

GIF.gif

方便起见我没有改这个listview滚动条自绘库的名称, 需要的可以自己修改

plusExbar.aardio 库代码如下:

//plusExbar 模拟滚动条
class plusExbar{
    //绑定的listbox,与之绑定的plus,listbox每项的行高,前景色,背景色
    ctor( listview,plus,iheight,foreColor=0xFF0097DE,backColor=0x757A7A7A ){
        plus.skin({
            background={
                default=backColor
            };
            color={
                default=foreColor;
            }
        })
        //listview有可能有header,那么需要先减去header的高度
        var headerH = listview.getHeader();
    	x,y,cx,cy = ..win.getPos(headerH);
        var max = listview.count-..math.floor((listview.height-cy)/iheight);
        var min = 1;
        plus.setTrackbarRange(max,1);
         
        if(max>0){
                //锁定最小滑块大小20
            if(..math.round(plus.height/max)<=20){
                plus.foreTop = 20;
                var max = listview.count-..math.floor((listview.height-cy-20)/iheight);
            }else{
                plus.foreTop = ..math.round(plus.height/max);
            }   
        }else {
            plus.foreTop = plus.height;
        }
        plus.progressPos = max;
         
        listview.scrollFunc = function( num ){
            plus.progressPos +=num; 
        }
        plus.onPosChanged = function( pos,thumbTrack ){
            if(thumbTrack){
                
                var goto = max-pos+1;
                var index = listview.hitTest(1,cy+1);
                if(index==null){
                	return;
                }
                if(goto == index){
                    //null
                }else {
                    if(goto>index){
                        for(i=1;goto-index;1){
                            ::SendMessageInt(listview.hwnd, 0x115/*_WM_VSCROLL*/, 1, 0); 
                        }   
                    }else {
                        for(i=1;index-goto;1){
                            ::SendMessageInt(listview.hwnd, 0x115/*_WM_VSCROLL*/, 0, 0);
                        }
                    }   
                }
                 
            }
        }
        plus.orphanWindow(true)
    };
}

如上介绍的, 使用的时候比listbox要多判断一句话:

使用示例如下:

import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=457;bottom=535)
winform.add(
button={cls="button";text="Button";left=72;top=465;right=204;bottom=517;z=3};
listview={cls="listview";left=49;top=26;right=400;bottom=422;edge=1;z=1};
plus={cls="plus";left=432;top=26;right=439;bottom=420;bgcolor=-8750470;border={radius=4};color=14587648;foreTop=33;paddingLeft=1;paddingRight=1;z=2}
)
/*}}*/

//移除列标题
//winform.listview.modifyStyle(,0x4000/*_LVS_NOCOLUMNHEADER*/)
//移除滚动条
winform.listview.modifyStyle(,0x2000/*_LVS_NOSCROLL*/)
winform.listview.insertColumn("列标题3",100) 
winform.listview.insertColumn("列标题2",100) 
winform.listview.insertColumn("列标题1",100) 
for(i=1;59;1){
winform.listview.addItem( { 
    text={i++"行内容";"1";"1,2"} 
} )    
 
}
 
winform.listview.wndproc = function(hwnd,message,wParam,lParam){
    if(message == 0x20A/*_WM_MOUSEWHEEL*/){  //滚轮消息
        var wheelDelta = ..raw.convert({int wParam=wParam },{word vk;word delta}).delta;
        if( wheelDelta > 0 ){
            ::SendMessageInt(winform.listview.hwnd, 0x115/*_WM_VSCROLL*/, 0, 0);
            if(winform.listview.scrollFunc){
                    winform.listview.scrollFunc(1);
            }
        }else {
           //判断最后一行是不是最后一行 
           var index = winform.listview.hitTest(1,winform.listview.height-1);
           	if(index==null or index>winform.listview.count){
           		return;
           	} 
           	::SendMessageInt(winform.listview.hwnd, 0x115/*_WM_VSCROLL*/, 1, 0);
            if(winform.listview.scrollFunc){
                    winform.listview.scrollFunc(-1);
            } 
        }
        return 0;
    };
}

import plusExbar;
plusExbar(winform.listview,winform.plus,20,0xFFE057B6);
 
 
winform.show();
win.loopMessage();
return winform;


2 个回复 | 最后更新于 2020-04-09
2020-04-09   #1

很聪明,简单的代码实现了炫酷的效果。

listview.wndproc 其实可以写到扩展库里会更方便, wndproc可以重复赋值,所以不影响控件继续增加 wndproc。

另外这个关于最后一行的判断实际上可以简化,可以这样写:

if( plus.stepProgress(-1,true) ){

      :SendMessageInt(winform.listview.hwnd, 0x115/*_WM_VSCROLL*/, 1, 0);

}  

plus.stepProgress(-1,true) 函数会自己判断是不是到头了,我们已经知道滚动条的大小,何必去 hitTest再探测一次。

所以建议改成这样:

listview.wndproc = function(hwnd,message,wParam,lParam){
    if(message == 0x20A/*_WM_MOUSEWHEEL*/){ 
        if( ::HIWORD(wParam) & 0x8000  ){ 
            if( plus.stepProgress(-1,true) ){
            	::SendMessageInt(winform.listview.hwnd, 0x115/*_WM_VSCROLL*/, 1, 0);
            }  
        }
        else { 
            ::SendMessageInt(listview.hwnd, 0x115/*_WM_VSCROLL*/, 0, 0);
            plus.stepProgress(1,true)
            
        }
        return 0;
    };
}



2020-04-09   #2

回复#1 @jacen :

刚刚把您的那个代码放到plusExbar库里面, 然后删除掉winform里面的listview回调,

运行一切ok!

按照这样写,确实简化好多代码,棒

登录后方可回帖

登 录
信息栏
本站永久域名:HtmLayout.Cn
纯私人站,当笔记本用的,学到哪写到哪,目前正在学aardio+halcon机器视觉.
Sciter中文在线文档Sciter在线学习文档
本 站 主 站:Stm32cube中文网
Aardio 官方站:Aardio官方
Aardio最新功能:Aardio官方更新日志
aardio在线手册Aardio在线手册
C大Aardio论坛:Aar爱好者论坛
简码教程网:简码编程
AARDIO语言QQ群:70517368
赞助商:才仁机械
下载站:非凡软件站
Loading...