一直以来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返回一个可编辑单元格的列表视图对象,nn鼠标左键单击单元格、或者按空格键开始编辑,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如果没有创建任何列,则自动创建列nn数据表应当包含行组成的数组,n每行的数据列必须是由列名和列值组成的键值对n数据表应使用fields包含需要显示的列名称数组n可以通过fields控制要显的列、以及要显示的顺序nn使用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();