Displaying application icons in the Windows system tray significantly enhances the usability of background applications. However, when implementing Windows tray icons in Go, there’s a limitation: unlike macOS, only the ICO format is supported. This article explains this difference and introduces practical solutions for converting PNG images to ICO.
Icon Format Differences Between Windows and macOS
When using libraries that handle tray icons in Go (e.g., github.com/getlantern/systray), there are crucial differences:
- macOS: Supports
.ico,.jpg,.pngimage formats. - Windows: Supports only the
.icoformat.
The reason Windows exclusively supports the ICO format lies in the legacy design of the Windows API and its system-level icon management. Tray icons need to contain images of various resolutions, such as 16x16, 24x24, and 32x32. The ICO format is designed to efficiently pack these multi-resolution images into a single file.
Problems When Using PNG Files
If you mistakenly specify a PNG file (e.g., happy.png) as an icon, you will encounter results like these:
ERROR systray: systray_windows.go:845 Unable to set icon: The operation completed successfully. [error=Unable to set icon: %v error_location=github.com/getlantern/systray.SetIcon (systray_windows.go:845) error_op= error_text=Unable to set icon: The operation completed successfully. error_type=errors.Error]
ERROR systray: systray_windows.go:845 at github.com/getlantern/systray.SetIcon (systray_windows.go:845)
ERROR systray: systray_windows.go:845 at main.onReady (main.go:18)
ERROR systray: systray_windows.go:845 at github.com/getlantern/systray.Register.func2 (systray.go:94)
ERROR systray: systray_windows.go:845 at runtime.goexit (asm_amd64.s:1693)
ERROR systray: systray_windows.go:845 Caused by: The operation completed successfully.
This error message can be confusing for several reasons:
- Contradiction of “operation completed successfully” message: This is a misinterpretation of the error code returned by the Windows API; the operation actually failed.
- Visual result: A blank space or a broken image appears in the tray icon area.
- Difficulty in identifying the cause: The lack of a clear message indicating that the PNG format is not supported makes it difficult for users to understand the root cause.
Converting from PNG to ICO
If you have a PNG image, you must convert it to the ICO format. Here are two practical methods.
1. Online Tool: CloudConvert
Advantages:
- No installation required
- Instantly usable in a web browser
- Supports batch conversion
How to Use:
- Access https://cloudconvert.com/png-to-ico
- Upload or drag and drop your PNG file
- Automatically converts to ICO format
- Download the converted file
Suitable for:
- One-time conversion needs
- Processing multiple files at once
- Preference for online tools
2. Downloadable Tool: SimplyIcon
Features:
- Windows-exclusive desktop application
- Lightweight, based on .NET Framework 2.0
- Intuitive drag-and-drop interface
- Useful when you prefer not to upload files to the internet
Automatically Generated Resolutions:
- 32x32 (required)
- 24x24
- 16x16
- 128x128 (if the original image is 128x128 or larger)
How to Use:
- Download from https://qrli.github.io/simplyicon/
- Run the program
- Drag and drop your PNG image onto the program window
- The ICO file is automatically generated
Suitable for:
- Frequent conversion tasks
- Working in an offline environment
- Need for fast processing
- Utilizing automatic multi-resolution generation
Usage in Go Code
Go’s embed package allows you to directly include icon files within your binary. This is very convenient as it eliminates the need for separate file management during deployment.
package main
import (
_ "embed" // For embedding the icon
"log"
"github.com/getlantern/systray"
)
//go:embed happy.ico
var iconData []byte
func main() {
systray.Run(onReady, onExit)
}
func onReady() {
systray.SetIcon(iconData)
systray.SetTitle("Happy Icon")
systray.SetTooltip("My happy icon application")
mQuit := systray.AddMenuItem("Quit", "Quit the whole app")
go func() {
<-mQuit.ClickedCh
systray.Quit()
}()
}
func onExit() {
// clean up here
log.Println("Exiting application")
}
Code Explanation:
_ "embed": Explicitly imports the embed package.//go:embed happy.ico: Embeds thehappy.icofile into theiconDatavariable at compile time. You must use an.icofile.systray.SetIcon(iconData): Sets the embedded icon data as the tray icon.
Important Points:
happy.icomust be located in the project directory and accessible at compile time.- You cannot use PNG files directly. They must be converted to ICO format.
- Including the icon in the binary increases the executable file size but eliminates the need to manage external files during deployment.
- This method is very stable in production environments.
Icon insertion successful!
Workflow Summary
- Prepare PNG Image: Use PNG from web projects or original artwork.
- Convert to ICO: Create an
.icofile using CloudConvert or SimplyIcon (essential!). - Add to Go Project: Copy the converted
.icofile to your project directory. - Embed in Binary: Include it at build time using the
//go:embeddirective (specify the.icofile). - Deploy: Distribute as a single executable (no external files needed).
Recommendations
Image Preparation:
- Original PNGs are recommended to have a resolution of at least 32x32.
- Optimal resolution is 128x128 or higher (to support various DPIs).
- Utilize PNG’s alpha channel for transparency if needed.
Format Conversion:
- Important: Windows tray only supports the ICO format. Using PNG files will result in errors.
- Conversion choice:
- Quick one-time tasks: CloudConvert
- Repetitive conversions: SimplyIcon
- Automation needed: Consider command-line tools (ImageMagick, ffmpeg, etc.)
Deployment Strategy:
- Using the embed package allows deployment as a single binary.
- Recompilation of code is required when updating icons (simple and easy to version control).
- ICO format verification: Always ensure the
.icoextension when embedding.
Conclusion
Windows tray icons only support the ICO format, and using PNG files will cause errors and display a blank space in the tray. This is not a limitation but part of the Windows system design, and it can be easily resolved using simple tools like CloudConvert or SimplyIcon. When combined with Go’s embed package, deployment becomes straightforward, establishing a stable icon management method for production environments.
Happy coding! 😊