//bkplus 透明背景贴图 import gdip.font; import gdip.path; import gdip.stringformat; import gdip.graphics; import gdip.bitmap; import gdip.solidBrush; import gdip.lineBrush; import gdip.pathGradientBrush; import util.metaProperty; namespace win.ui.ctrl; class bkplus{ ctor(parent,tParam){ this.text = tParam.text; //@AIFIX if(!tParam.left && !tParam.top && tParam.dl && tParam.dr && tParam.dt && !tParam.db){ var rc = parent._defClientRect; if(rc){ if( tParam.right && (rc.width == tParam.right+1) ){ if(tParam.bottom && tParam.bottom < (rc.height * 0.5) ){ tParam.right = rc.width } } } } if(tParam.bgcolor!==null){ if(!(tParam.bgcolor & 0xFF000000)){ this.backgroundColor = ..gdi.rgbReverse( tParam.bgcolor ) | 0xFF000000; } else this.backgroundColor = tParam.bgcolor; tParam.bgcolor = null; } if(tParam.forecolor!==null){ if(!(tParam.forecolor & 0xFF000000)){ this.foregroundColor = ..gdi.rgbReverse( tParam.forecolor ) | 0xFF000000; } else this.foregroundColor = tParam.forecolor; tParam.forecolor = null; } this.paddingRight = tParam.paddingRight:0; this.paddingBottom = tParam.paddingBottom:0; this.paddingLeft = tParam.paddingLeft:0; this.paddingTop = tParam.paddingTop:0; if(!#tParam.repeat) tParam.repeat = "expand"; this.onlyDirectDrawBackground = true;//禁止创建窗口 this.rect = ::RECT(); if(!_WINXP) { if( !tParam.font ) tParam.font = ::LOGFONT(name="Segoe UI"); elseif( tParam.font.name=="Tahoma" ) tParam.font.name="Segoe UI"; } else { if( !tParam.font ) tParam.font = ::LOGFONT(name="MS Shell Dlg"); elseif( tParam.font.name=="Tahoma" ) tParam.font.name="MS Shell Dlg"; } if(tParam.font.name!="Segoe UI"){ this.textRenderingHint = 3/*_GdipTextRenderingHintAntiAliasGridFit*/; } else { this.textRenderingHint = 5/*_TextRenderingHintClearTypeGridFit*/; } this.smoothingMode = 4/*_GdipSmoothingModeAntiAlias*/; this.interpolationMode = 7/*_InterpolationModeHighQualityBicubic*/; }; onDirectDrawBackground = function(hdc,graphics){ if(this.$hidden) return; var rc = this.rect; if(!graphics) { graphics = ..gdip.graphics(hdc); hdc = null; } graphics.smoothingMode = this.smoothingMode; graphics.compositingQuality = 2/*_GdipCompositingQualityHighQuality*/; graphics.interpolationMode = this.interpolationMode; graphics.pixelOffsetMode = 2/*_PixelOffsetModeHighQuality*/ graphics.textRenderingHint = this.textRenderingHint; if(this.background){ if(type(this.background) == "string"){ this.background = ..gdip.loadCachedBitmap(this.background); if(!this.background ) return; } graphics.drawBackground(this.background,this.repeat,rc,this.bkTop:0,this.bkRight:0,this.bkBottom:0,this.bkLeft:0); } elseif( (this.backgroundColor!==null) && (this.linearGradient== null) ){ var brush = ..gdip.solidBrush(this.backgroundColor); graphics.fillRectangle(brush,rc.xywh() ); brush.delete() } var rcContent = rc.copy(); rcContent.right = rcContent.right - this.paddingRight; rcContent.bottom = rcContent.bottom - this.paddingBottom; rcContent.left = rcContent.left + this.paddingLeft; rcContent.top = rcContent.top + this.paddingTop; if(this.foregroundColor!==null){ if(this.linearGradient!== null && this.backgroundColor !== null ){ if(this.linearGradient>=0){ var rf = rc.float(); rf.angle = this.linearGradient; var brush = ..gdip.lineBrush(rf,this.backgroundColor,this.foregroundColor); graphics.fillRectangle( brush,rc.xywh()); brush.delete(); } else { var pathGradient = ..gdip.path(); pathGradient.addEllipse(rc.left,rc.top,rc.width(),rc.height()); var brush = ..gdip.pathGradientBrush(pathGradient); brush.setCenterColor(this.backgroundColor); brush.setSurroundColors(this.foregroundColor); brush.gammaCorrection = true; graphics.fillEllipse(brush,rc.xywh()); brush.delete(); pathGradient.delete(); } } else { var brush = ..gdip.solidBrush(this.foregroundColor); graphics.fillRectangle(brush,rcContent.xywh() ); brush.delete() } } if(this.onDrawBackground){ this.onDrawBackground(graphics,rc) } if(#this.text){ var f = ..gdip.stringformat(); f.align = __stringAlignment[ this.align : "center" ] f.lineAlign = __stringAlignment[ this.valign : "center" ] f.hotkeyPrefix = 1/*_GdipHotkeyPrefixShow*/; f.flags = 0x800/*_GdipStringFormatFlagsMeasureTrailingSpaces*/ | 0x1000/*_StringFormatFlagsNoWrap*/; if(this.trimming!==null) f.trimming = this.trimming; if( !this.argbColor ) this.argbColor = ..gdi.rgbReverse( this.color!=-1? this.color : 0 ) | ( 0xFF << 24 ); var brush = ..gdip.solidBrush( this.argbColor ); var rectf = rcContent.float(); if( this[["(font)"]] ) { if( !this.onDrawString ){ graphics.drawString( this.text ,this[["(font)"]],rectf, f,brush); } else{ this.onDrawString(graphics,this.text,this[["(font)"]],rcContent, f,brush) } } brush.delete(); f.delete(); } if(!hdc) graphics.delete(); }; setPos = function(x,y,cx,cy){ this.rect.setPos(x,y,cx,cy); }; getPos = function(){ return this.rect.getPos(); }; redraw = function(){ owner[["_parentForm"]].redrawBackground(owner.rect); }; _onDestroy = function(){ if(this.bitmap){ ::DeleteObject(this.bitmap); this.bitmap = null; } }; @_metaProperty } bkplus._metaProperty = ..util.metaProperty( background = { _get = function () { return owner.getBackground(); } _set = function (v) { var old = owner.setBackground(v,,!owner[["initializing"]]); } }; setBackground = function(bmp,cacheName){ var background = owner[["(background)"]]; if(type(bmp)==type.number){ owner[["(background)"]] = null; if( bmp == owner.backgroundColor ) return; owner.backgroundColor = bmp; return; } owner.backgroundColor = null; if( bmp == background ) return; var old = background; if( bmp ){ background = ..gdip.loadCachedBitmap(bmp,cacheName); if( background ){ owner[["(background)"]] = background; } else { return; } } else { owner[["(background)"]] = null; } return old; }; getBackground = function(){ return owner[["(background)"]]; }; foreground = { _get = function () { return owner.foregroundColor; } _set = function (v) { owner.foregroundColor = v; } }; getFont = function(noScale){ if(owner["(font)"]){ var graphics = ..gdip.graphics({hwnd=owner[["_parentForm"]].hwnd}); var f = owner["(font)"].getLogFont(graphics); graphics.delete(); if(!noScale){ var yScale = owner[["dpiScaleY"]]; if(yScale && yScale>1) f[["h"]] = f[["h"]] / yScale; } else f.noScale = true; return f; } }; setFont = function(f,own = true ){ if( type(f) == type.pointer ){ var lf = LOGFONT(); if( !::GetObject(f, ..raw.sizeof(lf), lf) ) return; if(own) ::DeleteObject(f); f = lf; } else { if(type(f) != type.table ) error("参数错误@1",2) f = ::LOGFONT(f); if(f[["h"]] && !f[["point"]] && !f[["noScale"]]){ var yScale = owner[["dpiScaleY"]]; if(yScale && yScale>1){ f[["h"]] = f[["h"]] * yScale; } } } if( f.handle && own) f.deleteIndirect(); if(f.color) { owner.color = f.color owner.argbColor = ..gdi.rgbReverse( f.color ) | ( 0xFF << 24 ) } var hdc = ::GetDC(owner[["_parentForm"]].hwnd); owner[["(font)"]] = ..gdip.font( hdc,f ); ::ReleaseDC(owner[["_parentForm"]].hwnd,hdc); return true; }; enableDpiScaling = function(scaleX,scaleY){ if( scaleX === false ){ return; } if(!( scaleX && scaleY ) ) { return; } if( !owner[["dpiScaleX"]] ) { owner[["dpiScaleX"]] = 1; owner[["dpiScaleY"]] = 1; } var origScaleX,origScaleY = owner[["dpiScaleX"]],owner[["dpiScaleY"]]; owner[["dpiScaleX"]] = scaleX; owner[["dpiScaleY"]] = scaleY; var font = owner.getFont(true); if( font ){ font.h = ( font.h / origScaleY ) * scaleY; owner.setFont(font); } }; show = function(v){ owner.$hidden = (v===null || !v); owner.redraw(); }; hide = { _get = function(ownerCall){ if(ownerCall) return function() {owner.$hidden = true;owner.redraw();}; return owner.$hidden; } _set = function(v){ owner.$hidden = v; owner.redraw(); } }; close = function(){ owner[["_parentForm"]].remove(owner); owner._onDestroy(); owner.redraw(); }; ) bkplus.__stringAlignment = { top =0/*_GdipStringAlignmentNear*/ ;bottom = 2/*_GdipStringAlignmentFar*/ ; left =0/*_GdipStringAlignmentNear*/ ; right = 2/*_GdipStringAlignmentFar*/; center = 1/*_GdipStringAlignmentCenter*/; } /**details(更多绘图样式与选项) [plus 控件](doc://library-guide/std/win/ui/ctrl/plus.md)调用 directDrawBackgroundOnly 函数也可以转换为背景贴图控件, 不但拥有 bk,bkplus 控件的相同优势,而且支持更多的绘图样式与选项。 end details**/ /**intellisense() win.ui.ctrl.bkplus() = 无窗口控件,仅用于背景贴图,支持透明png图像,\n直接输出颜色或图像到窗口背景图缓存,\n因为不需要创建窗口可避免前后叠加控件后,处理不当带来的闪烁,\n适合显示静态、不会频繁变动的图像\n\nplus控件也可通过\n调用directDrawBackgroundOnly函数变为背景控件\n!winuictrlbkplus. end intellisense**/ /**intellisense(!winuictrlbkplus) background = 设置背景图像或背景颜色。\n设置背景图像时支持 jpg,gif,png 等格式图像路径或内存数据,支持 gdip.bitmap 对象。\n设置背景颜色支持 0xAARRGGBB 格式颜色数值(ARGB 格式)。\n通过此属性修改背景颜色会自动删除之前指定的背景图像。\n修改此属性后会自动重绘,而通过 backgroundColor 属性修改背景色不会自动重绘。\n\n读取此属性时,即使未指定背景图像,也不会返回背景颜色值,\n应改用 backgroundColor 属性获取背景颜色值。 backgroundColor = 背景颜色, 0xAARRGGBB 格式颜色数值(ARGB 格式)\n直接修改这个属性时不会重绘控件。\n也不会删除通过 background 属性指定的背景图像。\n\nbk,bkplus 是无句柄控件,可以任意前后叠加多个 bk,bkplus 控件。 foreground = 设置前景图像或前景颜色。\n设置前景图像时支持 jpg,gif,png 等格式图像路径或内存数据,支持 gdip.bitmap 对象。\n设置前景颜色支持 0xAARRGGBB 格式颜色数值(ARGB 格式)。\n修改此属性后会自动重绘,通过 foregroundColor 属性修改前景色不会自动重绘。\n\n读取此属性时,即使未指定前景图像,也不会返回前景颜色值,\n应改用 foregroundColor 属性获取前景颜色值。 foregroundColor = 前景颜色, 0xAARRGGBB 格式颜色数值(ARGB 格式)\n直接修改这个属性时不会重绘控件。\n也不会删除通过 foreground 属性指定的前景图像。\n\nbk,bkplus 是无句柄控件,可以任意前后叠加多个 bk,bkplus 控件。 redraw() = 刷新,会导致背景窗口重建背景图缓存\n不建议频繁调用 getPos() = 返回 `x,y,cx,cy` 等 4 个值。\n`x,y`为控件坐标,`cx,cy` 为控件宽、高。 setPos(.(x,y,cx,cw) = 修改控件的 x,y 坐标与宽(cx),高(cw)。\n所有参数可选,不指定的参数则保持原值。\n对于 bk,bkplus 控件此函数不负责重绘。 onDrawBackground = @.onDrawBackground(hdc,rc){ /*背景绘图以后触发此回调,\nhdc为当前绘图设备句柄,rc为控件位置*/ } onDrawString = @.onDrawString = function(graphics,text,font,rectf,strformat,brush){ __/*自定义输出文本,请不要删除传入参数中的GDI+对象*/ graphics.drawString(text,font,rectf,strformat,brush); } paddingRight = 前景色右边距 paddingBottom = 前景色下边距 paddingLeft = 前景色左边距 paddingTop = 前景色上边距 linearGradient = 使用此属性指定线性渐变的方向角度,负数值表示使用径向渐变,\n必须同时指定背景色、前景色才有效,指定图像后此属性无效 argbColor = ARGB格式颜色数值,用于文本输出 textRenderingHint = @.textRenderingHint = _GdipTextRenderingHint__ ; smoothingMode = 绘图画布默认抗锯齿模式,\n默认值为_GdipSmoothingModeAntiAlias interpolationMode = 图像缩放时的默认插值模式,\n默认值为_GdipInterpolationModeHighQualityBicubic show() = 显示窗口。\n参数 @1 为 false 时隐藏窗口。 hide = 当前控件是否隐藏\n\n以 `.` 前导的 `.hide()` 作为成员函数被调用时,\n作用等价于将 hide 属性设为 null 。 close() = 关闭控件。 end intellisense**/