Icon fixes (windows), see #35.

This commit is contained in:
Nuno Cruces 2022-07-26 14:49:49 +01:00
parent ab2a08c75a
commit 566fbb4e60
6 changed files with 36 additions and 34 deletions

View file

@ -223,13 +223,11 @@ func pickFolders(opts options, multi bool) (string, []string, error) {
}
}
if opts.ctx != nil || opts.windowIcon != nil {
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
if err != nil {
return "", nil, err
}
defer unhook()
}
err = dialog.Show(owner)
if opts.ctx != nil && opts.ctx.Err() != nil {
@ -293,13 +291,11 @@ func browseForFolder(opts options) (string, []string, error) {
args.CallbackFunc = syscall.NewCallback(browseForFolderCallback)
}
if opts.ctx != nil || opts.windowIcon != nil {
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
if err != nil {
return "", nil, err
}
defer unhook()
}
ptr := win.SHBrowseForFolder(&args)
if opts.ctx != nil && opts.ctx.Err() != nil {

View file

@ -380,7 +380,7 @@ type CWPRETSTRUCT struct {
}
//sys CallNextHookEx(hk Handle, code int32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) = user32.CallNextHookEx
//sys CreateIconFromResource(resBits []byte, icon bool, ver uint32) (ret Handle, err error) = user32.CreateIconFromResource
//sys CreateIconFromResourceEx(resBits []byte, icon bool, ver uint32, cx int, cy int, flags int) (ret Handle, err error) = user32.CreateIconFromResourceEx
//sys CreateWindowEx(exStyle uint32, className *uint16, windowName *uint16, style uint32, x int, y int, width int, height int, parent HWND, menu Handle, instance Handle, param unsafe.Pointer) (ret HWND, err error) = user32.CreateWindowExW
//sys DefWindowProc(wnd HWND, msg uint32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) = user32.DefWindowProcW
//sys DestroyIcon(icon Handle) (err error) = user32.DestroyIcon

View file

@ -70,7 +70,7 @@ var (
procSHGetPathFromIDListEx = modshell32.NewProc("SHGetPathFromIDListEx")
procShell_NotifyIconW = modshell32.NewProc("Shell_NotifyIconW")
procCallNextHookEx = moduser32.NewProc("CallNextHookEx")
procCreateIconFromResource = moduser32.NewProc("CreateIconFromResource")
procCreateIconFromResourceEx = moduser32.NewProc("CreateIconFromResourceEx")
procCreateWindowExW = moduser32.NewProc("CreateWindowExW")
procDefWindowProcW = moduser32.NewProc("DefWindowProcW")
procDestroyIcon = moduser32.NewProc("DestroyIcon")
@ -267,7 +267,7 @@ func CallNextHookEx(hk Handle, code int32, wparam uintptr, lparam unsafe.Pointer
return
}
func CreateIconFromResource(resBits []byte, icon bool, ver uint32) (ret Handle, err error) {
func CreateIconFromResourceEx(resBits []byte, icon bool, ver uint32, cx int, cy int, flags int) (ret Handle, err error) {
var _p0 *byte
if len(resBits) > 0 {
_p0 = &resBits[0]
@ -276,7 +276,7 @@ func CreateIconFromResource(resBits []byte, icon bool, ver uint32) (ret Handle,
if icon {
_p1 = 1
}
r0, _, e1 := syscall.Syscall6(procCreateIconFromResource.Addr(), 4, uintptr(unsafe.Pointer(_p0)), uintptr(len(resBits)), uintptr(_p1), uintptr(ver), 0, 0)
r0, _, e1 := syscall.Syscall9(procCreateIconFromResourceEx.Addr(), 7, uintptr(unsafe.Pointer(_p0)), uintptr(len(resBits)), uintptr(_p1), uintptr(ver), uintptr(cx), uintptr(cy), uintptr(flags), 0, 0)
ret = Handle(r0)
if ret == 0 {
err = errnoErr(e1)

View file

@ -82,8 +82,9 @@ func message(kind messageKind, text string, opts options) error {
}
}
func hookMessageDialog(opts options) (unhook context.CancelFunc, err error) {
func hookMessageDialog(opts options) (context.CancelFunc, error) {
var init func(wnd win.HWND)
var icon icon
if opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil {
init = func(wnd win.HWND) {
if opts.okLabel != nil {
@ -97,13 +98,19 @@ func hookMessageDialog(opts options) (unhook context.CancelFunc, err error) {
win.SetDlgItemText(wnd, win.IDNO, strptr(*opts.extraButton))
}
icon := getIcon(opts.icon)
if icon.handle != 0 {
defer icon.delete()
ctl, _ := win.GetDlgItem(wnd, win.IDC_STATIC_OK)
win.SendMessage(ctl, win.STM_SETICON, uintptr(icon.handle), 0)
}
}
}
return hookDialog(opts.ctx, opts.windowIcon, nil, init)
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, init)
if err != nil || opts.icon == nil {
return unhook, err
}
icon = getIcon(opts.icon)
return func() {
icon.delete()
unhook()
}, nil
}

View file

@ -41,7 +41,7 @@ func notify(text string, opts options) error {
icon := getIcon(opts.icon)
if icon.handle != 0 {
defer icon.delete()
args.Icon = win.Handle(icon.handle)
args.Icon = icon.handle
args.Flags |= win.NIF_ICON
args.InfoFlags |= win.NIIF_USER
}

View file

@ -75,7 +75,7 @@ func setupEnumCallback(wnd win.HWND, lparam *win.HWND) uintptr {
}
func hookDialog(ctx context.Context, icon any, title *string, init func(wnd win.HWND)) (unhook context.CancelFunc, err error) {
if ctx == nil && icon == nil && init == nil {
if ctx == nil && icon == nil && title == nil && init == nil {
return func() {}, nil
}
if ctx != nil && ctx.Err() != nil {
@ -94,7 +94,7 @@ type dialogHook struct {
wnd uintptr
hook win.Handle
done chan struct{}
icon any
icon icon
title *string
init func(wnd win.HWND)
}
@ -111,7 +111,7 @@ func newDialogHook(ctx context.Context, icon any, title *string, init func(wnd w
ctx: ctx,
tid: tid,
hook: hk,
icon: icon,
icon: getIcon(icon),
title: title,
init: init,
}
@ -132,12 +132,8 @@ func dialogHookProc(code int32, wparam uintptr, lparam *win.CWPRETSTRUCT) uintpt
if hook.ctx != nil && hook.ctx.Err() != nil {
win.SendMessage(lparam.Wnd, win.WM_SYSCOMMAND, win.SC_CLOSE, 0)
} else {
if hook.icon != nil {
icon := getIcon(hook.icon)
if icon.handle != 0 {
defer icon.delete()
win.SendMessage(lparam.Wnd, win.WM_SETICON, 0, uintptr(icon.handle))
}
if hook.icon.handle != 0 {
win.SendMessage(lparam.Wnd, win.WM_SETICON, 0, uintptr(hook.icon.handle))
}
if hook.title != nil {
win.SetWindowText(lparam.Wnd, strptr(*hook.title))
@ -155,6 +151,7 @@ func (h *dialogHook) unhook() {
if h.done != nil {
close(h.done)
}
h.icon.delete()
win.UnhookWindowsHookEx(h.hook)
}
@ -289,17 +286,19 @@ func getIcon(i any) icon {
res.handle, _ = win.LoadImage(0,
strptr(path),
win.IMAGE_ICON, 0, 0,
win.LR_LOADFROMFILE|win.LR_DEFAULTSIZE|win.LR_SHARED)
win.LR_LOADFROMFILE|win.LR_DEFAULTSIZE)
res.destroy = true
case bytes.HasPrefix(data, []byte("\x89PNG\r\n\x1a\n")):
res.handle, err = win.CreateIconFromResource(
data, true, 0x00030000)
res.handle, _ = win.CreateIconFromResourceEx(
data, true, 0x00030000, 0, 0,
win.LR_DEFAULTSIZE)
res.destroy = true
}
return res
}
func (i *icon) delete() {
if i.handle != 0 {
if i.destroy && i.handle != 0 {
win.DestroyIcon(i.handle)
i.handle = 0
}