From 7ac67006b5f3ef03f38e7d56bfe0da739579c8f3 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Wed, 27 Jul 2022 00:25:18 +0100 Subject: [PATCH] Icons (windows), see #35. --- internal/win/user32.go | 6 ----- internal/win/zsyscall_windows.go | 10 -------- util_windows.go | 44 +++++++++++++++++++------------- 3 files changed, 26 insertions(+), 34 deletions(-) diff --git a/internal/win/user32.go b/internal/win/user32.go index 1b31505..1b4370f 100644 --- a/internal/win/user32.go +++ b/internal/win/user32.go @@ -231,11 +231,6 @@ const ( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = ^uintptr(4) + 1 DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED = ^uintptr(5) + 1 - // LoadImage type - IMAGE_BITMAP = 0 - IMAGE_ICON = 1 - IMAGE_CURSOR = 2 - // LoadIcon resources IDI_APPLICATION = 32512 IDI_ERROR = 32513 @@ -398,7 +393,6 @@ type CWPRETSTRUCT struct { //sys getWindowTextLength(wnd HWND) (ret int, err error) = user32.GetWindowTextLengthW //sys IsDialogMessage(wnd HWND, msg *MSG) (ok bool) = user32.IsDialogMessageW //sys LoadIcon(instance Handle, resource uintptr) (ret Handle, err error) = user32.LoadIconW -//sys LoadImage(instance Handle, name *uint16, typ int, cx int, cy int, load int) (ret Handle, err error) = user32.LoadImageW //sys PostQuitMessage(exitCode int) = user32.PostQuitMessage //sys RegisterClassEx(cls *WNDCLASSEX) (err error) = user32.RegisterClassExW //sys ReleaseDC(wnd HWND, dc Handle) (ok bool) = user32.ReleaseDC diff --git a/internal/win/zsyscall_windows.go b/internal/win/zsyscall_windows.go index 34884f6..2716faa 100644 --- a/internal/win/zsyscall_windows.go +++ b/internal/win/zsyscall_windows.go @@ -89,7 +89,6 @@ var ( procGetWindowTextW = moduser32.NewProc("GetWindowTextW") procIsDialogMessageW = moduser32.NewProc("IsDialogMessageW") procLoadIconW = moduser32.NewProc("LoadIconW") - procLoadImageW = moduser32.NewProc("LoadImageW") procPostQuitMessage = moduser32.NewProc("PostQuitMessage") procRegisterClassExW = moduser32.NewProc("RegisterClassExW") procReleaseDC = moduser32.NewProc("ReleaseDC") @@ -433,15 +432,6 @@ func LoadIcon(instance Handle, resource uintptr) (ret Handle, err error) { return } -func LoadImage(instance Handle, name *uint16, typ int, cx int, cy int, load int) (ret Handle, err error) { - r0, _, e1 := syscall.Syscall6(procLoadImageW.Addr(), 6, uintptr(instance), uintptr(unsafe.Pointer(name)), uintptr(typ), uintptr(cx), uintptr(cy), uintptr(load)) - ret = Handle(r0) - if ret == 0 { - err = errnoErr(e1) - } - return -} - func PostQuitMessage(exitCode int) { syscall.Syscall(procPostQuitMessage.Addr(), 1, uintptr(exitCode), 0, 0) return diff --git a/util_windows.go b/util_windows.go index 6c37dd5..7f609af 100644 --- a/util_windows.go +++ b/util_windows.go @@ -3,6 +3,7 @@ package zenity import ( "bytes" "context" + "io" "os" "path/filepath" "runtime" @@ -13,7 +14,6 @@ import ( "unsafe" "github.com/ncruces/zenity/internal/win" - "golang.org/x/sys/windows" ) const ( @@ -278,39 +278,47 @@ func getIcon(i any) (icon icon, err error) { return icon, nil } - data, err := os.ReadFile(path) + file, err := os.Open(path) + if err != nil { + return icon, err + } + defer file.Close() + + var peek [8]byte + _, err = file.ReadAt(peek[:], 0) if err != nil { return icon, err } - switch { - case bytes.HasPrefix(data, []byte("\x00\x00\x01\x00")): - icon.handle, err = win.LoadImage(0, - strptr(path), - win.IMAGE_ICON, 0, 0, - win.LR_LOADFROMFILE|win.LR_DEFAULTSIZE) - icon.destroy = true - case bytes.HasPrefix(data, []byte("\x89PNG\r\n\x1a\n")): + if bytes.Equal(peek[:], []byte("\x89PNG\r\n\x1a\n")) { + data, err := io.ReadAll(file) + if err != nil { + return icon, err + } icon.handle, err = win.CreateIconFromResourceEx( data, true, 0x00030000, 0, 0, win.LR_DEFAULTSIZE) - icon.destroy = true - case bytes.HasPrefix(data, []byte("MZ")): - var instance windows.Handle - instance, err = win.GetModuleHandle(nil) if err != nil { - break + return icon, err + } + } else { + instance, err := win.GetModuleHandle(nil) + if err != nil { + return icon, err } path, err = filepath.Abs(path) if err != nil { - break + return icon, err } var i uint16 icon.handle, err = win.ExtractAssociatedIcon( instance, strptr(path), &i) - icon.destroy = true + if err != nil { + return icon, err + } } - return icon, err + icon.destroy = true + return icon, nil } func (i *icon) delete() {