Window icons (windows).

This commit is contained in:
Nuno Cruces 2022-05-24 00:12:38 +01:00
parent b988db5bd2
commit 205db7d4be
7 changed files with 48 additions and 23 deletions

View file

@ -38,6 +38,8 @@ func (dlg *calendarDialog) setup(text string, opts options) (time.Time, error) {
defer setup()()
dlg.font = getFont()
defer dlg.font.delete()
icon := getIcon(opts.windowIcon)
defer icon.delete()
if opts.ctx != nil && opts.ctx.Err() != nil {
return time.Time{}, opts.ctx.Err()
@ -48,7 +50,7 @@ func (dlg *calendarDialog) setup(text string, opts options) (time.Time, error) {
return time.Time{}, err
}
cls, err := registerClass(instance, syscall.NewCallback(calendarProc))
cls, err := registerClass(instance, icon.handle, syscall.NewCallback(calendarProc))
if cls == 0 {
return time.Time{}, err
}

View file

@ -37,6 +37,8 @@ func (dlg *entryDialog) setup(text string, opts options) (string, error) {
defer setup()()
dlg.font = getFont()
defer dlg.font.delete()
icon := getIcon(opts.windowIcon)
defer icon.delete()
if opts.ctx != nil && opts.ctx.Err() != nil {
return "", opts.ctx.Err()
@ -47,7 +49,7 @@ func (dlg *entryDialog) setup(text string, opts options) (string, error) {
return "", err
}
cls, err := registerClass(instance, syscall.NewCallback(entryProc))
cls, err := registerClass(instance, icon.handle, syscall.NewCallback(entryProc))
if cls == 0 {
return "", err
}

View file

@ -54,6 +54,8 @@ func (dlg *listDialog) setup(text string, opts options) ([]string, error) {
defer setup()()
dlg.font = getFont()
defer dlg.font.delete()
icon := getIcon(opts.windowIcon)
defer icon.delete()
if opts.ctx != nil && opts.ctx.Err() != nil {
return nil, opts.ctx.Err()
@ -64,7 +66,7 @@ func (dlg *listDialog) setup(text string, opts options) ([]string, error) {
return nil, err
}
cls, err := registerClass(instance, syscall.NewCallback(listProc))
cls, err := registerClass(instance, icon.handle, syscall.NewCallback(listProc))
if cls == 0 {
return nil, err
}

View file

@ -42,6 +42,16 @@ func notify(text string, opts options) error {
args.InfoFlags |= 0x2 // NIIF_WARNING
case ErrorIcon:
args.InfoFlags |= 0x3 // NIIF_ERROR
case NoIcon:
//
default:
icon := getIcon(opts.icon)
if icon.handle != 0 {
defer icon.delete()
args.Icon = icon.handle
args.Flags |= 0x00000002 // NIF_ICON
args.InfoFlags |= 0x4 // NIIF_USER
}
}
runtime.LockOSThread()

View file

@ -111,16 +111,14 @@ func (d *progressDialog) Close() error {
}
func (dlg *progressDialog) setup(opts options) error {
done := false
defer func() {
if !done {
dlg.init.Done()
}
}()
var once sync.Once
defer once.Do(dlg.init.Done)
defer setup()()
dlg.font = getFont()
defer dlg.font.delete()
icon := getIcon(opts.windowIcon)
defer icon.delete()
if opts.ctx != nil && opts.ctx.Err() != nil {
return opts.ctx.Err()
@ -131,7 +129,7 @@ func (dlg *progressDialog) setup(opts options) error {
return err
}
cls, err := registerClass(instance, syscall.NewCallback(progressProc))
cls, err := registerClass(instance, icon.handle, syscall.NewCallback(progressProc))
if cls == 0 {
return err
}
@ -182,8 +180,7 @@ func (dlg *progressDialog) setup(opts options) error {
} else {
sendMessage.Call(dlg.progCtl, _PBM_SETRANGE32, 0, uintptr(opts.maxValue))
}
dlg.init.Done()
done = true
once.Do(dlg.init.Done)
if opts.ctx != nil {
wait := make(chan struct{})

View file

@ -47,6 +47,8 @@ func (dlg *passwordDialog) setup(opts options) (string, string, error) {
defer setup()()
dlg.font = getFont()
defer dlg.font.delete()
icon := getIcon(opts.windowIcon)
defer icon.delete()
if opts.ctx != nil && opts.ctx.Err() != nil {
return "", "", opts.ctx.Err()
@ -57,7 +59,7 @@ func (dlg *passwordDialog) setup(opts options) (string, string, error) {
return "", "", err
}
cls, err := registerClass(instance, syscall.NewCallback(passwordProc))
cls, err := registerClass(instance, icon.handle, syscall.NewCallback(passwordProc))
if cls == 0 {
return "", "", err
}

View file

@ -180,7 +180,7 @@ type dialogHook struct {
func newDialogHook(ctx context.Context, icon any, title *string, init func(wnd uintptr)) (*dialogHook, error) {
tid, _, _ := getCurrentThreadId.Call()
hk, _, err := setWindowsHookEx.Call(5, // WH_CBT
hk, _, err := setWindowsHookEx.Call(12, // WH_CALLWNDPROCRET
syscall.NewCallback(dialogHookProc), 0, tid)
if hk == 0 {
return nil, err
@ -203,31 +203,31 @@ func newDialogHook(ctx context.Context, icon any, title *string, init func(wnd u
return &hook, nil
}
func dialogHookProc(code int32, wparam, lparam uintptr) uintptr {
if code == 5 { // HCBT_ACTIVATE
func dialogHookProc(code int32, wparam uintptr, lparam *_CWPRETSTRUCT) uintptr {
if lparam.Message == 0x0110 { // WM_INITDIALOG
tid, _, _ := getCurrentThreadId.Call()
hook := (*dialogHook)(loadBackRef(tid))
atomic.StoreUintptr(&hook.wnd, wparam)
atomic.StoreUintptr(&hook.wnd, lparam.Wnd)
if hook.ctx != nil && hook.ctx.Err() != nil {
sendMessage.Call(wparam, _WM_SYSCOMMAND, _SC_CLOSE, 0)
sendMessage.Call(lparam.Wnd, _WM_SYSCOMMAND, _SC_CLOSE, 0)
} else {
if hook.icon != nil {
icon := getIcon(hook.icon)
if icon.handle != 0 {
defer icon.delete()
sendMessage.Call(wparam, _WM_SETICON, 0, icon.handle)
sendMessage.Call(lparam.Wnd, _WM_SETICON, 0, icon.handle)
}
}
if hook.title != nil {
setWindowText.Call(wparam, strptr(*hook.title))
setWindowText.Call(lparam.Wnd, strptr(*hook.title))
}
if hook.init != nil {
hook.init(wparam)
hook.init(lparam.Wnd)
}
}
}
next, _, _ := callNextHookEx.Call(
0, uintptr(code), wparam, lparam)
0, uintptr(code), wparam, uintptr(unsafe.Pointer(lparam)))
return next
}
@ -408,12 +408,13 @@ func getWindowString(wnd uintptr) string {
return syscall.UTF16ToString(buf)
}
func registerClass(instance, proc uintptr) (uintptr, error) {
func registerClass(instance, icon, proc uintptr) (uintptr, error) {
name := "WC_" + strconv.FormatUint(uint64(proc), 16)
var wcx _WNDCLASSEX
wcx.Size = uint32(unsafe.Sizeof(wcx))
wcx.WndProc = proc
wcx.Icon = icon
wcx.Instance = instance
wcx.Background = 5 // COLOR_WINDOW
wcx.ClassName = syscall.StringToUTF16Ptr(name)
@ -487,6 +488,15 @@ type _INITCOMMONCONTROLSEX struct {
ICC uint32
}
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-cwpretstruct
type _CWPRETSTRUCT struct {
Result uintptr
LParam uintptr
WParam uintptr
Message uint32
Wnd uintptr
}
// https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-logfontw
type _LOGFONT struct {
Height int32