Set window icon on Admin Panel (title bar + taskbar)
All checks were successful
Release / build (push) Successful in 2m34s

Embed the blue SyncWarden shield icon in the panel binary and set it
as the window icon via Win32 SendMessage/WM_SETICON on startup.
Uses the syncing (blue) variant as the status-independent panel icon.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Axel Meyer
2026-03-03 23:26:11 +01:00
parent 110bb715ff
commit 11e5c9b915
4 changed files with 96 additions and 0 deletions

7
cmd/panel/icon_other.go Normal file
View File

@@ -0,0 +1,7 @@
//go:build !windows
package main
import "unsafe"
func setWindowIcon(windowPtr unsafe.Pointer) {}

85
cmd/panel/icon_windows.go Normal file
View File

@@ -0,0 +1,85 @@
//go:build windows
package main
import (
"bytes"
_ "embed"
"encoding/binary"
"os"
"path/filepath"
"syscall"
"unsafe"
)
//go:embed panel_icon.png
var panelIconPNG []byte
func setWindowIcon(windowPtr unsafe.Pointer) {
hwnd := uintptr(windowPtr)
if hwnd == 0 {
return
}
// Write a temp ICO file (Windows LoadImage needs a file path)
icoData := wrapPNG(panelIconPNG, 64, 64)
icoPath := filepath.Join(os.TempDir(), "syncwarden-panel.ico")
if err := os.WriteFile(icoPath, icoData, 0644); err != nil {
return
}
user32 := syscall.NewLazyDLL("user32.dll")
loadImage := user32.NewProc("LoadImageW")
sendMessage := user32.NewProc("SendMessageW")
pathW, _ := syscall.UTF16PtrFromString(icoPath)
const (
imageIcon = 1
lrLoadFromFile = 0x0010
wmSetIcon = 0x0080
iconBig = 1
iconSmall = 0
)
hBig, _, _ := loadImage.Call(0, uintptr(unsafe.Pointer(pathW)), imageIcon, 32, 32, lrLoadFromFile)
if hBig != 0 {
sendMessage.Call(hwnd, wmSetIcon, iconBig, hBig)
}
hSmall, _, _ := loadImage.Call(0, uintptr(unsafe.Pointer(pathW)), imageIcon, 16, 16, lrLoadFromFile)
if hSmall != 0 {
sendMessage.Call(hwnd, wmSetIcon, iconSmall, hSmall)
}
}
func wrapPNG(pngData []byte, width, height int) []byte {
const headerSize = 6
const entrySize = 16
imageOffset := headerSize + entrySize
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, uint16(0))
binary.Write(buf, binary.LittleEndian, uint16(1))
binary.Write(buf, binary.LittleEndian, uint16(1))
w := byte(width)
if width >= 256 {
w = 0
}
h := byte(height)
if height >= 256 {
h = 0
}
buf.WriteByte(w)
buf.WriteByte(h)
buf.WriteByte(0)
buf.WriteByte(0)
binary.Write(buf, binary.LittleEndian, uint16(1))
binary.Write(buf, binary.LittleEndian, uint16(32))
binary.Write(buf, binary.LittleEndian, uint32(len(pngData)))
binary.Write(buf, binary.LittleEndian, uint32(imageOffset))
buf.Write(pngData)
return buf.Bytes()
}

View File

@@ -19,6 +19,10 @@ func main() {
w.SetTitle("SyncWarden — Admin Panel")
w.SetSize(1024, 768, webview.HintNone)
// Set window icon (title bar + taskbar)
setWindowIcon(w.Window())
w.Navigate(*addr)
w.Run()
}

BIN
cmd/panel/panel_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB