新增: 壁纸切换(主题/本地图片/Bing/纯色渐变)

This commit is contained in:
2026-05-25 19:54:32 +08:00
parent a804db3579
commit bb1574641f
14 changed files with 868 additions and 395 deletions

View File

@@ -16,14 +16,44 @@ import (
var zodiacItems []*systray.MenuItem
var cityItems []*systray.MenuItem
var themeItems []*systray.MenuItem
var themeNames = []struct {
Name ThemeName
Label string
}{
{ThemeAurora, "极光"},
{ThemeStar, "星空"},
{ThemeGradient, "渐变"},
{ThemeParticle, "粒子"},
}
func onSystrayReady() {
systray.SetIcon(generateIcon())
systray.SetTooltip("动态壁纸引擎")
cfg := loadConfig()
mPause := systray.AddMenuItem("暂停", "暂停/继续")
systray.AddSeparator()
// 壁纸主题
mTheme := systray.AddMenuItem("壁纸主题", "")
for _, t := range themeNames {
item := mTheme.AddSubMenuItem(t.Label, t.Label)
if cfg.WallpaperType == WPTheme && cfg.Theme == t.Name {
item.Check()
}
themeItems = append(themeItems, item)
}
mLocalImage := systray.AddMenuItem("本地图片", "选择本地图片作为壁纸")
mBingDaily := systray.AddMenuItem("Bing 每日壁纸", "使用 Bing 每日壁纸")
mSolidColor := systray.AddMenuItem("纯色壁纸", "选择纯色壁纸")
mGradientColor := systray.AddMenuItem("渐变壁纸", "选择渐变壁纸")
systray.AddSeparator()
// 星座
mZodiac := systray.AddMenuItem("星座设置", "")
zodiacs := []string{
"白羊座", "金牛座", "双子座",
@@ -31,7 +61,6 @@ func onSystrayReady() {
"天秤座", "天蝎座", "射手座",
"摩羯座", "水瓶座", "双鱼座",
}
cfg := loadConfig()
for _, z := range zodiacs {
item := mZodiac.AddSubMenuItem(z, z)
if z == cfg.Zodiac {
@@ -42,6 +71,7 @@ func onSystrayReady() {
systray.AddSeparator()
// 城市
mCity := systray.AddMenuItem("城市设置", "")
for _, c := range cities {
item := mCity.AddSubMenuItem(c.Name, c.Adm1+" "+c.Name)
@@ -54,14 +84,113 @@ func onSystrayReady() {
systray.AddSeparator()
mQuit := systray.AddMenuItem("退出", "退出程序")
// 主题切换监听
for i, item := range themeItems {
go func(idx int, mi *systray.MenuItem) {
for {
<-mi.ClickedCh
cfg := loadConfig()
cfg.WallpaperType = WPTheme
cfg.Theme = themeNames[idx].Name
saveConfig(cfg)
for _, it := range themeItems {
it.Uncheck()
}
mi.Check()
log.Printf("主题切换: %s", themeNames[idx].Label)
reloadWallpaper()
}
}(i, item)
}
// 本地图片
go func() {
for {
<-mLocalImage.ClickedCh
path := openFileDialog(wvHwnd)
if path == "" {
continue
}
cfg := loadConfig()
cfg.WallpaperType = WPImage
cfg.ImagePath = path
saveConfig(cfg)
for _, it := range themeItems {
it.Uncheck()
}
log.Printf("本地图片: %s", path)
reloadWallpaper()
}
}()
// Bing 每日
go func() {
for {
<-mBingDaily.ClickedCh
cfg := loadConfig()
cfg.WallpaperType = WPBing
saveConfig(cfg)
for _, it := range themeItems {
it.Uncheck()
}
log.Println("切换 Bing 壁纸")
go fetchBingWallpaper()
}
}()
// 纯色壁纸
go func() {
for {
<-mSolidColor.ClickedCh
color := colorPickerDialog(wvHwnd, "")
if color == "" {
continue
}
cfg := loadConfig()
cfg.WallpaperType = WPColor
cfg.Color1 = color
cfg.ColorGradient = false
saveConfig(cfg)
for _, it := range themeItems {
it.Uncheck()
}
log.Printf("纯色壁纸: %s", color)
reloadWallpaper()
}
}()
// 渐变壁纸
go func() {
for {
<-mGradientColor.ClickedCh
c1 := colorPickerDialog(wvHwnd, "")
if c1 == "" {
continue
}
c2 := colorPickerDialog(wvHwnd, "")
if c2 == "" {
c2 = "#16213e"
}
cfg := loadConfig()
cfg.WallpaperType = WPColor
cfg.Color1 = c1
cfg.Color2 = c2
cfg.ColorGradient = true
saveConfig(cfg)
for _, it := range themeItems {
it.Uncheck()
}
log.Printf("渐变壁纸: %s -> %s", c1, c2)
reloadWallpaper()
}
}()
// 星座选择监听
for i, item := range zodiacItems {
go func(idx int, mi *systray.MenuItem) {
name := zodiacs[idx]
log.Printf("星座监听启动: %s", name)
for {
<-mi.ClickedCh
log.Printf("星座点击: %s", name)
cfg := loadConfig()
cfg.Zodiac = name
saveConfig(cfg)
@@ -77,11 +206,9 @@ func onSystrayReady() {
// 城市选择监听
for i, item := range cityItems {
go func(idx int, mi *systray.MenuItem) {
log.Printf("城市监听启动: %s", cities[idx].Name)
for {
<-mi.ClickedCh
city := cities[idx]
log.Printf("城市点击: %s", city.Name)
cfg := loadConfig()
cfg.City = city.ID
saveConfig(cfg)
@@ -96,13 +223,11 @@ func onSystrayReady() {
// 暂停
go func() {
log.Println("暂停监听启动")
for {
<-mPause.ClickedCh
newVal := 1 - atomic.LoadInt32(&paused)
atomic.StoreInt32(&paused, newVal)
isPaused := newVal == 1
log.Printf("暂停切换: paused=%v", isPaused)
if isPaused {
mPause.SetTitle("继续")
} else {
@@ -120,6 +245,7 @@ func onSystrayReady() {
go startWebView()
go weatherLoop()
go bingWallpaperLoop()
}
func startWebView() {
@@ -145,18 +271,13 @@ func startWebView() {
log.Fatal("WebView2 create failed")
}
htmlData, err := fs.ReadFile("web/wallpaper.html")
if err != nil {
log.Fatal("读取 wallpaper.html 失败:", err)
}
wv.Bind("setZodiacFromGo", func(zodiac string) error {
cfg := loadConfig()
cfg.Zodiac = zodiac
return saveConfig(cfg)
})
wv.SetHtml(string(htmlData))
wv.SetHtml(buildWallpaperHTML(loadConfig()))
time.Sleep(1 * time.Second)
wvHwnd = uintptr(wv.Window())
@@ -165,17 +286,14 @@ func startWebView() {
procMoveWindow.Call(wvHwnd, uintptr(^uint(0)), uintptr(^uint(0)), uintptr(screenW+2), uintptr(screenH+2), 1)
log.Printf("壁纸已嵌入: HWND=0x%x, %dx%d", wvHwnd, screenW, screenH)
// 注入配置
go func() {
time.Sleep(500 * time.Millisecond)
cfg := loadConfig()
evalJS(fmt.Sprintf(`window.userZodiac = %q;`, cfg.Zodiac))
log.Printf("配置已注入: zodiac=%s", cfg.Zodiac)
}()
go fullscreenMonitor()
// 延迟嵌入 WorkerW
go func() {
time.Sleep(3 * time.Second)
workerw := findWorkerW()
@@ -186,7 +304,6 @@ func startWebView() {
}
}()
// 消息循环
type msg struct {
hwnd uintptr
message uint32
@@ -196,7 +313,6 @@ func startWebView() {
pt struct{ x, y int32 }
}
var m msg
log.Println("启动自定义消息循环...")
for {
ret, _, _ := procGetMessageW.Call(
uintptr(unsafe.Pointer(&m)),
@@ -215,7 +331,15 @@ func startWebView() {
}
}
}
nextMsg:
if m.message == wmSetHtml {
select {
case html := <-htmlQueue:
wv.SetHtml(html)
default:
}
goto nextMsg
}
nextMsg:
procTranslateMessage.Call(uintptr(unsafe.Pointer(&m)))
procDispatchMessageW.Call(uintptr(unsafe.Pointer(&m)))
}