开始

在写ui工具的时候,常常会设置控件的背景或字体颜色;

通常的做法是在options参数中使用backgroundRed cblack

而如果想使用变量就会出现麻烦的字符串拼接,像这样:

this.AddText('background' bgc ' c' fc)

在控件很多的时候便会像这样(我曾经写的ui):
image

为了解决这种复杂性,有了下面的工具类Theme.ahk

代码

class Theme {

  __New(_builder) {
    this.t := _builder.applyTheme
  }

  Custom := Map()

  SetCtrlOpts(ctrl, opts) {
    this.Custom.Set(ctrl.Hwnd, opts)
    return this
  }

  Apply(target) {
    if not target is Gui {
      throw Error('target is no a gui')
    }
    target.BackColor := this.t.window_Bgc
    ctrls := WinGetControlsHwnd(target)
    for ctrl in ctrls {
      c := GuiCtrlFromHwnd(ctrl)
      if this.Custom.Has(ctrl) {
        c.Opt(this.Custom.Get(ctrl))
        continue
      }
      switch {
        case c is Gui.Edit: c.Opt('+Background' this.t.edit_Bgc ' +c' this.t.edit_Fc)
        case c is Gui.Text: c.Opt('+c' this.t.default_Fc)
        case c is Gui.ListView: c.Opt('+Background' this.t.lv_Bgc ' +c' this.t.lv_Fc)
        case c is Gui.StatusBar: c.Opt('-Theme +Background' this.t.statusBar_Bgc ' +c' this.t.statusBar_Fc)
        default: 
      }
    }
    return target
  }

  static Dark(target) => Theme.Builder().UseTheme('Dark').Build().Apply(target)
  static Light(target) => Theme.Builder().UseTheme('Light').Build().Apply(target)
  static Custom(target, _theme) => Theme.Builder().UseTheme(_theme).Build().Apply(target)

  class Builder {

    __New() {
      this.applyTheme := Theme.Themes()
    }

    UseTheme(_theme := 'Light') {
      switch _theme {
        case 'Dark': this.applyTheme := Theme.Themes.Dark()
        case 'Light': this.applyTheme := Theme.Themes.Light()
        default:
          {
            if _theme is Theme.Themes {
              this.applyTheme := _theme
            } else Throw Error('invalid theme type: ' Type(_theme))
          }
      }
      return this
    }

    Chain(exp) => this
    LTrim3(str) => LTrim(str, '#')
    BackColor(color) => this.Chain(this.applyTheme.window_Bgc := this.LTrim3(color))
    LvFontColor(color) => this.Chain(this.applyTheme.lv_Fc := this.LTrim3(color))
    LvBgc(color) => this.Chain(this.applyTheme.lv_Bgc := this.LTrim3(color))
    TextColor(color) => this.Chain(this.applyTheme.default_Fc := this.LTrim3(color))
    EditFontColor(color) => this.Chain(this.applyTheme.edit_Fc := this.LTrim3(color))
    EditBgc(color) => this.Chain(this.applyTheme.edit_Bgc := this.LTrim3(color))
    StatusBarFc(color) => this.Chain(this.applyTheme.statusBar_Fc := this.LTrim3(color))
    StatusBarBgc(color) => this.Chain(this.applyTheme.statusBar_Bgc := this.LTrim3(color))

    Build() => Theme(this)

  }

  class Themes {
    __New() {
      this.window_Bgc := 'white'
      this.default_Fc := 'Black'
      this.default_Bgc := this.window_Bgc
      this.edit_Fc := this.default_Fc
      this.edit_Bgc := this.default_Bgc
      this.lv_Fc := this.default_Fc
      this.lv_Bgc := this.default_Bgc
      this.statusBar_Fc := this.default_Fc
      this.statusBar_Bgc := 'grey'
    }

    class Dark extends Theme.Themes {
      __New() {
        super.__New()
        this.window_Bgc := '1D2021'
        this.default_Fc := 'FABD2F'
        this.edit_Fc := '61CEDB'
        this.edit_Bgc := '292929'
        this.lv_Fc := 'B9CAE4'
        this.lv_Bgc := '434957'
        this.statusBar_Fc := 'FABD2F'
        this.statusBar_Bgc := '94A3BF'
      }
    }

    class Light extends Theme.Themes {
      __New() {
        super.__New()
        this.window_Bgc := 'f6eeda'
        this.default_Fc := '682d00'
        this.edit_Fc := '4b0c37'
        this.edit_Bgc := 'fffaf4'
        this.lv_Fc := '00667d'
        this.lv_Bgc := 'fffaed'
        this.statusBar_Fc := '682d00'
        this.statusBar_Bgc := 'e8e1cd'
      }
    }
  }

}

解释

我们使用builder模式和内部类进行封装,这样使它像流式使用,也可以直接使用工厂方法,极大简化操作。

例子

g := Gui('')
g.SetFont('s15', 'consolas')
text := g.AddText(, 'Test')
g.AddEdit('+Background000')
; Use [builder()]
Theme.Builder()
  .UseTheme('Dark')               ; set theme
  .TextFontColor('#abc')          ; set all text font color
  .BackColor('White')             ; set window background color
  .Build()                        ; build
  .SetCtrlOpts(text, '+cblack')   ; set single control's options
  .Apply(g)                       ; finally apply theme
; Use Factory methods
Theme.Dark(g)
; Or use custom theme
class MyTheme extends Theme.Themes {
  __New() {
    super.__New()
    this.default_Fc := 'green'
  }
}
; Then call Theme.Custom()
Theme.Custom(g, MyTheme())
g.Show()

最常用的其实是工厂方法,有了它,我们设置主题的时候就可以简单的在构造函数的最后添加一句:

Theme.Light(this);

多么简洁!

posted on 2024-03-25 12:57  落寞的雪  阅读(77)  评论(0编辑  收藏  举报