用plus控件自绘一个Switch控件

Mr_MAO 8小时前 57

//用plus控件自绘一个【switch控件】  (没有使用iconText)
import util.metaProperty; 
class switchCtrl {
    ctor(plusCtrl) {
        this.plus = plusCtrl;
        if(this.plus.cls != "plus") error("必须在 plus 控件上构造", 2);
        
        this.plus.notify = true;
        this.onToggle = null; 
        
        this.$checked = false; 
        this.$trackColorOff = 0xFFE5E5EA;	// 默认滑道背景(关)
        this.$trackColorOn = 0xFF34C759;	// 默认滑道前景(开)
        this.$thumbColorOff = 0xFFFCFCFC;	// 默认滑块颜色(关)
        this.$thumbColorOn = 0xFFFFFFFF;	// 默认滑块颜色(开)
        
        var darkenColor = function(color, factor) {
            var a = (color >> 24) & 0xAA;
            var r = ..math.floor(((color >> 16) & 0xFF) * factor);
            var g = ..math.floor(((color >> 8) & 0xFF) * factor);
            var b = ..math.floor((color & 0xFF) * factor);
            return (a << 24) | (r << 16) | (g << 8) | b;
        };
        
        // 注册自绘事件
        this.plus.onDrawContent = function(graphics, rc) {
			graphics.setSmoothingMode(4/*_GdipSmoothingModeAntiAlias*/);
			
            var padding = this.plus.parent.dpiScale(2); 
            var thumbGap = this.plus.parent.dpiScale(4);
                        
            var width, height = rc.width(), rc.height();

            var trackColor = this.$checked ? this.$trackColorOn : this.$trackColorOff;
            var thumbColor = this.$checked ? this.$thumbColorOn : this.$thumbColorOff;

            if(this.plus.disabled){
                trackColor = darkenColor(trackColor, 0.85);	// 滑道变暗 15%
                thumbColor = darkenColor(thumbColor, 0.95);	// 滑块变暗 5%
            }

            // 绘制轨道
            var trackBrush = ..gdip.solidBrush(trackColor);
            var path = ..gdip.path();
            path.addRoundRect(rc.left + padding, rc.top + padding, width - (padding*2), height - (padding*2), (height - padding*2) / 2);
            graphics.fillPath(trackBrush, path);

            // 绘制轮廓线
            var borderColor = this.plus.disabled ? 0xFFE5E5E5 : 0xFFBFBFBF;
            var borderPen = ..gdip.pen(borderColor, 1);
            graphics.drawPath(borderPen, path);

            // 绘制滑块
            var thumbSize = height - (thumbGap * 2); 
            var thumbLeft = this.$checked ? (rc.left + width - thumbSize - thumbGap) : (rc.left + thumbGap);
            var thumbTop = rc.top + thumbGap;
            var thumbBrush = ..gdip.solidBrush(thumbColor);
            graphics.fillEllipse(thumbBrush, thumbLeft, thumbTop, thumbSize, thumbSize);

            trackBrush.delete(); path.delete(); borderPen.delete(); thumbBrush.delete();
        };

        // 注册鼠标点击事件
        this.plus.onMouseClick = function(wParam, lParam){
            if(this.plus.disabled) return; // 禁用时不处理点击
            this.checked = !this.checked;  
        };
    };

    @_metaProperty;
}

switchCtrl._metaProperty = ..util.metaProperty(
	disabled = {
        _get = lambda() owner.plus.disabled;
        _set = function(v) { 
            owner.plus.disabled = v; 
            owner.plus.redraw(); 
        };
    };
    checked = {
        _get = lambda()  owner.$checked;
        _set = function(v) {
            if(owner.$checked == v) return;
            owner.$checked = v; 
            owner.plus.redraw(); 
            if(owner.onToggle) owner.onToggle(v);
        };
    };
    trackColorOn = {
        _get = lambda() owner.$trackColorOn;
        _set = function(v) { owner.$trackColorOn = v; owner.plus.redraw(); };
    };
    trackColorOff = {
        _get = lambda() owner.$trackColorOff;
        _set = function(v) { owner.$trackColorOff = v; owner.plus.redraw(); };
    };
)

import win.ui;
/*DSG{{*/
var winform = win.form(text="自绘Switch控件";right=399;bottom=263;border="dialog frame";max=false)
winform.add(
btnChangeColor={cls="button";text="换色";left=80;top=192;right=168;bottom=227;z=3};
btnDisabled={cls="button";text="禁用";left=224;top=192;right=312;bottom=227;z=6};
btnSetOff={cls="button";text="关闭";left=224;top=128;right=312;bottom=163;z=2};
btnSetOn={cls="button";text="打开";left=80;top=128;right=168;bottom=163;z=1};
label={cls="static";text="已关闭";left=232;top=48;right=320;bottom=72;color=0x111111;font=LOGFONT(h=-16);transparent=1;z=5};
plus1={cls="plus";left=136;top=40;right=220;bottom=80;notify=1;z=4}
)
/*}}*/

