//combobox 下拉框 import win.ui.ctrl.edit; import win.ui.ctrl.listbox; import win.ui.ctrl.metaProperty; namespace win.ui.ctrl; class combobox{ ctor(parent,tParam){ if(tParam) { if( tParam.noIntegralHeight) tParam.style |= 0x0400/*_CBS_NOINTEGRALHEIGHT */; elseif(tParam.mode != "simple"){ tParam.bottom += 100; } if( (!tParam.mode) || ( tParam.mode == "dropdown" ) ){ tParam.style |= 2/*_CBS_DROPDOWN*/ this.onCreated = function(){ this._hwndEdit = ..win.findEx(this.hwnd,0,"Edit"); ::SendMessageInt(owner.hwnd, 0x14E/*_CB_SETCURSEL*/,0,0); }; this._adjust = function( cx,cy,wParam ) { if( owner._hwndEdit != ..win.getFocus() ) ::SendMessageInt(owner._hwndEdit,0xB1/*_EM_SETSEL*/,-1 ,-1); } } elseif( tParam.mode == "dropdownlist" ) { tParam.style |= 0x3/*_CBS_DROPDOWNLIST*/ this.onCreated = function(){ ::SendMessageInt(owner.hwnd, 0x14E/*_CB_SETCURSEL*/,0,0); }; } elseif( tParam.mode == "simple" ){ tParam.style |= 0x1/*_CBS_SIMPLE*/ } if(tParam.ownerDraw) { tParam.style |= 0x220/*_CBS_OWNERDRAWVARIABLE | _CBS_HASSTRINGS*/; }; if(tParam.edge) tParam.exstyle |= 0x200/*_WS_EX_CLIENTEDGE*/; if( tParam.hscroll ) tParam.style |= 0x40/*_CBS_AUTOHSCROLL*/; this._commandFuncnames = { [1/*_CBN_SELCHANGE*/]="onSelChange"; [3/*_CBN_SETFOCUS*/]="onFocusGot"; [4/*_CBN_KILLFOCUS*/]="onFocusLost"; [5/*_CBN_EDITCHANGE*/]="onEditChange"; [7/*_CBN_DROPDOWN*/]="onDropDown"; [8/*_CBN_CLOSEUP*/]="onCloseUp"; [9/*_CBN_SELENDOK*/]="onOk"; [0xA/*_CBN_SELENDCANCEL*/]="onCancel"; } } }; @_metaProperty } combobox._metaProperty = metaProperty( info = function(){ var info = { INT cbSize = 52; struct rcItem = ::RECT(); struct rcButton = ::RECT(); INT stateButton; addr hwndCombo; addr hwndItem; addr hwndList; } if( ::User32.SendMessage(owner.hwnd,0x0164/*CB_GETCOMBOBOXINFO*/,null, info) ){ return info; } }; listBox = { _get = function(){ if( owner.__listbox__ ) return owner.__listbox__; var hwndList = owner.info()[["hwndList"]] if(hwndList){ owner.__listbox__ = ..win.ui.ctrl.listbox(); owner.__listbox__.hwnd = hwndList; return owner.__listbox__; } } }; editBox = { _get = function(){ if(!owner._hwndEdit) return; if( owner.__editbox__ ) return owner.__editbox__; owner.__editbox__ = ..win.ui.ctrl.edit(); owner.__editbox__.hwnd = owner._hwndEdit; return owner.__editbox__; } }; dir = function(path,flag){ return ::User32.SendMessage(owner.hwnd, 0x145/*_CB_DIR*/,flag:0,..io.fullpath(path:"/*")) }; count = { _get = function(){ return ::SendMessage(owner.hwnd, 0x146/*_CB_GETCOUNT*/, null,null) } }; limit = { _set = function( v ){ ::SendMessageInt(owner[["hwnd"]], 0x141/*_CB_LIMITTEXT*/, v , 0) } }; selIndex = { _get = function(){ return ::SendMessage(owner.hwnd, 0x147/*_CB_GETCURSEL*/) + 1; } _set = function( v ){ ::User32.SendMessage(owner.hwnd, 0x14E/*_CB_SETCURSEL*/,(v:0)-1,0) } }; selText = { _get = function(){ var sel = ::SendMessage(owner.hwnd, 0x147/*_CB_GETCURSEL*/ ) var len = ::SendMessage(owner.hwnd, 0x149/*_CB_GETLBTEXTLEN*/, topointer(sel)); var re ,text = ::SendMessageByStr(owner.hwnd, 0x148/*_CB_GETLBTEXT*/,sel,len+1); return text:""; } _set = function(v){ var ind = ::User32.SendMessage(owner.hwnd , 0x158/*_CB_FINDSTRINGEXACT*/, , v ) ; if( ind != -1){ ::SendMessageInt(owner.hwnd, 0x14E/*_CB_SETCURSEL*/,ind,0); } } }; add = function(str,...){ if(...) return owner.addItems([str,...]);//@AIFIX @Deprecated if(type(str)=="table") return owner.addItems(str);//@AIFIX @Deprecated ::User32.SendMessage(owner.hwnd , 0x143/*_CB_ADDSTRING*/, ,str) }; insert = function( str,i){ if( i ? i>0 ) i--; ::User32.SendMessage(owner.hwnd , 0x14A/*_CB_INSERTSTRING*/,i,str) }; clear = function(){ ::SendMessage(owner.hwnd , 0x14B/*_CB_RESETCONTENT*/ ) }; delete = function(ind){ if(!ind) ind=owner.selIndex; ::User32.SendMessage(owner.hwnd , 0x144/*_CB_DELETESTRING*/,ind-1,0) }; find = function(v){ var ind = ::User32.SendMessage(owner.hwnd , 0x14C/*_CB_FINDSTRING*/, ,v); return ind!=-1/*_CB_ERR*/?ind+1:0 }; findEx = function( str ){ var ind = ::User32.SendMessage(owner.hwnd , 0x158/*_CB_FINDSTRINGEXACT*/, , str ) ; return ind!=-1/*_CB_ERR*/?ind+1:0 }; selectString = function(v,indexStart){ ::User32.SendMessage(owner.hwnd, 0x14D/*_CB_SELECTSTRING*/,(indexStart:0)-1,v); }; showDropDown = function(d){ ::SendMessageInt(owner.hwnd, 0x14F/*_CB_SHOWDROPDOWN*/,(d||d===null)?1:0,0); }; autoComplete = function(items,selIndex){ if(!owner.editBox) error("此函数仅适用于 dropdown 模式",2); if(!#items) { owner.listBox.items = {}; owner.showDropDown(false); return; } var s = owner.editBox.text; owner.listBox.items = items; owner.listBox.selIndex = (selIndex:1); var this = owner; this.setTimeout( function(){ var onDropDown = this.onDropDown; this.onDropDown = null; this.showDropDown(); this.onDropDown = onDropDown; this.editBox.text = s; this.editBox.setFocus(); } ) }; items = { _get = function(){ var count = ::SendMessage(owner.hwnd, 0x146/*_CB_GETCOUNT*/); var tab = {}; for(i=0;count-1;1){ var len = ::SendMessageInt(owner.hwnd, 0x149/*_CB_GETLBTEXTLEN*/, i,0) ; var ret,text = ::SendMessageByStr(owner.hwnd , 0x148/*_CB_GETLBTEXT*/,i,len+1); ..table.push(tab,text) } return tab; } _set = function( v ){ ::SendMessage(owner.hwnd , 0x14B/*_CB_RESETCONTENT*/ ); ::SendMessageInt(owner.hwnd, 0x14F/*_CB_SHOWDROPDOWN*/,0,0); if( type(v) == "table" ) { var hwnd = owner.hwnd; for( i=1;#(v) ){ ::User32.SendMessage(hwnd,0x143/*_CB_ADDSTRING*/,,tostring(v[i])); } } } }; addItems = function(items){ for(i,v in items){ ::User32.SendMessage(owner.hwnd , 0x143/*_CB_ADDSTRING*/, ,tostring(v)) } }; setCueBannerText = function(s){ owner.text = ""; ::User32.SendMessage(owner[["hwnd"]], 0x1703/*_CB_SETCUEBANNER*/,,s); }; getEditSel = function(){ var re,min,max = ::SendMessageByInt(owner[["hwnd"]],0xB0/*_EM_GETSEL*/,0,0); if( min >=0 ) { if( min == max ) return min; min = min +1; }; return min,max; }; setEditSel = function(min=0,max){ if(max===null) {max = min;if(max>=0){min=max+1}}; elseif((min>max) && (max>0) ){ min,max = max,min; } if( min > 0 ) min = min - 1; ::SendMessageInt(owner[["hwnd"]],0xB1/*_EM_SETSEL*/,min ,max); }; topIndex = { _get = function(){ return ::SendMessage(owner.hwnd, 0x015b/*_CB_GETTOPINDEX*/)+1; } _set = function( v ){ ::SendMessageInt(owner.hwnd , 0x015c/*_CB_SETTOPINDEX*/,v-1,0); } }; minVisible = { _get = function(){ return ::SendMessage(owner.hwnd, 0x1702/*_CB_GETMINVISIBLE*/); } _set = function( v ){ ::SendMessageInt(owner.hwnd , 0x1701/*_CB_SETMINVISIBLE*/,v,0); } } ) with combobox._metaProperty{ value = items; onListChange = { _set = function(v){owner.onSelChange = v} };//@Deprecated } /***intellisense(!combobox) topIndex = 获取此属性返回首个可见项索引,\n设置此属性为项目索引则滚动到该项可见。\n项目起始索引为 1 minVisible = 设置或获取下拉列表最小显示项目数,\n请在设计属性中启用垂直滚动条。\n\n如果不想多点一下,可如下改进此属性源码:\nutil.metaProperty.extend(win.ui.ctrl.combobox,{\n minVisible = {\n _set = function( v ){ \n ::SendMessageInt(owner.hwnd , 0x1701/*_CB_SETMINVISIBLE*/,v,0); \n } \n }\n}) setCueBannerText(__/*提示文本*/) = 设置文本为空的输入提示,\n参数 @1 使用字符串指定提示内容。\n此函数会自动设置控件 text 属性为空 editBox = 返回下拉控件编辑框\n!edit. listBox = 返回下拉控件列表框\n!listbox. showDropDown(.(true) = 显示下拉列表\n参数为false隐藏下拉列表 autoComplete( = 用于onEditChange事件内部显示自动完成列表\n此函数会在显示列表后保持输入文本与光标不变\n仅适用于dropdown模式 autoComplete(.(items,selIndex) = @items参数使用一个字符串数组指定要显示的列表项,\n@selIndex指定选项索引,不指定时默认为1 setCueBannerText(.("提示文本") = 仅适用 dropdown 模式:\n指定文本框文本为空时的显示的默认提示文本,\n此函数会取消当前选中项,\nXP系统不支持此函数、但调用不报错 setEditSel(.(起始位置,结束位置) = 仅适用 dropdown 模式:\n设置输入框选区,以字符为单位。\n首字符位置为 1 ,选区包含起始与结束位置\n如果结束位置小于开始位置,自动交换参数位置 setEditSel(.(当前位置) = 仅适用 dropdown 模式:\n设置输入框为无选区。\n移动光标到指定位置的字符后面 getEditSel() = 仅适用 dropdown 模式:\n获取输入框选区起始位置,结束位置。\n选区包含起始与结束位置的字符,首字符位置为1\n开始位置在指定的字符前面,结束位置表示指定的字符后面\n只有一个返回值时表示无选区,并表示输入光标在指定字符后面\n返回0表示输入光标在最前面,并且无选区 info() = 返回COMBOBOXINFO结构体,\n关于此结构体请查阅MSDN dir(.("目录路径",_DDL_->->->) = 类似dir命令,列出指定目录下匹配的文件,支持通配符\n参数@2可指定选项,默认为 _DDL_READWRITE cls = 设计时类名 className = 运行时类名 find(__/*请输入文本*/) = 查找列表项 findEx(__/*请输入文本*/) = 精确查找指定的项\n找不到返回0 items = 获取或设置组合框列表,属性值为字符串数组,\n\n仅在属性面板设置初始化items属性时初始化selIndex为1,\n代码中动态修改items后请自行指定selIndex,\n\n如果自动指定了你不想要的selIndex,这会增加不必要的重绘。 addItems(__/*字符串数组*/) = 添加字符串数组到组合框列表,\n数组元素将调用 tostring 转换为字符串后顺序添加到组合框列表尾部。 limit = 只写属性,修改最大允许输入的文本长度,\n如果设为0,则设定为默认长度0x7FFFFFFE,\n必须在控件初始化属性中启用横向滚动条,该属性才能生效 selText = 读取或设置组合框当前选中文本\n在 onOk 事件回调中获取最新值应当使用selText而不是text属性 text = 组合框当前输入文本\n在 onOk 事件回调中获取最新值应当使用 selText 而不是 text 属性 count = 列表项数目 selIndex = 获取或指定当前选中的项索引,属性值为数值。\n设为 null 取消选项。\n\ndropdown 模式下设置选项后默认会全选文本,\n可调用 setEditSel 方法设置或文本框取消选区。 selText = 获取或指定当前选中的文本,精确匹配 selectString(.("文本前缀",开始索引) = 按文本前缀查找并选中项目,\n自开始索引后面开始查找,默认值为0也就是开始处搜索 add(.("文本") = 添加到组合框,\n支持0x100/*_CBS_SORT*/排序 insert(.("文本",插入位置) = 默认添加到开始处,\n-1表示添加到尾部\n不支持0x100/*_CBS_SORT*/排序 clear() = 清除组合框所有内容 delete(__/*索引*/) = 删除参数指定索引的项,不指定参数时删除当前选中项。 hwnd = 控件句柄 id = 控件ID _parentForm = 返回创建控件的容器窗口(win.form对象),所有窗口控件都拥有此只读属性。\n对于使用窗体设计器创建的窗口,也就是返回设计时窗体容器。\n\n即使子窗口移除子窗口样式、更改父子关系,或以 orphanWindow显示,\n控件的 _parentForm 始终都不会改变\n!winform. getParent() = 返回父窗口\n!static. setParent(__/*控件对象*/) = 改变父窗口 hide = 当前控件窗口是否隐藏。\n仅检查当前窗口的可见性样式(窗口 是否移除了 _WS_VISIBLE 样式)。\n不考虑父窗口是否可见,不考虑是否被其他窗口遮挡。\n如果需要同时判断父窗口的可见性,应改用 win.isVisible 函数。\n\n以 `.` 前导的 `.hide()` 作为成员函数被调用时,\n作用等价于将 hide 属性设为 null 。 disabled = 是否禁用 left = 左侧坐标 right = 右侧坐标 top = 顶部坐标 bottom = 底部坐标 width = 宽度 height = 高度 redraw() = 刷新 show(true__) = 显示控件 getRect() = 控件区块位置(::RECT结构体) getRect(true) = 控件屏幕区块位置(::RECT结构体) setRect(rc) = 设置控件区块位置(::RECT结构体) setRect(rc,true) = 设置控件屏幕区块位置(::RECT结构体) getClientRect() = 控件客户区块位置(::RECT结构体)\n!rect. getFont() = 控件字体(::LOGFONT结构体)\n!logfont. setFont(__/*指定字体*/) = 指定LOGFONT字体对象,或逻辑字体句柄 setFont(混入字体属性) = @.setFont(point=10;name="宋体"); theme = 外观主题,例如\nwinform.button.theme = "Explorer"\nwinform.button.theme = false modifyStyle(.(remove,add,swpFlags) = 修改窗口样式,所有参数都是可选参数,\n@remove 用数值指定要移除的样式,可使用 _WS_ 前缀的常量\n@add 用数值指定要添加的样式,可使用 _WS_ 前缀的常量\n@swpFlags 可选用数值指定调整窗口选项,可使用 _SWP_ 前缀的常量\n如果指定了 @swpFlag ,则使用该参数调用::SetWindowPos\n细节请参考 win.modifyStyle 函数源码 modifyStyleEx(.(remove,add,swpFlags) = 修改窗口扩展样式,所有参数都是可选参数,\n@remove 用数值指定要移除的样式,可使用 _WS_EX_ 前缀的常量\n@add 用数值指定要添加的样式,可使用 _WS_EX_ 前缀的常量\n@swpFlags 可选用数值指定调整窗口选项,可使用 _SWP_ 前缀的常量\n如果指定了 @swpFlag ,则使用该参数调用::SetWindowPos\n细节请参考 win.modifyStyle 函数源码 capture = 是否捕获全局鼠标消息 close() = 关闭控件窗口 onSize = @.onSize = function( width,height,wParam ) { \n __/*父窗口改变大小后会自动触发此事件函数。\n注意 onSize 是 adjust 事件的别名,作用相同\n所有 win.form 创建的窗体和控件都支持 onSize(或 adjust)事件,\n重复赋值 onSize(或 adjust)会追加事件触发器而非替换原来的值。\n\nwidth 参数为窗口客户区宽度,height 参数为窗口客户区高度,\nwParam 参数来自 _WM_SIZE 消息的 wParam 参数,一般不用管。\n一般不建议添加一个 wndproc 仅仅是为了处理 _WM_SIZE 消息,\n定义 onSize 事件是更好的选择。\n \n};*/ adjust = @.adjust = function( cx,cy,wParam ) { \n __/*父窗口改变大小后会自动触发此事件函数。\n注意 onSize 是 adjust 事件的别名,作用相同。\n所有 win.form 创建的窗体和控件都支持 adjust 事件,\n重复赋值 adjust 会追加事件触发器而非替换原来的值。\n\ncx 参数为窗口客户区宽度,cy 参数为窗口客户区高度,\nwParam 参数来自 _WM_SIZE 消息的 wParam 参数,一般不用管。\n一般不建议添加一个 wndproc 仅仅是为了处理 _WM_SIZE 消息,\n定义 adjust 事件是更好的选择。\n\n如果主动调用此函数,则检查并执行所有之前添加的 adjust 事件函数。\n省略调用参数时 cx,cy 参数默认设为窗口大小*/ \n}; invalidate(__/*可选使用::RECT()对象指定客户区*/) = 使窗口绘图区无效 invalidate(__/*可选使用::RECT()对象指定客户区*/,0) = 使窗口绘图区无效\n不刷新背景 update() = 重绘invalidate函数指定的区块 setFocus() = 设置焦点 tabNext(.(移动焦点,是否反向) = 获取下一个支持tab控制焦点的控件\n参数@1为true会自动移动焦点到该控件\n参数@2为true则获取上一个控件,否则获取下一个控件 tabNext() = !static. setPos(.(x坐标,y坐标,宽,高,插入位置,参数) = 调整窗口位置或排序,所有参数可选\n同时指定x,y坐标则移动位置\n同时指定宽高则改变大小\n指定插入位置(句柄或_HWND前缀常量)则调整Z序 getPos() = 返回相对坐标,宽,高\nx,y,cx,cy=win.getPos(hwnd) valid = 窗口是否有效,\n窗口未关闭返回 true ,\n窗口已关闭或正在关闭返回 false threadCallable() = 开启此控件的跨线程调用功能 orphanWindow(.(transparent,hwndBuddy) = 创建悬浮窗口,\n悬浮窗口仍然显示在原来的位置,\n悬浮窗口如影随形的跟随父窗口移动或改变大小,控件原来的固定边距等参数仍然有效\n此控件不建议指定参数 sendMessage(.(msg,wParam,lParam) = 发送窗口消息\n此函数用法请参考 ::User32.SendMessage postMessage(.(msg,wParam,lParam) = 投递窗口消息到消息队列中\n此函数用法请参考 ::User32.PostMessage _defWindowProc(hwnd,message,wParam,lParam) = 用于在 wndproc 回调中提前调用默认消息回调函数,\n所有窗口和控件定义了 wndproc 回调以后会自动创建这个函数,\n调用此函数以后,wndproc 必须指定非 null 返回值,\n以避免再次重复调用默认回调函数 oncommand(id,event) = @.oncommand = function(id,event){ var text = owner.selText; __/*响应事件,event比较常用的值:\n_CBN_SELCHANGE表示正在改变当前项,但下拉框还没有关闭\n_CBN_SELENDOK表示已改变选项且下拉框即将关闭\n注意事件中要用selText属性取新的值*/ } onOk() = @.onOk = function(){ __/*响应事件,用户已确认选择指定选项,\n注意事件中要用 selText 属性取新的值\n单击选项或在选项上回车都会触发此事件(无论是否改变选项)*/ } onSelChange() = @.onSelChange = function(){ __/*改变当前选项触发此事件。\n在下拉框上按方向键调整当前选项会触发此事件,\n在选项上回车确认选项时,如果选项已改变则会触发此事件,\n如果回车操作未改变选项仅触发 onOk 事件。\n\n注意事件中要用 selText 属性取新的值\n使用代码修改 selIndex 时不会触发*/ } onCancel() = @.onCancel = function(){ __/*响应事件,用户未确认选项且且下拉框即将关闭\n例如用户点击其他控件关闭下拉列表或直接关闭窗口*/ } onEditChange() = @.onEditChange = function(){ __/*响应事件,输入框中的文本已变更,\n只有用户输入时才会触发,\n切换选项或使用代码修改text属性不会触发\n注意使用text属性取最新值*/ } onDropDown() = @.onDropDown = function(){ __/*弹出下拉列表前触发此事件\n用代码调用 showDropDown 函数也会触发此事件*/ } onFocusGot() = @.onFocusGot = function(){ __/*下拉框获得焦点时触发此事件*/ } onFocusLost() = @.onFocusLost = function(){ __/*下拉框失去焦点时触发此事件*/ } onCloseUp() = @.onCloseUp = function(){ __/*下拉列表隐藏时触发此事件*/ } end intellisense***/ /**intellisense() ?win.ui.ctrl.combobox = !combobox. win.ui.ctrl.combobox() = 下拉框控件\n!combobox. _CBN_CLOSEUP=@8/*_CBN_CLOSEUP*/ _CBN_DBLCLK=@2/*_CBN_DBLCLK*/ _CBN_DROPDOWN=@7/*_CBN_DROPDOWN*/ _CBN_EDITCHANGE=@5/*_CBN_EDITCHANGE*/ _CBN_EDITUPDATE=@6/*_CBN_EDITUPDATE*/ _CBN_KILLFOCUS=@4/*_CBN_KILLFOCUS*/ _CBN_SELCHANGE=@1/*_CBN_SELCHANGE*/ _CBN_SELENDCANCEL=@0xA/*_CBN_SELENDCANCEL*/ _CBN_SELENDOK=@9/*_CBN_SELENDOK*/ _CBN_SETFOCUS=@3/*_CBN_SETFOCUS*/ end intellisense**/