开始
在写ui工具的时候,常常会设置控件的背景或字体颜色;
通常的做法是在options参数中使用backgroundRed cblack
而如果想使用变量就会出现麻烦的字符串拼接,像这样:
this.AddText('background' bgc ' c' fc)
在控件很多的时候便会像这样(我曾经写的ui):
为了解决这种复杂性,有了下面的工具类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);
多么简洁!