Skip to content

Commit f9ef2ce

Browse files
Copilotohidurbappy
andcommitted
Fix tray icon display by implementing proper ICO file loading from embedded data
Co-authored-by: ohidurbappy <22405409+ohidurbappy@users.noreply.github.com>
1 parent b6ac292 commit f9ef2ce

1 file changed

Lines changed: 52 additions & 19 deletions

File tree

main.go

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ var (
6565
postQuitMessage = user32.NewProc("PostQuitMessage")
6666
loadIcon = user32.NewProc("LoadIconW")
6767
loadImage = user32.NewProc("LoadImageW")
68+
createIconFromResourceEx = user32.NewProc("CreateIconFromResourceEx")
6869
getModuleHandle = kernel32.NewProc("GetModuleHandleW")
6970
)
7071

@@ -162,28 +163,60 @@ func initializeSystemTray() {
162163
}
163164

164165
func createIconFromData(data []byte) syscall.Handle {
165-
// Create icon from embedded ICO data
166-
// For now, we'll use different system icons to represent light/dark modes
167-
// This should be enhanced to properly load the embedded .ico files
166+
// ICO files start with an ICONDIR structure, but for CreateIconFromResourceEx
167+
// we need to skip the ICO header and pass just the icon image data
168+
// ICO format: ICONDIR (6 bytes) + ICONDIRENTRY array + actual icon data
168169

169-
if len(data) > 0 {
170-
// In a full implementation, we'd parse the ICO format and use:
171-
// CreateIconFromResource or CreateIconFromResourceEx
172-
173-
// For demo purposes, use different system icons:
174-
if len(data) == len(light_mode) {
175-
// Light mode icon - use sun-like icon
176-
icon, _, _ := loadIcon.Call(0, 32516) // IDI_WARNING (triangle, yellowish)
177-
return syscall.Handle(icon)
178-
} else {
179-
// Dark mode icon - use moon-like icon
180-
icon, _, _ := loadIcon.Call(0, 32513) // IDI_QUESTION (blue)
181-
return syscall.Handle(icon)
182-
}
170+
if len(data) < 6 {
171+
// Fallback to system icon if data is invalid
172+
icon, _, _ := loadIcon.Call(0, 32512) // IDI_APPLICATION
173+
return syscall.Handle(icon)
174+
}
175+
176+
// Parse ICO header to find the first icon entry
177+
// ICONDIR: Reserved(2) + Type(2) + Count(2)
178+
iconCount := uint16(data[4]) | (uint16(data[5]) << 8)
179+
if iconCount == 0 || len(data) < 6 + int(iconCount)*16 {
180+
// Fallback to system icon if structure is invalid
181+
icon, _, _ := loadIcon.Call(0, 32512) // IDI_APPLICATION
182+
return syscall.Handle(icon)
183+
}
184+
185+
// Get first ICONDIRENTRY (16 bytes starting at offset 6)
186+
entryOffset := 6
187+
imageOffset := uint32(data[entryOffset+12]) | (uint32(data[entryOffset+13]) << 8) |
188+
(uint32(data[entryOffset+14]) << 16) | (uint32(data[entryOffset+15]) << 24)
189+
imageSize := uint32(data[entryOffset+8]) | (uint32(data[entryOffset+9]) << 8) |
190+
(uint32(data[entryOffset+10]) << 16) | (uint32(data[entryOffset+11]) << 24)
191+
192+
// Validate image offset and size
193+
if imageOffset >= uint32(len(data)) || imageOffset+imageSize > uint32(len(data)) {
194+
// Fallback to system icon if offset/size is invalid
195+
icon, _, _ := loadIcon.Call(0, 32512) // IDI_APPLICATION
196+
return syscall.Handle(icon)
197+
}
198+
199+
// Extract the actual icon image data (skip ICO header)
200+
imageData := data[imageOffset:imageOffset+imageSize]
201+
202+
// Create icon from the image data
203+
icon, _, _ := createIconFromResourceEx.Call(
204+
uintptr(unsafe.Pointer(&imageData[0])), // pointer to icon data
205+
uintptr(imageSize), // size of icon data
206+
1, // fIcon = TRUE (this is an icon, not cursor)
207+
0x00030000, // dwVersion = 0x00030000
208+
0, // cxDesired = 0 (use default)
209+
0, // cyDesired = 0 (use default)
210+
0, // Flags = 0 (default behavior)
211+
)
212+
213+
if icon != 0 {
214+
return syscall.Handle(icon)
183215
}
184216

185-
icon, _, _ := loadIcon.Call(0, 32512) // IDI_APPLICATION (default)
186-
return syscall.Handle(icon)
217+
// Final fallback to system icon if CreateIconFromResourceEx failed
218+
fallbackIcon, _, _ := loadIcon.Call(0, 32512) // IDI_APPLICATION
219+
return syscall.Handle(fallbackIcon)
187220
}
188221

189222
func createTrayIcon() {

0 commit comments

Comments
 (0)