改造listview使其实现表格内编辑框editbox和下拉列表框combobox功能
By
admin
at 2022-10-29 • 1人收藏 • 1923人看过
一直以来winform的listview都只是作为数据输出显示来用, 想要实现数据的双向操作比较难
之前都需要用其他表格类控件实现这个双击编辑文本,双击实现下拉列表框选择文本功能, 而且其中有很大一部分是ocx组件,
那么就需要在客户电脑上regsvr32 注册它, 这样就需要管理员权限, 这样操作并不是很好,
于是考虑着手动改造listview使其满足我的需求.
还好, aardio范例里有个数据视图win.ui.grid的库可供参考, 我就是根据这个库内的实现方法来升级改造的.
下面我在原listview grid基础上增加了, 双击指定列 可直接编辑文本 / 弹出下拉框选择文本 功能.
listviewEX.aardio 库代码如下:
//listview 扩展 import win.ui.ctrl.edit; import win.ui.ctrl.combobox; namespace win.ui; class listviewEx{ ctor( listview ){ this = listview; this.fullRow = 1; this.gridLines = 1; this.columnsEditbox = {};//记录编辑框列号 this.columnsCombobox = {};//记录下拉框列号和列表值 //添加下拉框模板 this.addCtrl( combobox = { cls="combobox";font = LOGFONT( h = -19 );left = 0;top = 0; right = 50;bottom = 50;autoResize = false ;hide = 1;edge = 1;mode="dropdownlist"; wndproc = function( hwnd, message, wParam, lParam ){ var update; var event = owner.event; if( message == 308 ) { update = true; } if( update ){ owner.show(false); var t = this.getItemText(event.iItem,event.iSubItem ); if( t!= owner.text ){ if( this.onEditChanged ) { if( false === this.onEditChanged(owner.text, event.iItem, event.iSubItem)) return; } this.setItemText( owner.text, event.iItem, event.iSubItem ); } if(this.onEditEnd){ this.onEditEnd(event.iItem, event.iSubItem); } } } } ); //添加编辑框模板 this.addCtrl( editBox = { cls="edit";font = LOGFONT( h = -19 );left = 0;top = 0; right = 50;bottom = 50;autoResize = false ;hide = 1;edge = 1; wndproc = function( hwnd, message, wParam, lParam ){ var update; var event = owner.event; if( ( message = 0x8/*_WM_KILLFOCUS*/) || (message == 0x101/*_WM_KEYUP*/ && wParam == 0xD/*_VK_RETURN*/ ) ) { update = true; } elseif(message == 0x201/*_WM_LBUTTONDOWN*/ ){ var x,y = ..win.getMessagePos(lParam) var rc = this.editBox.getClientRect(); if( ! ::PtInRect(rc,x,y) ) update = true; this.editBox.capture = !update; } elseif(message == 0x101/*_WM_KEYUP*/){ if( wParam == 0xD/*_VK_RETURN*/ ) update = true; elseif( wParam == 0x1B/*_VK_ESC*/){ owner.text = this.getItemText(event.iItem,event.iSubItem ); update = true; } } if( update ){ owner.show(false); var t = this.getItemText(event.iItem,event.iSubItem ); if( t!= owner.text ){ if( this.onEditChanged ) { if( false === this.onEditChanged(owner.text, event.iItem, event.iSubItem)) return; } this.setItemText( owner.text, event.iItem, event.iSubItem ); } if(this.onEditEnd){ this.onEditEnd(event.iItem, event.iSubItem); } } } } ) }; //绘制下拉框 beginCombobox = function(iItem,iSubItem){ var combobox = this.combobox; if( ..win.isVisible(combobox.hwnd) ) return; var event = this.combobox.event; if(iItem===null && iSubItem===null) { iItem = event.iItem; iSubItem = event.iSubItem; } else { event = { iItem = iItem; iSubItem = iSubItem; }; combobox.event = event; } combobox.items = this.columnsCombobox[iSubItem]; combobox.selText=this.getItemText(iItem,iSubItem); var rc=this.getItemRect(iItem,iSubItem,,2/*_LVIR_LABEL*/ ); rc.inflate(2,2); combobox.setRect(rc); combobox.showDropDown(); return true; }; //绘制编辑框 beginEdit = function(iItem,iSubItem){ var edit = this.editBox; if( ..win.isVisible(edit.hwnd) ) return; var event = this.editBox.event; if(iItem===null && iSubItem===null) { iItem = event.iItem; iSubItem = event.iSubItem; } else { event = { iItem = iItem; iSubItem = iSubItem; }; edit.event = event; } edit.text=this.getItemText(iItem,iSubItem); var rc=this.getItemRect(iItem,iSubItem,,2/*_LVIR_LABEL*/ ); rc.inflate(2,2); edit.setRect(rc); edit.show(); edit.setFocus(); edit.capture = true; return true; }; //设置下拉框模式 列号/下拉值 setcolumnsCombobox = function(iSubItem,tab,...){ var c = type(tab) === "table" ? tab : {tab,...} this.columnsCombobox[iSubItem] = c; }; //设置编辑框模式 列号 setcolumnsEditbox = function(...){ var c = type(...) === "table" ? ... : {...} for(i,idx in c) this.columnsEditbox[idx] = 1; }; prenotify = { [0xFFFFFFFD/*_NM_DBLCLK*/] = function(id,code,ptr){ var event = this.getNotifyMessage(code,ptr); if( ! event.iItem && event.iSubItem ) return ; //启用 编辑框 if( this.columnsEditbox[event.iSubItem] ){ this.editBox.event = event; this.beginEdit(); }; //启用 下拉框 if( this.columnsCombobox[event.iSubItem] ){ this.combobox.event = event; this.beginCombobox(); }; }; } } /**intellisense() win.ui.listviewEx(__) = 参数必须指定一个listview控件对象\n返回一个可编辑单元格的列表视图对象,\n\n鼠标左键单击单元格、或者按空格键开始编辑,\n回车完成编辑,ESC键撤消编辑,回车+上下方向键快速移动到其他项,\n用户完成编辑后会触发onEditChanged事件.\n!listview. win.ui.listviewEx() = !win_ui_listviewEx. !win_ui_listviewEx.edit = 实现编辑功能的edit控件\n此功能需要扩展listview并实现了编辑功能的的控件才能支持\n!edit. !win_ui_listviewEx.combobox = 实现编辑功能的edit控件\n此功能需要扩展listview并实现了编辑功能的的控件才能支持\n!combobox. !win_ui_listviewEx.onEditChanged(text,iItem,iSubItem) = @.onEditChanged = function(text,iItem,iSubItem){ __/*控件完成编辑,并且文本已变更,\ntext为改变后的文本,iItem为行号,iSubItem为列号\n此功能需要扩展listview并实现了编辑功能的的控件才能支持\n返回false可中止更新显示文本*/ } !win_ui_listviewEx.onEditEnd(iItem,iSubItem) = @.onEditEnd = function(iItem,iSubItem){ __/*控件完成编辑*/ } !win_ui_listviewEx.setTable(__) = 用listview控件显示数据表\n此函数会自动清空控件之前的所有项,\n如果没有创建任何列,则自动创建列\n\n数据表应当包含行组成的数组,\n每行的数据列必须是由列名和列值组成的键值对\n数据表应使用fields包含需要显示的列名称数组\n可以通过fields控制要显的列、以及要显示的顺序\n\n使用sqlite,access,sqlServer等数据库对象提供的getTable函数可获取符合此规格的数据表 !win_ui_listviewEx.setColumns(__) = 用一个字符串数组指定要显示的列\n如果参数为空则清空所有列 !win_ui_listviewEx.setcolumnsCombobox(__) = 可以使用一个或多个参数指定要禁止编辑的列序号,\n也可以用一个数组参数指定多个列序号 !win_ui_listviewEx.setcolumnsEditbox(__) = 可以使用一个或多个参数指定要编辑的列序号,\n也可以用一个数组参数指定多个列序号 !win_ui_listviewEx.clear() = 清空所有行 !win_ui_listviewEx.clear(true) = 清空所有行,并且清空所有列 end intellisense**/
使用的方法如下:
import win.ui; /*DSG{{*/ mainForm = win.form(text="testListviewEx";right=740;bottom=315;bgcolor=16777215) mainForm.add( listview={cls="listview";left=13;top=8;right=729;bottom=309;border=1;db=1;dl=1;dr=1;dt=1;font=LOGFONT(h=-13);fullRow=1;gridLines=1;msel=false;vscroll=1;z=1} ) /*}}*/ import console console.open() import win.ui.listviewEx; var grid = win.ui.listviewEx(mainForm.listview); grid.setcolumnsEditbox(2); grid.setcolumnsCombobox(3,"10","1000","2000","5000"); grid.setcolumnsCombobox(4,{"Z+","Z-","ZNP+","ZNP-"}); grid.setcolumnsCombobox(5,{"急停","减速停"}); grid.onEditChanged = function(text,iItem,iSubItem){ console.log("onEditChanged",text,iItem,iSubItem) } import win.imageList; var iml = win.imageList(1,30); mainForm.listview.setImageList( iml,1/*_LVSIL_NORMAL*/ ); mainForm.listview.setColumns( {"轴号","加减速时间","单脉冲运动量","找零方式","停止方式"}, {60,120,120,100,100}, {2,2,2,2,2}, ); var axisData = {}; for(i=1;20;1){ axisData[i]={}; axisData[i][1] = "轴"++i; axisData[i][2] = "0.1"; axisData[i][3] = "1"; axisData[i][4] = "Z+"; axisData[i][5] = "急停"; } mainForm.listview.items = axisData; mainForm.show(); return win.loopMessage();
主要看上面部分, 上面声明完所有的列功能, 下面还是用listview自己的功能实现代码.
示例工程下载:
欢迎大家来共同升级这个listviewEx库, 因为这个是第一个版本, 难免有很多繁琐或者bug存在.
如果有好的建议或者对代码进行了功能升级, 欢迎在下方留言分享.
谢谢
6 个回复 | 最后更新于 2022-11-10
![the100s](/upload/avatar/middle/203.png)
the100s
2022-10-31
#1
厉害了
不知道你有没有注意,利用原生拓展的listview有时候,数据量比较大的时候,或者光标焦点还在的时候,会出现丢失和闪烁的情况。我之前写过一版,功能比这个可能要稍微多一些,但是使用过程中不理想,代码如下,抛砖引玉,希望大家能搞出更好的
//listviewExx拓展 /*这个库主要是通过父窗体创建唯一控件,然后修改控件的父窗体为listview实现 原因是lisveiw.addCtrl创建的combobox无法正确利用tracker处理消息(因为combobox是符合控件,由editbox和listbox组成的,其他控件都可以), 先在这里记录,待以后有空了研究 */ import fonts.fontAwesome; import win.debounce import win.imageList import win.ui.ctrl.combobox; //对于组合控件,动态创建时必须要先导入库 import win.ui.ctrl.datetimepick; import math import time namespace bmt.ctrl; class listviewExx{ ctor( lvCtrl ){ this=assert(lvCtrl,"请先指定listview对象"); this = lvCtrl; this.ctrlSetting={}; //定义一个公共表,用于存放combobox的值 this.lvClr ={}; //设置背景色和字体颜色 this.currentRow=0; //当前选中的行号 this.currentCol=0; //当前选中的列号 this.currentCls=false; //当前显示的cls this.bgclr135 = null; //奇数行背景颜色 this.bgclr246 = null; //偶数行背景颜色 this.fontclr135 = null; //奇数行字体颜色 this.fontclr246 = null; //偶数行字体颜色 //设置列标题图标 var iml = ..win.imageList(12,12); //排序时的小箭头,图像为w24*h12,分割宽度就是w12*h12 的整数倍 //iml.add('GIF\56\57a \0\15\0\x80\0\0\x80\x80\x80\xff\0\xff\33\xf9\4\0\0\0\0\0\44\0\0\0\0 \0\15\0\0\2\31\x8c\x8f\xa9\xcb\xed\15\xa3\x9c\xb4N\xf0\x80\xde\56k\xbfA\\\xd7\x84 \x97Y\xea\xca\xb6\xee\11\xc7F\1\0;', 0xff00ff); iml.add('\x47\x49\x46\x38\x39\x61\x18\0\x0C\0\x91\0\0\0\0\0\xFF\xFF\xFF\xFF\0\xFF\xFF\xFF\xFF\x21\xF9\x04\x01\0\0\x03\0\x2C\0\0\0\0\x18\0\x0C\0\0\x02\x2C\x94\x05\x09\xC7\x96\x7D\x94\x82\x6E\x41\x29\xE9\x6B\xF3\x4D\x6E\x31\xDB\x18\x46\xE5\x75\x82\x94\xB9\x56\x2D\x92\x92\xAE\x0A\x2E\xDE\x26\xA6\x30\xA6\xE3\xF5\x87\x6A\x65\x0E\x05\0\x3B', 0xff00ff); this.setColumnImageList(iml); this.setFont(point=12;name='FontAwesome') //font=LOGFONT(h=-18;name='FontAwesome') this.setExtended(0x10000/*_LVS_EX_DOUBLEBUFFER*/)//启用双缓冲,避免拖动滚动条时闪烁 this.gridLines=1 var _tm = ..time().getMilliTime(); var _cbb = "combobox"++_tm; var _ddl = "ddl"++_tm; var _edit = "edit"++_tm; var _date = "date"++_tm; //var _ckb = "ckb"++_tm; this.parent.add( [_cbb ] = {cls="combobox";items={};mode="dropdown"; notify = true;hide=1;vscroll=1;hscroll=1;z=1;}; //动态添加combobox类型按钮控件 [_ddl] = {cls="combobox";items={};mode="dropdownlist";notify = true;hide=1;edge=1;vscroll=1;hscroll=1;z=1;}; //动态添加dropdownlist 类型按钮控件 //[_ckb] = {cls="checkbox";text="选定";checked=false;notify = true;hide=1;z=1;}; //动态添checkbox类型按钮控件 [_edit] = {cls="edit";hide=1;edge=1;notify = true;z=1;}; //新增编辑功能 [_date]={cls="datetimepick";hide=1;edge=1;style=2;z=1} //新增日期控件 ); /*将父窗口空间过继到listview下面来*/ this.parent[_cbb].setParent(this) this.parent[_ddl].setParent(this) //this.parent[_ckb].setParent(this) this.parent[_edit].setParent(this) this.parent[_date].setParent(this) /*方便操作,伪装成listview成员*/ this.combobox = this.parent[_cbb]; this.dropdownlist = this.parent[_ddl]; //this.ckbox = this.parent[_ckb]; this.editbox = this.parent[_edit]; this.dateBox = this.parent[_date]; /*以下处理combobox的消息回调 */ this.combobox.blockInnerCmd=false; //用于控制combobox内部预制的oncommand指令,主要原因是_precommand是只读的 //this.combobox.itemMustExist=false; //用于控制combobox的item值,当为true,则输入的值必须是item中的值,否则可以自由输入 var cbbUpdate=..win.debounce(function(){ //延迟刷新combobox值 ; this.combobox.blockInnerCmd = true this.combobox.showDropDown(false) this.combobox.show(false) this.currentCls = false; var r,c=this.getCtrlRowAndCol(this.combobox) //根据combobox的位置,计算出所在listview的位置 var text = this.combobox.text try{ this.combobox.itemMustExist = this.ctrlSetting[c][r][["itemMustExist"]] : this.ctrlSetting[c][["itemMustExist"]] } //需要严格校验combobox中item必须存在,则修改listview前进行判断 if(this.combobox.itemMustExist){ if(!..table.find(this.combobox.items,text)){ //输入的值不是已经存在的值,则不修改原有的listview值 text = "" this.combobox.blockInnerCmd = false return ; } } this.setItemText(text,r,c) this.combobox.blockInnerCmd = false },100) this.combobox.sortItems=..win.debounce(function(){ //根据输入值,筛选combobox原始items列表,并替换在本次显示时临时更新 //对于特别长的列表,可定义该函数,当输入item中关键字后,会自动调用此函数排序结果 this.combobox.blockInnerCmd = true //阻断消息 var oItems=this.getCtrlAttr(this.currentCol,this.currentRow) //获取原始items值 var text= ..string.replace( this.combobox.editBox.text,"\s","") var items = ..table.filter( oItems, lambda(v) ..string.indexOf(v,text) ) this.combobox.listBox.items=items /*延时处理,防止鼠标丢失*/ this.setTimeout(function(){ this.combobox.showDropDown(text); this.combobox.editBox.text=text; this.combobox.editBox.setFocus(); this.combobox.blockInnerCmd = false //重新启用消息 }) },100) this.combobox._precommand=function(id,event){ if(this.combobox.blockInnerCmd){return} //防止下面处理combobox时,会产生无效的消息;这里需要做阻断消息 select(event) { case 4,9/*1,2,4,8,9,10,11*/{ ///*消息框失去焦点*/ cbbUpdate() } case 5 { //长列表筛选,可根据输入的关键字筛选结果 if(this.combobox.sortItems){ this.combobox.sortItems() } } } }; this.dropdownlist._precommand=function(id,event){ select(event) { case 8/*_CBN_CLOSEUP*/{ //消息框失去焦点 this.setItemText(this.dropdownlist.selText,this.currentRow,this.currentCol) this.dropdownlist.show(false) this.currentCls = false; } } }; this.editbox.wndproc =..win.debounce(function(hwnd, message, wParam, lParam){ //延迟刷新edit值 ; var update; select(message) { case 0x101/*_WM_KEYUP*/ { if( wParam == 0xD/*_VK_RETURN*/ ) update=true; elseif( wParam == 0x1B/*_VK_ESC*/){ this.editbox.text = this.editbox.otext //重置为原始字符 update=true } } case 0x8/*_WM_KILLFOCUS*/,133 {update=true} }; if(update){ var r,c=this.getCtrlRowAndCol(this.editbox) //根据combobox的位置,计算出所在listview的位置 this.setItemText(this.editbox.text,r,c) this.editbox.show(false) this.currentCls = false; } },50) /*dateBox回调*/ this.dateBox.prenotify = function(id,code,ptr){ select(code) { case 0xFFFFFD0F/*_DTN_CLOSEUP*/,0xFFFFFFF8/*_NM_KILLFOCUS*/{ //失去焦点或月历关闭后更新 if(this.dateBox.checked){ //只有启用时间日历控件时才修改值,否则不修改 this.setItemText(this.dateBox.text,this.currentRow,this.currentCol) this.dateBox.show(false) this.currentCls = false; } } } }; }; //-----------------------共用功能区部分---------------------------------- /*排序*/ sortItems = function(){ var sortColumn =this.itemSortColumn; var itemData = this.items; if(sortColumn<0){ var i = ..math.abs(sortColumn) ..table.sort(itemData,lambda(a) ( owner[i]:"") > (a[i]:"") ) } else { ..table.sort(itemData,lambda(a) ( owner[sortColumn]:"") < (a[sortColumn]:"") ) } this.items = itemData; this.clearColumnImage() this.setColumnImage(..math.abs(sortColumn), sortColumn<0 ? 1 : 0); } _prenotify = function (id,code,ptr) { //预回调,可能和标准库冲突,慎用 select(code) { case 0xFFFFFF94/*_LVN_COLUMNCLICK*/ { //排序 if(this.sortItems){ this.itemSortColumn := 1; var notifyMsg = this.getNotifyMessage(code,ptr) if(this.itemSortColumn = notifyMsg.iSubItem) this.itemSortColumn = -notifyMsg.iSubItem; else this.itemSortColumn = notifyMsg.iSubItem; this.sortItems(); } } case 0xFFFFFF4C/*_LVN_BEGINSCROLL*/ { //开始滚动列表,则隐藏当前显示的控件;因为不隐藏控件会显示到别的位置上 try{ this[this.currentCls].show(false) this[this.currentCls].showDropDown(false) } } case 0xFFFFFFFE/*_NM_CLICK*/ { //单击显示控件 try{//隐藏上个控件 this[this.currentCls].show(false) this[this.currentCls].showDropDown(false) } //保存当前点击的行列号 this.currentRow,this.currentCol = owner.hitTest() owner.showCtrl(this.currentRow,this.currentCol) }; case 0xFFFFFFF4/*_NM_CUSTOMDRAW*/ { var lvcd = this.getNotifyCustomDraw(code,ptr); if( lvcd.nmcd.dwDrawStage == 0x10001/*_CDDS_ITEMPREPAINT*/) return 0x20/*_CDRF_NOTIFYSUBITEMDRAW*/; elseif( lvcd.nmcd.dwDrawStage == 1/*_CDDS_PREPAINT*/ ) return 0x20/*_CDRF_NOTIFYITEMDRAW*/; elseif( lvcd.nmcd.dwDrawStage == ( 0x10001/*_CDDS_ITEMPREPAINT*/ | 0x20000/*_CDDS_SUBITEM*/) ){ //注意这里 iSubItem 的索引自0开始( 其他函数通常自1开始 ) var r,c=lvcd.nmcd.dwItemSpec,lvcd.iSubItem //获得行列号 if(lvcd.nmcd.rc.bottom){ //bottom底边大于0时,r,c同时加1 c++ r++ /*更新checkbox控件值*/ var value,ctrl=this.getCtrlAttr(c,r) var text = this.getItemText(r,c) if(ctrl=="ckbox" and !#text) this.setItemText(value,r,c) /*更新字体颜色和背景颜色*/ var clr=this.getclr(r,c) //注意每次重绘都要对每个设置,不然就是变成对整行整列设置了 /*设置特定的值*/ lvcd.clrText = clr.textClr : ( r%2 ? this.fontclr135 : this.fontclr246) : this.color : 0x000000 lvcd.clrTextBk = clr.bkClr : ( r%2 ? this.bgclr135 : this.bgclr246) : this.bgcolor : 0xffffff lvcd.update() return 0/*_CDRF_DODEFAULT*/ } } } } }; /* 函数说明:计算控件显示位置 函数参数:1、row行号;2、col列号;3、csl要显示的控件 */ calcRect=function(r,c,cls){ var rc=this.getItemRect(r,c) if(c==1){ //第一列获取的是整行的宽度 var rc2=owner.getItemRect(r,2) rc.right=rc2.left } var rcForm=owner.getRect(true) if(cls=="ckbox"){ //复选框需要调整位置 rcForm.left += 7 rcForm.top +=2 } //计算要显示在的位置 rc.left += rcForm.left+1 rc.right += rcForm.left+2 rc.top += rcForm.top rc.bottom += rcForm.top return rc; }; /* 函数说明:计算控件位置所在的listview行列号,返回row,col 函数参数:1、ctrlObj */ getCtrlRowAndCol=function(ctrlObj){ var rc=ctrlObj.getRect(true) //根据combobox的位置计算出所在listview单元格位置 return this.hitTest(rc.left+5,rc.top+5,true); }; /* 函数说明:设置指定行列的值和控件类型 函数参数:1、row行号;2、col列号;3、控件默认值;4、控件类型;5、itemMustExist,combobox的输入值是否必须为已存在项目 */ setCtrlAttr=function(c,r,value,cls,itemMustExist){ //设置 this.ctrlSetting[c] := {} if(r){ this.ctrlSetting[c][r]:= {} this.ctrlSetting[c][r].value=value this.ctrlSetting[c][r]["cls"]=cls //cls设置为当前列要显示的控件类型 if(cls=="combobox") this.ctrlSetting[c][r]["itemMustExist"]=itemMustExist //combobox的输入值是否必须为已存在项目 }else { this.ctrlSetting[c]["default"]=value //default作为列默认值 this.ctrlSetting[c]["cls"]=cls; //cls设置为当前列要显示的控件类型 if(cls=="combobox") this.ctrlSetting[c]["itemMustExist"]=itemMustExist //combobox的输入值是否必须为已存在项目 } }; /* 函数说明:获取指定行列的值和控件类型 函数参数:1、row行号;2、col列号 函数返回:value,cls */ getCtrlAttr=function(c,r){ var value=this.ctrlSetting[[c]][[r]][["value"]] //尝试获取特定值 : this.ctrlSetting[[c]][["default"]] //不存在时则获取默认值(如果设置过整列) var cls =this.ctrlSetting[[c]][[r]][["cls"]] //尝试获取特定值 : this.ctrlSetting[[c]][["cls"]] //不存在时则获取默认值(如果设置过整列) return value,cls; }; /* 函数说明:在listview点击的位置,显示设置的控件 函数参数:1、行号;2、列号 */ showCtrl=function(r,c){ //获取下拉选项表 var value,cls= this.getCtrlAttr(c,r) if(!cls or cls="none") return ; //没有控件值的,或单独设置不可用的 this.currentCls=cls; //记录当前显示的cls值 var itemText=this.getItemText(this.currentRow,this.currentCol ) var rc = this.calcRect(r,c,cls) //计算要显示到的位置 select(cls) { case "dropdownlist", "combobox"{ //this[cls].disabled=false this[cls].items=value this[cls].selText=itemText if(cls=="combobox"){this[cls].text=itemText} } case "editbox" { this.editbox.otext=itemText; //记录原始值 this.editbox.text=this.editbox.otext; //设置当前值 } case "ckbox"{ //切换开关状态 if(..string.startWith( itemText,'\uF05E') ) itemText = ..string.replace(itemText,'^\uF05E','\uF05D'); //如果是关状态,则切换为开 elseif(..string.startWith( itemText,'\uF05D') ) itemText = ..string.replace(itemText,'^\uF05D','\uF05E'); //如果是开状态,则切换为关 else itemText = value; //如果未设置过, 则设置默认值 this.setItemText(itemText,this.currentRow,this.currentCol) return ; } case "dateBox" { this.dateBox.time=#time ? ..time(itemText) : ..time() this.dateBox.checked = true //设置默认状态为选中状态 } } this[cls].setRect(rc,true) //winform.combobox.setRect(rc,true) this[cls].show(true) this[cls].setFocus() }; /* 函数说明:设置指定的行,列位置的combobox的Items值;注意设置后,其他控件将不可用 函数参数:1、items表;2;列号;3、[行号];设置行号则表示对单个单元格设置,否则设置整列;4、itemMustExist输入值是否必须为列表中已存在的值;5、enable=true;默认启用 */ setCombobox=function(items,c,r,itemMustExist,enable=true){ var mode= enable ? "combobox" : "none" this.setCtrlAttr(c,r,items,mode,itemMustExist) }; /* 函数说明:设置指定的行,列位置的dropdownlist的Items值;注意设置后,其他控件将不可用 函数参数:1、items表;2;列号;3、[行号];设置行号则表示对单个单元格设置,否则设置整列;4、enable=true;默认启用 */ setDropdownlist=function(items,c,r,enable=true){ var mode= enable ? "dropdownlist" : "none" this.setCtrlAttr(c,r,items,mode) }; /* 函数说明:设置指定的行,列位置的ckb的选中值;注意设置后,其他控件将不可用 函数参数: 1、列号;2、[行号];设置行号则表示对单个单元格设置,否则设置整列; 3、checked=false;4、text=“要显示的字”;默认为"选定" 5、enable=true;默认启用 */ setCheckbox=function(c,r,checked=false,text="选定",enable=true){ var value = (checked ? '\uF05D' : '\uF05E') ++ text var mode= enable ? "ckbox" : "none" this.setCtrlAttr(c,r,value,mode) //如何修改状态 }; /* 函数说明:设置指定的行,列位置可编辑情况;注意设置Editable,其他控件将不可用 函数参数:1、单独的列号或列的集合;2、[行号];设置行号则表示对单个单元格设置,否则设置整列;4、enable=true;默认启用 */ setEditable=function(columnTab,r,enable=true){ if(type(columnTab)!=type.table) columnTab={columnTab} //将非tab转换成tab var mode= enable ? "editbox" : "none" for(i=1;#columnTab;1){ var c=columnTab[i] this.setCtrlAttr(c,r,,mode) } }; /* 函数说明:在指定的行,列位置设置日期控件;注意设置Editable,其他控件将不可用 函数参数:1、列号;2、[行号];设置行号则表示对单个单元格设置,否则设置整列;3、enable=true;默认启用 */ setDateBox=function(c,r,enable=true){ var mode= enable ? "dateBox" : "none" this.setCtrlAttr(c,r,"",mode) }; /* 函数说明:设置指定行列的文字颜色 函数参数:1、clr颜色值;2、clrType颜色类型;3、[row行号];4、[col列号] */ setclr=function(clr,clrType,r,c){ // clrType = "textClr" : "bkClr" if(r and c){ //设置单个单元格颜色 this.lvClr[c] := {} //初始化列字体色 this.lvClr[c][r] := {} //初始化行字体色 this.lvClr[c][r][clrType]=clr //记录单元格颜色 } elseif(c){ //设置整列颜色 this.lvClr[c] := {} //初始化列字体色 this.lvClr[c].default := {} //初始化行字体色 this.lvClr[c].default[clrType]=clr //记录单元格颜色 } elseif(r){ //设置整行颜色 this.lvClr.default := {} //初始化列字体色 this.lvClr.default[r] := {} //初始化行字体色 this.lvClr.default[r][clrType]=clr //记录单元格颜色 } }; /* 函数说明:获取指定行列的文字颜色和背景颜色 函数参数:1、row行号;2、col列号 函数返回:clr={textClr=;bkClr=} */ getclr=function(r,c){ var clr={} clr.textClr = this.lvClr[[c]][[r]][["textClr"]] //直接获取颜色值 : this.lvClr[[c]][["default"]][["textClr"]] //不存在则获取列默认值 : this.lvClr[["default"]][[r]][["textClr"]] //不存在则获取行默认值 //这里有个问题,如果行和列都设置过颜色,那么只能已列的颜色为主,行颜色无效了,待解决后设置的生效 clr.bkClr = this.lvClr[[c]][[r]][["bkClr"]] //直接获取颜色值 : this.lvClr[[c]][["default"]][["bkClr"]] //不存在则获取列默认值 : this.lvClr[["default"]][[r]][["bkClr"]] //不存在则获取行默认值 //这里有个问题,如果行和列都设置过颜色,那么只能已列的颜色为主,行颜色无效了,待解决为后设置的生效 return clr; }; /*函数说明:设置指定行列的背景颜色;函数参数:1、clr;2、[row行号];3、[col列号]*/ setBkclr=function(clr,r,c){ this.setclr(clr,"bkClr",r,c) }; /*函数说明:设置指定行列的文字颜色;函数参数:1、clr;2、[row行号];3、[col列号]*/ setTextclr=function(clr,r,c){ this.setclr(clr,"textClr",r,c) }; /*函数说明:获取指定列的值;函数参数:col列号*/ getOneColumnText=function(c){ var text={} for(i=1;#this.items;1){ var line=this.items[i] ..table.push(text,line[c]) } return text; }; /*函数说明:获取指定行的值;函数参数:row列号*/ getOneRowText=function(r){ return this.items[[r]];}; /*函数说明:设置标题值;函数参数:title={{t1;t2;t3};{width1;width2;width3}}*/ setTitle=function(titles){ var text=titles[1] var widths=titles[2] for(i=1;#text;1){ this.insertColumn(text[i],widths[[i]]) } }; /*函数说明:显示或隐藏列标题;函数参数:true|false*/ showHead=function(flag=true){ if(flag) this.modifyStyle(0x4000/*_LVS_NOCOLUMNHEADER*/); else this.modifyStyle(,0x4000/*_LVS_NOCOLUMNHEADER*/); }; /*设置行高,参数h[=15]*/ setRowHeight = function(h=15){ var imageList = ..win.imageList(1, h);//行高 this.setImageList( imageList, 1/*_LVSIL_SMALL*/); }; /*设置文本大小,参数h[=15]*/ setFontSize = function(s=15){ this.setFont({point=s}); this.redraw() }; } /**intellisense(bmt.ctrl) listviewExx=listview拓展库 listviewExx(__listview)=包装一个listview,为其增加各种控件\n参数listview控件 listviewExx()=!bmt_lvEx. listviewExx=!listview. end intellisense**/ /**intellisense(!bmt_lvEx.) currentRow=当前显示控件在listview中的行号,设置后 currentCol=当前显示控件在listview中的列号 combobox=listview的combobox控件文本编辑框\n!combobox. dropdownlist=listview的dropdownlist控件文本编辑框\n!combobox. editbox=listview的文本编辑框\n!edit. ckbox=listview的复选框\n!checkbox. dateBox=listview的日期时间控件\n!datetimepick. showCtrl(.(r,c)=在listview点击的位置,显示设置的控件,一般情况下不用调用此函数\n函数参数:1、行号;2、列号 setCombobox(.(items,c,r,itemMustExist,enable)=设置或修改指定的行,列位置的combobox的Items值;注意设置后,其他控件将不可用\n1、items表;\n2;列号;\n3、行号[可选],使用则表示对单个单元格设置,否则设置整列;\n4、itemMustExist输入的列表值必须已经存在(相当于一个可以输入值进行筛选的ddl用了);\n5、enable=true;默认启用 setDropdownlist(.(items,c,r,enable)=设置或修改指定的行,列位置的dropdownlist的Items值;注意设置后,其他控件将不可用\n1、items表;2;列号;3、行号[可选],使用则表示对单个单元格设置,否则设置整列;4、enable=true;默认启用 setEditable(.(columnTab,r,enable)=设置指定的行,列位置可编辑情况;注意设置Editable,其他控件将不可用\n函数参数:1、单独的列号或列的集合;2、[行号];设置行号则表示对单个单元格设置,否则设置整列;4、enable=true;默认启用 setCheckbox(.(c,r,checked,text,enable) = 设置指定的行,列位置的ckb的选中值;注意设置后,其他控件将不可用\n参数1、列号;\n参数2、[行号];设置行号则表示对单个单元格设置,否则设置整列;\n3、checked=false;\n4、text=“要显示的字”;默认为"选定"\n5、enable=true;默认启用 setDateBox(.(c,r,enable)=在指定的行,列位置设置日期控件;注意设置Editable,其他控件将不可用\n参数:1、列号;\n参数2、[行号];设置行号则表示对单个单元格设置,否则设置整列;\参数3、enable=true;默认启用 setBkclr(.(clr,r,c)=设置指定行列的背景颜色\n函数参数:1、clr;2、[row行号];3、[col列号]\n同时使用行列则设置指定单元格,只使用一个话,若只指定行或列则表示整行或整列 setTextclr(.(clr,r,c)=设置指定行列的文字颜色\n函数参数:1、clr;2、[row行号];3、[col列号]\n同时使用行列则设置指定单元格,只使用一个话;若只指定行或列则表示整行或整列 getOneColumnText(__c)=获取指定列的值;参数:col列序号\n即使无效的列序号也会返回空表 getOneRowText(__r)=获取指定行的值;参数:row行序号\n无效的行序号也会返回null getCtrlAttr(.(c,r)=获取指定行列的值(value|items)和控件类型(cls)\n函数参数:1、row行号;2、col列号\n函数返回:value,cls setCtrlAttr(.(c,r,value,cls)=设置指定行列的值和控件类型\n函数参数:1、row行号;2、col列号;3、控件默认值;4、控件类型;\n5、itemMustExist,combobox的输入值是否必须为已存在项目,仅对cbb有效 showHead(__true)=添加或移除列标题,true=移除;false=添加 setRowHeight(__15)=设置行高,参数h[=15] setFontSize(__15)=设置文本大小,参数s[=15] sortItems() = @.sortItems=function(){/*自定义点击列标题时的排序函数,默认按ansi大小排序*/\n} end intellisense**/ /**intellisense() !bmt_lvEx.setTitle(title)=@.setTitle({/*设置标题值*/\n{"序号";"姓名";"性别"};\n{200;200;-1}\n}) !bmt_lvEx.bgclr135 = @.bgclr135 = 0xeecc66;/*奇数行颜色*/ !bmt_lvEx.bgclr246 = @.bgclr246 = 0x66ccee;/*偶数行颜色*/ !bmt_lvEx.fontclr135 = @.fontclr135 = 0xff4400;/*奇数行字体颜色*/ !bmt_lvEx.fontclr246 = @.fontclr246 = 0x0044ff;/*偶数行字体颜色*/ !bmt_lvEx.combobox.blockInnerCmd=用于控制combobox内部预制的oncommand指令,如果需要额外写listview.combobox.oncommand,请将此项设为true !bmt_lvEx.combobox.itemMustExist=用于控制combobox的item值,当为true,则输入的值必须是item中的值,否则可以自由输入 !bmt_lvEx.combobox.sortItems() = @.sortItems=/*删除这个大括号->->*/{ win.debounce(function(){ /*对于有特别多的item的combobox,可定义该函数,当输入值发生变化(_CBN_EDITCHANGE)时会自动调用此函数排序结果*/ owner.blockInnerCmd = true /*阻断消息*/ var oItems=owner.parent.getCtrlAttr(owner.parent.currentCol,owner.parent.currentRow) /*获取原始items值*/ var text= string.replace( owner.editBox.text,"\s","") if(!#text){ /*输入内容被清空*/ owner.items=oItems }else { var items = {} for(i=1;#oItems;1){ if(string.indexOf(oItems[i],text)){ table.push(items,oItems[i]) } } owner.items=items } owner.showDropDown(text); owner.blockInnerCmd = false /*重新启用消息*/ },200) /*删除这个大括号->->*/} end intellisense**/
登录后方可回帖