//toolbar 工具条 import win.imageList; import win.ui.tooltip; import win.ui.ctrl.metaProperty; namespace win.ui { import util.metaProperty; class toolbar { ctor (winform) { if( ! winform[["hwnd"]] ){ if(type(winform)==type.number){ winform = {hwnd=winform;_mapCommandProc={}} } else { error("第一个构造参数必须指定有效窗口",3) } } this.parent = winform; this.hParent = winform.hwnd; winform.toolbar = this; this.flat = true; this.label = true; this.buttons = {}; }; create = function (tParam) { if(this.hwnd) error("已创建对象!",2); var style = 0x40000000/*_WS_CHILD*/ | 0x10000000/*_WS_VISIBLE*/ ; if( tParam[["style"]] ) style = style | tParam[["style"]]; if( tParam[["style"]] ) style = style | tParam[["style"]]; if( this.flat ) style = style | 0x800/*_TBSTYLE_FLAT*/ | 0x100/*_TBSTYLE_TOOLTIPS*/; this.hwnd = ::CreateWindowEx( tParam[["exstyle"]] or 0,"ToolbarWindow32", ,style,0, 0, 0, 0, this.hParent, 0 ); ::SendMessageInt(this.hwnd,0x41e/*_TB_BUTTONSTRUCTSIZE*/, 20, 0); ::SendMessageInt(this.hwnd,0x200C/*_CCM_DPISCALE*/,1,0); this.tooltip = ..win.ui.tooltip(winform); ::SendMessageInt(this.hwnd, 0x424/*_TB_SETTOOLTIPS*/, this.tooltip.hwnd, 0); this.showLabel = this.label; this.cls = "toolbar"; this.className = "ToolbarWindow32"; this.disableDpiScaling = true; if(winform[["hwnd"]] && winform.add){ winform.add(this); } return this.hwnd; }; _preadjust = function(){ ::SendMessageInt(this.hwnd, 0x421/*_TB_AUTOSIZE*/, 0, 0); }; getButtonById = function(id){ var idx = 1 + ::User32.SendMessage( this.hwnd,0x419/*_TB_COMMANDTOINDEX*/,id,0); if( idx ) return this.buttons[idx]; }; getButton = function(idx){ return this.buttons[idx]; }; add = function (text,proc,iBitmap,id,fsStyle) { if(!id){ id = this.parent.registCommand(proc); } else { if(proc)this.parent.registCommand(proc,id); } var tbb = TBBUTTON(this); tbb.iBitmap = (iBitmap:0) - 1; tbb.idCommand = id; tbb.fsState = 4/*_TBSTATE_ENABLED*/; if(fsStyle){ tbb.fsStyle = fsStyle; } else { tbb.fsStyle = text == null ? 1/*_TBSTYLE_SEP*/ : 0x10/*_TBSTYLE_BUTTON |_TBSTYLE_AUTOSIZE*/; } tbb.iString = text or ""; ..table.push(this.buttons,tbb ); ::SendMessageByStruct(this.hwnd, 0x444/*_TB_ADDBUTTONSW*/, 1, tbb); ::SendMessageInt(this.hwnd, 0x421/*_TB_AUTOSIZE*/, 0, 0); return tbb; } @_metaProperty; } namespace toolbar{ _metaProperty = ..win.ui.ctrl.metaProperty( showLabel = { _get = function () { return owner.label; } _set = function (v) { if (owner.hwnd) ::SendMessageInt(owner.hwnd, 0x400/*_WM_USER*/+60/*_TB_SETMAXTEXTROWS*/, v ? 1 : 0, 0); owner.label = v ? true : false; } }; style = { _get = function () { return ::SendMessageInt(owner.hwnd, 0x439/*_TB_GETSTYLE*/, 0, 0); } _set = function (v) { return ::SendMessageInt(owner.hwnd, 0x438/*_TB_SETSTYLE*/, 0, ::MAKELONG(v, 0)); } }; modifyStyle = function( remove=0,add=0 ){ var style = ( owner.style & ~remove ) | add ; owner.style = style; return style; }; setExtended = function(ex,v=true){ return ::SendMessageInt(owner.hwnd, 0x454/*_0x454*/,ex,v?ex:0); }; getExtended = function(ex=~0){ return ::SendMessage(owner.hwnd, 0x455/*_LVM_GETEXTENDEDLISTVIEWSTYLE*/) & ex; }; getNotifyInfo = function(ptr){ var tb = ..raw.convert(ptr,{ struct hdr = ::NMHDR(); int item; struct button = TBBUTTON(); int cchText; ustring pszText; stuct rc = ::RECT(); }); }; imageList = { _get = function () { return ::SendMessageInt(owner.hwnd, 0x400/*_WM_USER*/+49/*_TB_GETIMAGELIST*/, 0, 0); } _set = function (v) { return ::SendMessage(owner.hwnd, 0x400/*_WM_USER*/+48/*_TB_SETIMAGELIST*/, , v); } } ) class TBBUTTON{ ctor (parent) { this.parent = parent; } int iBitmap; int idCommand; BYTE fsState; BYTE fsStyle; INT dwData; ustring iString; @_metaProperty; } namespace TBBUTTON{ class INFO { INT cbSize = 32; INT mask = 0; int idCommand; int iImage; BYTE fsState; BYTE fsStyle; WORD cx; INT lParam; pointer text; int cchText; }; INFO_AUTOSET_MASK = function(info){ if( info.text !== null ){ info.text = ..string.toUtf16(info.text); info.cchText = #info.text/2; } if( info.cchText ){ info.mask |= 2/*_TBIF_TEXT*/ } if( info.fsState ){ info.mask |= 4/*_TBIF_STATE*/ } if( info.idCommand ){ info.mask |= 0x20/*_TBIF_COMMAND*/ } if( info.iImage !== null ){ info.mask |= 1/*_TBIF_IMAGE*/ } if( info.cx ){ info.mask |= 0x40/*_TBIF_SIZE*/ } if( info.fsStyle ){ info.mask |= 8/*_TBIF_STYLE*/ } }; _metaProperty = ..util.metaProperty( getInfo = function(mask){ var info = INFO(); info.mask = mask; var idx = ::SendMessageByStruct(owner.parent.hwnd,0x43F/*_TB_GETBUTTONINFOW*/,owner.idCommand,info) ; if( idx >= 0 ){ if( info.mask & 2/*_TBIF_TEXT*/ ) info.text = ..string.fromUtf16(info.text,,true); return info; } } setInfo = function(info){ if(!info._struct)info = ..table.assign(INFO(),info); INFO_AUTOSET_MASK(info); return !! ::SendMessageByStruct(owner.parent.hwnd,0x440/*_TB_SETBUTTONINFOW*/,owner.idCommand,info); } id = { _get = function () { return owner.idCommand; } _set = function (v) { if( owner.setInfo( idCommand = v ) ){ owner.idCommand = v; } } }; index = function(){ return ( 1 + ::User32.SendMessage( owner.parent.hwnd,0x419/*_TB_COMMANDTOINDEX*/,owner.idCommand,0) ); }; delete = function(){ var idx = owner.index(); if(idx) { ..table.remove(owner.parent.buttons,idx); return ::SendMessageInt( owner.parent.hwnd,0x416/*_TB_DELETEBUTTON*/,idx - 1,0); } }; text = { _get = function () { return owner.iString; } _set = function (v) { if( owner.setInfo( text = v ) ){ owner.iString = v; } } }; getRect = function(){ var rc = ::RECT() if( ::SendMessageByStruct(owner.parent.hwnd,0x433/*_TB_GETRECT*/,owner.idCommand,rc) ) return rc; }; click = function(){ owner.parent.parent.sendMessage( 0x111/*_WM_COMMAND*/,owner.idCommand,0,0) }; state = { _get = function () { return ::SendMessageInt(owner.parent.hwnd, 0x412/*_TB_GETSTATE*/, owner.idCommand, 0); } _set = function (v) { return ::SendMessageInt(owner.parent.hwnd, 0x411/*_TB_SETSTATE*/, owner.idCommand, ::MAKELONG(v, 0)); } }; disabled = { _get = function () { return !( owner.state & 4/*_TBSTATE_ENABLED*/); } _set = function (v) { if (v) owner.state -= 4/*_TBSTATE_ENABLED*/; else owner.state |= 4/*_TBSTATE_ENABLED*/; } }; enabled = { _get = function () { return !owner.disabled; } _set = function (v) { owner.disabled = !v; } }; checked = { _get = function () { return owner.state & 0x1; } _set = function (v) { if (v) owner.state |= 0x1; else if (owner.checked) owner.state -= 0x1; } } ); } }; } //感谢 lujjjh 贡献最初的源代码(2010.9) /**intellisense() win.ui.toolbar(__/*父窗口*/) = 工具条控件。\n\n此控件不建议使用,请改用高级选项( win.ui.tabs ),\n高级选项卡可以更好地支持字体图标、 DPI 缩放等 win.ui.toolbar() = !toolbar. end intellisense**/ /**intellisense(!toolbar) create(tParam) = 创建工具条,注意工具条会占用父窗口上的空间,\n可选传入 @tParam 参数表,可包含 style,exstyle 等样式参数\n可用样式可参考:\n https://docs.microsoft.com/en-us/windows/win32/controls/toolbar-control-and-button-styles add(标题,回调函数,图像索引,可选指定命令ID) = @.add(\n "文字", \n function (id) {\n\n },1\n) style = 工具栏样式,数值,\n 使用 _TBSTYLE_ 前缀常量表示样式,\n也支持 _CCS_ 前缀的样式常量,\n直接设置此样式会覆盖工具条原来的一些默认样式,\n例如 让工具条显示在顶部的 _CCS_TOP,这会导致工具条移到底部,\n建议用 modifyStyle 修改样式可避免此问题 modifyStyle(.(移除样式,添加样式) = 所有参数可选,默认为0\n使用 _TBSTYLE_ 前缀常量表示样式 adjust() = 重新设置工具栏大小 showLabel = 是否在按钮上显示文字 imageList = 指定工具条控件的图像列表。\n指定的图像列表支持 DPI 自适应缩放\n发送 _CCM_DPISCALE 消息且其他参数为 0 可关闭 DPI 自适应 getButton(.(索引) = 返回按钮对象 getButtonById(.(idCommand) = 返回按钮对象 buttons[1__/*索引*/] = 返回指定的按钮对象 buttons.? = !toolbar_button. add() = 添加一个分隔条\n!toolbar_button. getButton() = !toolbar_button. getButtonById() = !toolbar_button. onDestroy = @.onDestroy = function(){\n __/*窗口销毁前触发*/\n} onnotify = @.onnotify = function(id,code,ptr){\n __/*通知事件触发*/\n} wndproc = @.wndproc = function(hwnd,message,wParam,lParam){\n __/*窗口消息回调,返回任意非null值阻止默认回调\nwndproc重复赋值时追加函数而不是覆盖之前的回调\n设为null添除所有消息回调函数\nwndproc也可以是一个表,键要为处理的消息,值为对应的消息回调函数*/ \n} sendMessage(.(msg,wParam,lParam) = 发送窗口消息\n此函数用法请参考 ::User32.SendMessage postMessage(.(msg,wParam,lParam) = 投递窗口消息到消息队列中\n此函数用法请参考 ::User32.PostMessage getRoot() = 获取顶层父窗口 setPos(.(x坐标,y坐标,宽,高,插入位置,参数) = 调整窗口位置或排序,所有参数可选\n同时指定x,y坐标则移动位置\n同时指定宽高则改变大小\n指定插入位置(句柄或_HWND前缀常量)则调整Z序 getPos() = 返回相对父窗口客户区的坐标,宽,高,\n参数为 true 返回屏幕坐标,宽,高\n\n注意工具条是默认已经做过 DPI 缩放的,\n所以请在 winform.enableDpiScaling("init"); 以后使用这些属性 height = 获取时返回工具条实际高度。\n只能获取,修改无效。\n\n注意工具条是默认已经做过 DPI 缩放的,\n所以请在 winform.enableDpiScaling("init"); 以后使用这些属性 width = 工具条宽度。\n只能获取,修改无效\n\n注意工具条是默认已经做过 DPI 缩放的,\n所以请在 winform.enableDpiScaling("init"); 以后使用这些属性 left = 左侧坐标。\n只能获取,修改无效\n\n注意工具条是默认已经做过 DPI 缩放的,\n所以请在 winform.enableDpiScaling("init"); 以后使用这些属性 right = 右侧坐标。\n只能获取,修改无效\n\n注意工具条是默认已经做过 DPI 缩放的,\n所以请在 winform.enableDpiScaling("init"); 以后使用这些属性 top = 顶部坐标。\n只能获取,修改无效\n\n注意工具条是默认已经做过 DPI 缩放的,\n所以请在 winform.enableDpiScaling("init"); 以后使用这些属性 bottom = 底部坐标。\n只能获取,修改无效\n\n注意工具条是默认已经做过 DPI 缩放的,\n所以请在 winform.enableDpiScaling("init"); 以后使用这些属性 show(true__) = 显示控件 getRect() = 控件区块位置,返回值为 ::RECT结构体\n!rect. getRect(true) = 控件屏幕区块位置,返回值为 ::RECT结构体 setRect(rc) = 设置控件区块位置,返回值为 ::RECT结构体 setRect(rc,true) = 设置控件屏幕区块位置,返回值为 ::RECT结构体 getClientRect() = 控件客户区块位置,返回值为 ::RECT结构体\n!rect. getFont(true) = 返回控件字体,返回值为 ::LOGFONT 结构体\n!logfont. setFont(__/*指定字体*/) = 指定LOGFONT字体对象,或逻辑字体句柄 hide = 控件是否隐藏 capture = 是否捕获全局鼠标消息 redraw() = 刷新 setRedraw(false) = 禁止重绘 setRedraw(true) = 恢复重绘 redrawTransparent() = 刷新\n透明背景时请使用此函数替代redraw() theme = 外观主题,例如\nwinform.button.theme = "Explorer"\nwinform.button.theme = false cls = 设计时类名 className = 运行时类名 hwnd = 控件句柄 getForm() = 标准库 win.ui 创建的所有窗体与控件对象都拥有此属性。\nwin.form 创建的窗体对象返回自身,其他控件对象返回创建控件的容器窗口( _parentForm 属性 )。 getParent() = 返回父窗口\n!winform. disabled = 是否禁用 setExtended(.(exstyle) = 启用工具条指定扩展样式 setExtended(.(exstyle,false) = 取消工具条指定扩展样式 getExtended(.() = 获取工具条扩展样式 getExtended(.(exstyle) = 获取工具条指定扩展样式 getNotifyInfo(ptr) = 在通知回调中获取 PNMTOOLBAR 结构体,\nptr 为 onnotify 回调传过来的指针参数 end intellisense**/ /**intellisense(!toolbar_button) getInfo( _TBIF__ ) = 获取TBBUTTONINFO结构体 setInfo( __ ) = 设置TBBUTTONINFO结构体,可指定部分字段 index() = 返回按钮索引 delete() = 删除按钮 id = 命令ID state = 读写按钮状态 disabled = 是否禁用 checked = 是否选中 text = 按钮文本 getRect() = 返回按钮区块\n!rect. click() = 点击按钮 end intellisense**/ /**intellisense() _CCS_TOP=@1/*_CCS_TOP*/ _CCS_NOMOVEY=@2/*_CCS_NOMOVEY*/ _CCS_BOTTOM=@3/*_CCS_BOTTOM*/ _CCS_NORESIZE=@4/*_CCS_NORESIZE*/ _CCS_NOPARENTALIGN=@8/*_CCS_NOPARENTALIGN*/ _CCS_ADJUSTABLE=@0x20/*_CCS_ADJUSTABLE*/ _CCS_NODIVIDER=@0x40/*_CCS_NODIVIDER*/ _CCS_VERT=@0x80/*_CCS_VERT*/ _CCS_LEFT=@0x81/*_CCS_LEFT*/ _CCS_NOMOVEX=@0x82/*_CCS_NOMOVEX*/ _CCS_RIGHT=@0x83/*_CCS_RIGHT*/ _TB_SETSTYLE=@0x438/*_TB_SETSTYLE*/ _TB_GETSTYLE=@0x439/*_TB_GETSTYLE*/ _TB_GETBUTTONSIZE=@0x43A/*_TB_GETBUTTONSIZE*/ _TB_SETBUTTONWIDTH=@0x43B/*_TB_SETBUTTONWIDTH*/ _TB_SETDISABLEDIMAGELIST=@0x436/*_TB_SETDISABLEDIMAGELIST*/ _TB_GETDISABLEDIMAGELIST=@0x437/*_TB_GETDISABLEDIMAGELIST*/ _TB_GETRECT=@0x433/*_TB_GETRECT*/ _TB_GETTOOLTIPS=@0x423/*_TB_GETTOOLTIPS*/ _TB_SETTOOLTIPS=@0x424/*_TB_SETTOOLTIPS*/ _TB_CHANGEBITMAP=@0x42B/*_TB_CHANGEBITMAP*/ _TB_GETBITMAP=@0x42C/*_TB_GETBITMAP*/ _TBIF_IMAGE=@1/*_TBIF_IMAGE*/ _TBIF_TEXT=@2/*_TBIF_TEXT*/ _TBIF_STATE=@4/*_TBIF_STATE*/ _TBIF_STYLE=@8/*_TBIF_STYLE*/ _TBIF_LPARAM=@0x10/*_TBIF_LPARAM*/ _TBIF_COMMAND=@0x20/*_TBIF_COMMAND*/ _TBIF_SIZE=@0x40/*_TBIF_SIZE*/ _TB_GETBUTTONTEXT=@0x42D/*_TB_GETBUTTONTEXT*/ _TBSTYLE_BUTTON=@0/*_TBSTYLE_BUTTON*/ _TBSTYLE_SEP=@1/*_TBSTYLE_SEP*/ _TBSTYLE_CHECK=@2/*_TBSTYLE_CHECK*/ _TBSTYLE_GROUP=@4/*_TBSTYLE_GROUP*/ _TBSTYLE_CHECKGROUP=@6/*_TBSTYLE_CHECKGROUP*/ _TBSTYLE_DROPDOWN=@8/*_TBSTYLE_DROPDOWN*/ _TBSTYLE_AUTOSIZE=@0x10/*_TBSTYLE_AUTOSIZE*/ _TBSTYLE_NOPREFIX=@0x20/*_TBSTYLE_NOPREFIX*/ _TBSTYLE_TOOLTIPS=@0x100/*_TBSTYLE_TOOLTIPS*/ _TBSTYLE_WRAPABLE=@0x200/*_TBSTYLE_WRAPABLE*/ _TBSTYLE_ALTDRAG=@0x400/*_TBSTYLE_ALTDRAG*/ _TBSTYLE_FLAT=@0x800/*_TBSTYLE_FLAT*/ _TBSTYLE_LIST=@0x1000/*_TBSTYLE_LIST*/ _TBSTYLE_CUSTOMERASE=@0x2000/*_TBSTYLE_CUSTOMERASE*/ _TBSTYLE_REGISTERDROP=@0x4000/*_TBSTYLE_REGISTERDROP*/ _TBSTYLE_TRANSPARENT=@0x8000/*_TBSTYLE_TRANSPARENT*/ end intellisense**/