【快手笔记】textBOX&RichTexBox(redit&richedit)
一。文本框(REDIT)
Windows 窗体文本框用于获取用户输入或显示文本。通常用于可编辑文本,也可使其成为只读控件。文本框可以显示多个行,对REDIT文本框强制换行用‘r\n'(如:winform.edit.text += '\r\n';)。REDIT控件为在该控件中显示或输入的文本提供一种格式化样式。若要显示多种类型的带格式文本,请使用 RichTextBox(多功能文本框) 控件。
控件显示的文本包含在 Text 属性中。默认情况下,最多可在一个文本框中输入 2048 个字符。如果将 Multiline 属性设置为 true,则最多可输入 32 KB 的文本。Text 属性可以在设计时使用“属性”窗口设置,在运行时用代码设置,或者在运行时通过用户输入来设置。可以在运行时通过读取 Text 属性来检索文本框的当前内容。
edit={ bottom=97;right=166;left=28;multiline=1;top=35;font=LOGFONT( name="宋体";h=-12 );z=1;text="edit";edge=1;cls="edit" }
bottom :获取控件下边缘与其容器的工作区上边缘之间的距离(以像素为单位)
right:获取控件右边缘与其容器的工作区左边缘之间的距离(以像素为单位)。
left:获取或设置控件左边缘与其容器的工作区左边缘之间的距离(以像素为单位)。
top:获取或设置控件上边缘与其容器的工作区上边缘之间的距离(以像素为单位)。
multiline:获取或设置一个值,该值指示此控件是否为多行 TextBox 控件。 (ture=1,flase则不显示,快手根据你画出来的高度自动设置是否使用multiline属性)
font:获取或设置控件显示的文字的字体。
text:获取或设置 TextBox 中的当前文本。
密码框设置属性password=1
edit={ bottom=80;right=210;left=38;top=56;font=LOGFONT( name="宋体";h=-12 );z=1;password=1;text="edit";edge=1;cls="edit" }
在快手设计器中选择false,源代码中就没有这个属性,因为“没有”与“false”在条件值同义,设计器是用这个语法特性来缩减生成的代码量。
控件语法:
winform.edit.oncommand = function(id,event){ //win.msgbox( winform.edit.text ); a=winform.edit.text//把输入框的值赋于变量a }//endproc |
焦点
win.getFocus(winform.edit.hwnd)//获取窗口输入焦点所在的窗口句柄
win.setFocus(winform.edit.hwnd)//设置输入焦点
TAB切换输入
控件默认是不可用tab切换的,要在属性里设置tab键支持。如果是edit文本框,不可为多行(multiline为0)
自动换行
只有RICHEDIT(多文本框)才可以自动换行,在视图属性设置[自动换行]=TURE(WRAP=1)
强制换行
普通edit用'\r\n'换行,richedit用'\n'换行
winform.edit.text += '\r\n';
winform.richedit.text += '\n'
winform.edit.text += '\r\n';
winform.richedit.text += '\n'
二。多行文本框(RICHEDIT)
RICHEDIT 控件用于显示、输入和操作带有格式的文本。RichTextBox 控件除了执行 TextBox 控件的所有功能之外,它还可以显示字体、颜色和链接,从文件加载文本和嵌入的图像,撤消和重复编辑操作以及查找指定的字符。与字处理应用程序(如 Microsoft Word)类似,RichTextBox 通常用于提供文本操作和显示功能。(摘自MDSN)
创建控件语句
richedit={ bottom=134;right=288;left=47;multiline=1;top=66;font=LOGFONT( name="宋体";h=-12 );z=1;text="richedit";edge=1;cls="richedit" } |
控件语法
|
响应事件一般指的鼠标单击等, id指的控件ID,基本可以忽略不管,event每个控件都仅有有限的几个;
在设计器中双击控件生成的 oncommand 事件响应函数:一般会被鼠标点击触发、以及控件数据发生改变时触发。有事件发生(例如鼠标从控件上滑过只是一个消息,并没有事件发生)
而右键点击控件,在菜单中点击“消息回调”生成的wndproc函数则可以处理所有消息。
而右键点击控件,在菜单中点击“消息回调”生成的wndproc函数则可以处理所有消息。
响应回车事件(只有多行文本框才有回车事件可以,单行文本框没有回车事件)
import win.ui; /*DSG{{*/ var winform = win.form(parent=...; text="AAuto Form";right=349;bottom=249 ) winform.add( edit={ bottom=169;right=235;left=55;multiline=1;top=75;font=LOGFONT( name="宋体";h=-12 );z=1;text="edit";edge=1;cls="edit" } ) /*}}*/ winform.edit.wndproc = function(hwnd,message,wparam,lparam){ win.setFocus(winform.edit.hwnd)//设置输入焦点 select(message) {//判断消息类型 case 0x100/*_WM_KEYDOWN*/ //键盘按下 {if(wparam == 0xD/*_VK_ENTER*/){ win.msgbox("你在文本框按了ENTER键","AAuto") } elseif(wparam == 0x20/*_VK_SPACE*/){ win.msgbox("你在文本框按了空格键","AAuto") } } } //无返回值则继续调用默认回调函数 }//endproc winform.show() win.loopMessage();
四。控件属性(参考库源码智能提示)
!edit.lineCount = 获取行数
!edit.setsel(1,__) = 设置选区,参数(起始位置,结束位置)
!edit.getsel() = 获取选区起始位置,结束位置
!edit.selText = 获取或设置选区文本\n仅支持richedit控件
!edit.modified = 文本内容是否已修改
!edit.rangeText(.(起始位置,结束位置) = 返回指定位置文本(仅richedit支持)
!edit.text = 编辑控件文本属性
!edit.hwnd = 控件句柄
!edit.id = 控件ID
!edit.parent = 父窗口
!edit.parent.hwnd = 父窗口句柄
!edit.hide = 控件是否隐藏
!edit.disabled = 控件时否可见
!edit.left = 左侧坐标
!edit.right = 右侧坐标
!edit.top = 顶部坐标
!edit.bottom = 底部坐标
!edit.limit = 字符数限制
!edit.scrollCaret = 滚动到光标处
!edit.lineScroll(.(滚动到指定行) = 滚动条移动到指定行
!edit.lineScroll(.(滚动指定行,列) = 滚动条移动到指定行\n第二个参数对richedit无效
!edit.lineToChar = 获取指定行首字符偏移位置
!edit.lineFromChar = 返回指定位置行数
!edit.lineText = 获取指定行文本
!edit.redraw() = 刷新
!edit.show(true__) = 显示控件
!edit.rect = 控件区块位置(::RECT结构体)
!edit.clientRect = 控件客户区块位置(::RECT结构体)
!edit.font = 控件字体(::LOGFONT结构体)
!edit.clientRect = 获取控件客户区块位置(::RECT结构体)
!edit.theme = 外观主题,例如\nwinform.button.theme = "Explorer"\nwinform.button.theme = false
!edit.modifyStyle(.(remove,add) = 如果指定第三个参数,则使用此参数调用::SetWidnowPos
!edit.modifyStyleEx(.(remove,add) = 如果指定第三个参数,则使用此参数调用::SetWidnowPos
!edit.capture = 是否捕获全局鼠标消自息
!edit.close() = 关闭控件窗
!edit.invalidate(__/*可选使用::RECT()对象指定客户区*/) = 使窗口绘图区无效
!edit.invalidate(__/*可选使用::RECT()对象指定客户区*/,0) = 使窗口绘图区无效\n不刷新背景
!edit.update() = 重绘invalidate函数指定的区块
!edit.wrap = 是否启用自动换行,仅richedit支持
!edit.onlink = @.onlink=function(msg,title){\n\n}
?win.ui.ctrl.edit =!edit.
?win.ui.ctrl.richedit =!edit.
五。控件构造源码
//这里我们使用一个反向的装饰继承类来封装edit与richedit控件的公用属性 class editDecorateMeta{ ctor(meta)begin this = meta end; //公用属性 //-------------------------------------- modified = { _get = function(){ return ::SendMessage(owner[["hwnd"]],0xB8/*_EM_GETMODIFY*/); } _set = function( v ){ ::SendMessageInt(owner[["hwnd"]],0xB9/*_EM_SETMODIFY*/,0,v ); } }; limit = { _get = function(){ return ::SendMessage(owner[["hwnd"]], 0x425/*_EM_GETLIMITTEXT*/, null , null); } _set = function( v ){ assert( type(v) == type.number ) ::SendMessage(owner[["hwnd"]], 0xC5/*_EM_LIMITTEXT*/, topointer(v) , null) } } selText = { _get = function(){ var re,min,max = ::SendMessageRefInt(owner[["hwnd"]],0xB0/*_EM_GETSEL*/,0,0); if(max>min){ var re,str = ::SendMessageByString( owner[["hwnd"]],0x43E/*_EM_GETSELTEXT*/,0,max-min+1); return str; } } _set = function( v ){ ::SendMessageByString(owner[["hwnd"]],0xC2/*_EM_REPLACESEL*/,0,v) } } //公用方法 //-------------------------------------- getsel = function(){ //获取起始和结束位置 var re,min,max = ::SendMessageRefInt(owner[["hwnd"]],0xB0/*_EM_GETSEL*/,0,0); return min;max ; } setsel = function(min=0,max=0){ //获取起始和结束位置 ::SendMessageInt(owner[["hwnd"]],0xB1/*_EM_SETSEL*/,min ,max); } rangeText = function(min,max){ var rg = TEXTRANGE(); rg.chrg.cpMin = min; rg.chrg.cpMax = max; rg.lpstrText = ..raw.malloc(max-min+1) ::SendMessageByStruct(owner.hwnd, 0x44B/*_EM_GETTEXTRANGE*/, 0, rg); return rg.lpstrText } lineCount = { _get = function(){ return ::SendMessage(owner[["hwnd"]],0xBA/*_EM_GETLINECOUNT*/); } }; lineText = function(ind){ ind++; var len = ::SendMessage(owner[["hwnd"]],0xC1/*_EM_LINELENGTH*/,topointer(ind)); var buffer = ..raw.toarray( len,"INT" ) buffer.array = { len };//Before sending the message, set the first word of this buffer to the size, in TCHARs, of the buffer ::SendMessageByStruct( owner[["hwnd"]],0xC4/*_EM_GETLINE*/,ind,buffer); return ..raw.tostring(buffer); } lineFromChar = function(pos){ pos--; return ::SendMessage(owner[["hwnd"]],0xC9/*_EM_LINEFROMCHAR*/,topointer(pos) ); } lineToChar = function(line){ line--; return ::SendMessage(owner[["hwnd"]],0xBB/*_EM_LINEINDEX*/,topointer(line), ); } lineScroll = function(line=0,h=0){ ::SendMessageInt(owner[["hwnd"]],0xB6/*_EM_LINESCROLL*/,h,line-1 ); } scrollCaret = function(){ ::SendMessage( owner[["hwnd"]] , 0xB7/*_EM_SCROLLCARET*/); } } class edit{ //构造函数 ctor(parent,tvalue){ if( tvalue.readonly ) tvalue.style |= 0x800/*_ES_READONLY*/ if( tvalue.password ) tvalue.style |= 0x20/*_ES_PASSWORD*/ else if( tvalue.multiline ){ tvalue.style |= 0x4/*_ES_MULTILINE*/ tvalue.style |= 0x1000/*_ES_WANTRETURN*/; } if( tvalue.number ) tvalue.style |=0x2000/*_ES_NUMBER*/ if(! tvalue.hidesel ) tvalue.style |= 0x100/*_ES_NOHIDESEL*/ //输入时文本框自动向右,向下滚动 tvalue.style |= ( 0x80/*_ES_AUTOHSCROLL*/ | 0x40/*_ES_AUTOVSCROLL*/ ) tvalue.bgcolor := 16777215; select(tvalue.align) { case "center" tvalue.style |= 0x1/*_ES_CENTER*/; case "right" tvalue.style |= 0x2/*_ES_RIGHT*/; else tvalue.style |= 0x0/*_ES_LEFT*/; } if(tvalue.edge) tvalue.exstyle |= 0x200/*_WS_EX_CLIENTEDGE*/; } @metaProperty; } edit.metaProperty = editDecorateMeta( ..win.ui.ctrl.metaProperty( ) ); class richedit{ ctor(parent,tvalue){ if(! _STUDIO_INVOKED) _dll := ..raw.loadDll("RICHED20.DLL"); tvalue.cls = "RichEdit20A"; if( tvalue.multiline ) tvalue.style |= 0x4/*_ES_MULTILINE*/ if( tvalue.multiline ){ tvalue.style |= 0x4/*_ES_MULTILINE*/ tvalue.style |= 0x1000/*_ES_WANTRETURN*/; } if( tvalue.readonly ) tvalue.style |= 0x800/*_ES_READONLY*/ if( tvalue.password ) tvalue.style |= 0x20/*_ES_PASSWORD*/ if(! tvalue.hidesel ) tvalue.style |= 0x100/*_ES_NOHIDESEL*/ tvalue.bgcolor := 16777215; //输入时文本框自动向右,向下滚动 tvalue.style |= ( 0x80/*_ES_AUTOHSCROLL*/ | 0x40/*_ES_AUTOVSCROLL*/ ) select(tvalue.align) { case "center" tvalue.style |= 0x1/*_ES_CENTER*/; case "right" tvalue.style |= 0x2/*_ES_RIGHT*/; else tvalue.style |= 0x0/*_ES_LEFT*/; } if(tvalue.edge) tvalue.exstyle |= 0x200/*_WS_EX_CLIENTEDGE*/; //保护成员 var m_wap = false //自动换行 } @metaProperty; } richedit.metaProperty = editDecorateMeta ( ..win.ui.ctrl.metaProperty( wrap = { _get = function(){ return m_wap; } _set = function(v){ m_wap = v; var hwnd = owner.hwnd;; if (v) { var hdc = ::GetDC(hwnd); ::SendMessageInt(hwnd, 0x448/*_EM_SETTARGETDEVICE*/, hdc, 0); ::ReleaseDC(hwnd, hdc); } else ::SendMessageInt(hwnd, 0x448/*_EM_SETTARGETDEVICE*/, 0, 1); } }; link = { _set = function(v){ if(v){ ::SendMessageInt(owner.hwnd, 0x445/*_EM_SETEVENTMASK*/, 0, 0x4000000/*_ENM_LINK */| ::SendMessageInt(owner.hwnd, 0x43B/*_EM_GETEVENTMASK*/, 0, 0)); ::SendMessageInt(owner.hwnd, 0x000045b/*EM_AUTOURLDETECT*/, 1, 0); } } } _prenotify = function(id,code,nmdr){ if(code== 0x070B/*_EN_LINK*/ && owner.onlink ){ var link = ENLINK_STRUCT(); ..raw.convert(nmdr, link); owner.onlink(link.msg,owner.rangeText( link.chrg.cpMin,link.chrg.cpMax) ) } } ) )
六. edit练习
import win.ui; //将第三个textbox设置只读,设置TAB键输入 /*DSG{{*/ var winform = win.form(parent=...; text="AAuto Form";right=336;bottom=112 ) winform.add( edit={ bottom=50;text="";left=18;top=26;font=LOGFONT( name="宋体";h=-12 );tabstop=1;z=1;right=82;edge=1;cls="edit" }; button={ bottom=45;right=219;left=194;top=26;font=LOGFONT( name="宋体";h=-12 );z=5;text="=";tabstop=1;cls="button" }; static={ right=125;bottom=47;text="+";left=94;top=33;font=LOGFONT( name="宋体";h=-12 );z=2;transparent=1;cls="static" }; edit3={ bottom=49;right=296;left=227;top=23;font=LOGFONT( name="宋体";h=-12 );z=4;text="";readonly=1;edge=1;cls="edit" }; edit2={ bottom=50;text="";left=118;top=26;font=LOGFONT( name="宋体";h=-12 );tabstop=1;z=3;right=182;edge=1;cls="edit" } ) /*}}*/ win.setFocus(winform.edit.hwnd)//设置输入焦点 //由于edit文本框不响应回车事件,饶一圈让它响应回车键 winform.wndproc = function(hwnd,message,wparam,lparam){ select(message) {//判断消息类型 case 0x111/*_WM_COMMAND*/ { if(wparam == 0x1/*_IDOK*/ ) //对话框的回车键是确认命令 { winform. _hwnds[ win.getFocus() ].next() } } } }//endproc //在第一个文本框输入完毕按回车键 winform.edit.next = function(){ win.setFocus(winform.edit2.hwnd) } //在第二个文本框输入完毕按回车键 winform.edit2.next = function(){ win.setFocus(winform.button.hwnd) } //光标跳到“=”执行回车计算命令 winform.button.next = function(){ try{ n,len=tonumber(winform.edit.text) if(len == #winform.edit.text){ aa=winform.edit.text } else {win.msgbox("第一个输入框请输入数值","AAuto") } n,len = tonumber(winform.edit2.text) if(len == #winform.edit2.text){ bb=winform.edit2.text } else { win.msgbox("第二个输入框请输入数值","AAuto") } winform.edit3.text=aa+bb } catch(e){ return ; } } //或鼠标点击“=”响应执行回车命令 winform.button.oncommand = function(id,event){ //win.msgbox( winform.button.text ); winform.button.next() }//endproc /*按“=”执行语句命令,此最简单的,不判断输入数值或字符,如果输入字符就相连接, 也不考虑ENDER键及TAB键输入 winform.button.oncommand = function(id,event){ //win.msgbox( winform.button.text ); aa=winform.edit.text;//定义第一个输入框变量 bb=winform.edit2.text;//定义第二个输入框变量 cc=aa+bb;//计算,输入数字自动计算,字符就想链接 winform.edit3.text=cc;//将计算结果赋值给第三个输入框 }//endproc */ winform.show() win.loopMessage();