// 初始化实例
var mySwitch = switchCtrl(winform.plus1);

mySwitch.onToggle = function(checked){
    winform.label.text = checked ? "已打开" : "已关闭"; 
}

// 修改switch控件的选中状态
winform.btnSetOn.oncommand = function(id,event) { 
    mySwitch.checked = true; 
}
winform.btnSetOff.oncommand = function(id,event) { 
    mySwitch.checked = false; 
}

// 修改滑道颜色
winform.btnChangeColor.oncommand = function(id,event) {
    if(mySwitch.trackColorOn  == 0xFF34C759){
        mySwitch.trackColorOn = 0xFF0D6EFD; // 滑道变蓝
    }else{
        mySwitch.trackColorOn = 0xFF34C759; // 滑道变绿
    } 
}

// 禁用switch控件
winform.btnDisabled.oncommand = function(id,event){
	mySwitch.disabled = !mySwitch.disabled;
	winform.btnDisabled.text = (!mySwitch.disabled) ? "禁用" : "启用";
	winform.label.color = (!mySwitch.disabled) ? 0x111111 : 0xC0C0C0;
	winform.label.redraw();
}

winform.show();
win.loopMessage();


最新回复 (1)
  • nanyi 3小时前
    0 2

    使用fontAwesome字体图标来实现。

    import win.ui;
    import fonts.fontAwesome;
    /*DSG{{*/
    var winform = win.form(text="开关控件演示";right=247;bottom=149;border="dialog frame";composited=1)
    winform.add(
    button={cls="button";text="打开";left=38;top=61;right=104;bottom=91;z=3};
    button2={cls="button";text="关闭";left=138;top=60;right=204;bottom=90;z=4};
    button3={cls="button";text="换色";left=38;top=101;right=104;bottom=131;z=5};
    button4={cls="button";text="禁用";left=139;top=102;right=205;bottom=132;z=6};
    plus={cls="plus";left=63;top=19;right=112;bottom=48;align="left";color=0xA4A0A0;font=LOGFONT(h=-15);iconStyle={align="left";font=LOGFONT(h=-29;name='FontAwesome')};iconText='\uF204';notify=1;textPadding={left=24};transparent=1;z=1};
    static={cls="static";text="已关闭";left=120;top=24;right=188;bottom=45;color=0x008000;transparent=1;z=2}
    )
    /*}}*/
    
    var colorThemes = [
        {off=0xFFA4A0A0; on=0xFF007D00};
        {off=0xFFA4A0A0; on=0xFF0078D4};
        {off=0xFFA4A0A0; on=0xFFFF6600};
        {off=0xFFA4A0A0; on=0xFF9C27B0};
    ];
    var themeIndex = 1;
    
    // ARGB(0xAARRGGBB) → BBGGRR,用于 static 控件颜色
    var argbToBggrr = function(argb){
        var r = (argb >> 16) & 0xFF;
        var g = (argb >> 8) & 0xFF;
        var b = argb & 0xFF;
        return (b << 16) | (g << 8) | r;
    }
    
    var applySkin = function(){
        var theme = colorThemes[themeIndex];
        winform.plus.skin({
            color={
                active=0xFFD1D1D1;
                default=theme.off;
                disabled=0xEE666666;
                focus=0xFFD1D1D1;
                hover=0xFFC0C0C0;
            };
            checked={
                iconText='\uF205';
                color={default=theme.on};
            }
        })
    }
    
    var updateStatus = function(){
        var theme = colorThemes[themeIndex];
        if(winform.plus.checked){
            winform.static.text = "已打开";
            winform.static.color = argbToBggrr(theme.on);  // 跟随主题色
        }
        else {
            winform.static.text = "已关闭";
            winform.static.color = argbToBggrr(theme.off);  // 灰色
        }
        winform.static.redraw()
    }
    
    applySkin();
    
    winform.plus.oncommand = function(){
        updateStatus();
    }
    
    winform.button.oncommand = function(){
        winform.plus.checked = true;
        updateStatus();
    }
    
    winform.button2.oncommand = function(){
        winform.plus.checked = false;
        updateStatus();
    }
    
    winform.button3.oncommand = function(){
        themeIndex = themeIndex % #colorThemes + 1;
        applySkin();
        updateStatus();  // 换色后同步更新 static 颜色
    }
    
    var isDisabled = false;
    winform.button4.oncommand = function(){
        isDisabled = !isDisabled;
        winform.plus.disabled = isDisabled;
        winform.button4.text = isDisabled ? "启用" : "禁用";
    }
    
    updateStatus();
    
    winform.show();
    win.loopMessage();


返回