mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 08:00:50 +08:00
138 lines
3.0 KiB
Go
138 lines
3.0 KiB
Go
//go:build windows
|
|
|
|
package w32
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"image"
|
|
"image/draw"
|
|
"image/png"
|
|
"unsafe"
|
|
)
|
|
|
|
func CreateIconFromResourceEx(presbits uintptr, dwResSize uint32, isIcon bool, version uint32, cxDesired int, cyDesired int, flags uint) (uintptr, error) {
|
|
icon := 0
|
|
if isIcon {
|
|
icon = 1
|
|
}
|
|
r, _, err := procCreateIconFromResourceEx.Call(
|
|
presbits,
|
|
uintptr(dwResSize),
|
|
uintptr(icon),
|
|
uintptr(version),
|
|
uintptr(cxDesired),
|
|
uintptr(cyDesired),
|
|
uintptr(flags),
|
|
)
|
|
|
|
if r == 0 {
|
|
return 0, err
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func isPNG(fileData []byte) bool {
|
|
if len(fileData) < 4 {
|
|
return false
|
|
}
|
|
return string(fileData[:4]) == "\x89PNG"
|
|
}
|
|
|
|
func isICO(fileData []byte) bool {
|
|
if len(fileData) < 4 {
|
|
return false
|
|
}
|
|
return string(fileData[:4]) == "\x00\x00\x01\x00"
|
|
}
|
|
|
|
// CreateSmallHIconFromImage creates a HICON from a PNG or ICO file
|
|
func CreateSmallHIconFromImage(fileData []byte) (HICON, error) {
|
|
if len(fileData) < 8 {
|
|
return 0, fmt.Errorf("invalid file format")
|
|
}
|
|
|
|
if !isPNG(fileData) && !isICO(fileData) {
|
|
return 0, fmt.Errorf("unsupported file format")
|
|
}
|
|
iconWidth := GetSystemMetrics(SM_CXSMICON)
|
|
iconHeight := GetSystemMetrics(SM_CYSMICON)
|
|
icon, err := CreateIconFromResourceEx(
|
|
uintptr(unsafe.Pointer(&fileData[0])),
|
|
uint32(len(fileData)),
|
|
true,
|
|
0x00030000,
|
|
iconWidth,
|
|
iconHeight,
|
|
LR_DEFAULTSIZE)
|
|
return HICON(icon), err
|
|
}
|
|
|
|
// CreateLargeHIconFromImage creates a HICON from a PNG or ICO file
|
|
func CreateLargeHIconFromImage(fileData []byte) (HICON, error) {
|
|
if len(fileData) < 8 {
|
|
return 0, fmt.Errorf("invalid file format")
|
|
}
|
|
|
|
if !isPNG(fileData) && !isICO(fileData) {
|
|
return 0, fmt.Errorf("unsupported file format")
|
|
}
|
|
iconWidth := GetSystemMetrics(SM_CXICON)
|
|
iconHeight := GetSystemMetrics(SM_CXICON)
|
|
icon, err := CreateIconFromResourceEx(
|
|
uintptr(unsafe.Pointer(&fileData[0])),
|
|
uint32(len(fileData)),
|
|
true,
|
|
0x00030000,
|
|
iconWidth,
|
|
iconHeight,
|
|
LR_DEFAULTSIZE)
|
|
return HICON(icon), err
|
|
}
|
|
|
|
func SetWindowIcon(hwnd HWND, icon HICON) {
|
|
SendMessage(hwnd, WM_SETICON, ICON_SMALL, uintptr(icon))
|
|
}
|
|
|
|
func pngToImage(data []byte) (*image.RGBA, error) {
|
|
img, err := png.Decode(bytes.NewReader(data))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
bounds := img.Bounds()
|
|
rgba := image.NewRGBA(bounds)
|
|
draw.Draw(rgba, bounds, img, bounds.Min, draw.Src)
|
|
return rgba, nil
|
|
}
|
|
|
|
func SetMenuIcons(parentMenu HMENU, itemID int, unchecked []byte, checked []byte) error {
|
|
if unchecked == nil {
|
|
return fmt.Errorf("invalid unchecked bitmap")
|
|
}
|
|
var err error
|
|
var uncheckedIcon, checkedIcon HBITMAP
|
|
var uncheckedImage, checkedImage *image.RGBA
|
|
uncheckedImage, err = pngToImage(unchecked)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
uncheckedIcon, err = CreateHBITMAPFromImage(uncheckedImage)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if checked != nil {
|
|
checkedImage, err = pngToImage(checked)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
checkedIcon, err = CreateHBITMAPFromImage(checkedImage)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
checkedIcon = uncheckedIcon
|
|
}
|
|
return SetMenuItemBitmaps(parentMenu, uint32(itemID), MF_BYCOMMAND, checkedIcon, uncheckedIcon)
|
|
}
|