Icon fixes (windows), see #35.
This commit is contained in:
parent
ab2a08c75a
commit
566fbb4e60
6 changed files with 36 additions and 34 deletions
|
@ -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)
|
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
defer unhook()
|
defer unhook()
|
||||||
}
|
|
||||||
|
|
||||||
err = dialog.Show(owner)
|
err = dialog.Show(owner)
|
||||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||||
|
@ -293,13 +291,11 @@ func browseForFolder(opts options) (string, []string, error) {
|
||||||
args.CallbackFunc = syscall.NewCallback(browseForFolderCallback)
|
args.CallbackFunc = syscall.NewCallback(browseForFolderCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.ctx != nil || opts.windowIcon != nil {
|
|
||||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
defer unhook()
|
defer unhook()
|
||||||
}
|
|
||||||
|
|
||||||
ptr := win.SHBrowseForFolder(&args)
|
ptr := win.SHBrowseForFolder(&args)
|
||||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||||
|
|
|
@ -380,7 +380,7 @@ type CWPRETSTRUCT struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys CallNextHookEx(hk Handle, code int32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) = user32.CallNextHookEx
|
//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 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 DefWindowProc(wnd HWND, msg uint32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) = user32.DefWindowProcW
|
||||||
//sys DestroyIcon(icon Handle) (err error) = user32.DestroyIcon
|
//sys DestroyIcon(icon Handle) (err error) = user32.DestroyIcon
|
||||||
|
|
|
@ -70,7 +70,7 @@ var (
|
||||||
procSHGetPathFromIDListEx = modshell32.NewProc("SHGetPathFromIDListEx")
|
procSHGetPathFromIDListEx = modshell32.NewProc("SHGetPathFromIDListEx")
|
||||||
procShell_NotifyIconW = modshell32.NewProc("Shell_NotifyIconW")
|
procShell_NotifyIconW = modshell32.NewProc("Shell_NotifyIconW")
|
||||||
procCallNextHookEx = moduser32.NewProc("CallNextHookEx")
|
procCallNextHookEx = moduser32.NewProc("CallNextHookEx")
|
||||||
procCreateIconFromResource = moduser32.NewProc("CreateIconFromResource")
|
procCreateIconFromResourceEx = moduser32.NewProc("CreateIconFromResourceEx")
|
||||||
procCreateWindowExW = moduser32.NewProc("CreateWindowExW")
|
procCreateWindowExW = moduser32.NewProc("CreateWindowExW")
|
||||||
procDefWindowProcW = moduser32.NewProc("DefWindowProcW")
|
procDefWindowProcW = moduser32.NewProc("DefWindowProcW")
|
||||||
procDestroyIcon = moduser32.NewProc("DestroyIcon")
|
procDestroyIcon = moduser32.NewProc("DestroyIcon")
|
||||||
|
@ -267,7 +267,7 @@ func CallNextHookEx(hk Handle, code int32, wparam uintptr, lparam unsafe.Pointer
|
||||||
return
|
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
|
var _p0 *byte
|
||||||
if len(resBits) > 0 {
|
if len(resBits) > 0 {
|
||||||
_p0 = &resBits[0]
|
_p0 = &resBits[0]
|
||||||
|
@ -276,7 +276,7 @@ func CreateIconFromResource(resBits []byte, icon bool, ver uint32) (ret Handle,
|
||||||
if icon {
|
if icon {
|
||||||
_p1 = 1
|
_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)
|
ret = Handle(r0)
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
err = errnoErr(e1)
|
err = errnoErr(e1)
|
||||||
|
|
|
@ -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 init func(wnd win.HWND)
|
||||||
|
var icon icon
|
||||||
if opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil {
|
if opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil {
|
||||||
init = func(wnd win.HWND) {
|
init = func(wnd win.HWND) {
|
||||||
if opts.okLabel != nil {
|
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))
|
win.SetDlgItemText(wnd, win.IDNO, strptr(*opts.extraButton))
|
||||||
}
|
}
|
||||||
|
|
||||||
icon := getIcon(opts.icon)
|
|
||||||
if icon.handle != 0 {
|
if icon.handle != 0 {
|
||||||
defer icon.delete()
|
|
||||||
ctl, _ := win.GetDlgItem(wnd, win.IDC_STATIC_OK)
|
ctl, _ := win.GetDlgItem(wnd, win.IDC_STATIC_OK)
|
||||||
win.SendMessage(ctl, win.STM_SETICON, uintptr(icon.handle), 0)
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ func notify(text string, opts options) error {
|
||||||
icon := getIcon(opts.icon)
|
icon := getIcon(opts.icon)
|
||||||
if icon.handle != 0 {
|
if icon.handle != 0 {
|
||||||
defer icon.delete()
|
defer icon.delete()
|
||||||
args.Icon = win.Handle(icon.handle)
|
args.Icon = icon.handle
|
||||||
args.Flags |= win.NIF_ICON
|
args.Flags |= win.NIF_ICON
|
||||||
args.InfoFlags |= win.NIIF_USER
|
args.InfoFlags |= win.NIIF_USER
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
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
|
return func() {}, nil
|
||||||
}
|
}
|
||||||
if ctx != nil && ctx.Err() != nil {
|
if ctx != nil && ctx.Err() != nil {
|
||||||
|
@ -94,7 +94,7 @@ type dialogHook struct {
|
||||||
wnd uintptr
|
wnd uintptr
|
||||||
hook win.Handle
|
hook win.Handle
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
icon any
|
icon icon
|
||||||
title *string
|
title *string
|
||||||
init func(wnd win.HWND)
|
init func(wnd win.HWND)
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ func newDialogHook(ctx context.Context, icon any, title *string, init func(wnd w
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
tid: tid,
|
tid: tid,
|
||||||
hook: hk,
|
hook: hk,
|
||||||
icon: icon,
|
icon: getIcon(icon),
|
||||||
title: title,
|
title: title,
|
||||||
init: init,
|
init: init,
|
||||||
}
|
}
|
||||||
|
@ -132,12 +132,8 @@ func dialogHookProc(code int32, wparam uintptr, lparam *win.CWPRETSTRUCT) uintpt
|
||||||
if hook.ctx != nil && hook.ctx.Err() != nil {
|
if hook.ctx != nil && hook.ctx.Err() != nil {
|
||||||
win.SendMessage(lparam.Wnd, win.WM_SYSCOMMAND, win.SC_CLOSE, 0)
|
win.SendMessage(lparam.Wnd, win.WM_SYSCOMMAND, win.SC_CLOSE, 0)
|
||||||
} else {
|
} else {
|
||||||
if hook.icon != nil {
|
if hook.icon.handle != 0 {
|
||||||
icon := getIcon(hook.icon)
|
win.SendMessage(lparam.Wnd, win.WM_SETICON, 0, uintptr(hook.icon.handle))
|
||||||
if icon.handle != 0 {
|
|
||||||
defer icon.delete()
|
|
||||||
win.SendMessage(lparam.Wnd, win.WM_SETICON, 0, uintptr(icon.handle))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if hook.title != nil {
|
if hook.title != nil {
|
||||||
win.SetWindowText(lparam.Wnd, strptr(*hook.title))
|
win.SetWindowText(lparam.Wnd, strptr(*hook.title))
|
||||||
|
@ -155,6 +151,7 @@ func (h *dialogHook) unhook() {
|
||||||
if h.done != nil {
|
if h.done != nil {
|
||||||
close(h.done)
|
close(h.done)
|
||||||
}
|
}
|
||||||
|
h.icon.delete()
|
||||||
win.UnhookWindowsHookEx(h.hook)
|
win.UnhookWindowsHookEx(h.hook)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,17 +286,19 @@ func getIcon(i any) icon {
|
||||||
res.handle, _ = win.LoadImage(0,
|
res.handle, _ = win.LoadImage(0,
|
||||||
strptr(path),
|
strptr(path),
|
||||||
win.IMAGE_ICON, 0, 0,
|
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")):
|
case bytes.HasPrefix(data, []byte("\x89PNG\r\n\x1a\n")):
|
||||||
res.handle, err = win.CreateIconFromResource(
|
res.handle, _ = win.CreateIconFromResourceEx(
|
||||||
data, true, 0x00030000)
|
data, true, 0x00030000, 0, 0,
|
||||||
|
win.LR_DEFAULTSIZE)
|
||||||
res.destroy = true
|
res.destroy = true
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *icon) delete() {
|
func (i *icon) delete() {
|
||||||
if i.handle != 0 {
|
if i.destroy && i.handle != 0 {
|
||||||
win.DestroyIcon(i.handle)
|
win.DestroyIcon(i.handle)
|
||||||
i.handle = 0
|
i.handle = 0
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue