Refactor (windows).

This commit is contained in:
Nuno Cruces 2022-06-23 14:49:08 +01:00
parent 762d54a00d
commit a52a097be2
8 changed files with 77 additions and 92 deletions

View file

@ -42,14 +42,11 @@ func selectColor(opts options) (color.Color, error) {
} }
defer setup()() defer setup()()
unhook, err := hookDialog(opts.ctx, opts.windowIcon, opts.title, nil)
if opts.ctx != nil || opts.title != nil { if err != nil {
unhook, err := hookDialog(opts.ctx, opts.windowIcon, opts.title, nil) return nil, err
if err != nil {
return nil, err
}
defer unhook()
} }
defer unhook()
ok := win.ChooseColor(&args) ok := win.ChooseColor(&args)
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {

View file

@ -163,7 +163,7 @@ func entryProc(wnd win.HWND, msg uint32, wparam uintptr, lparam *unsafe.Pointer)
default: default:
return 1 return 1
case win.IDOK, win.IDYES: case win.IDOK, win.IDYES:
dlg.out = getWindowString(dlg.editCtl) dlg.out = win.GetWindowText(dlg.editCtl)
case win.IDCANCEL: case win.IDCANCEL:
dlg.err = ErrCanceled dlg.err = ErrCanceled
case win.IDNO: case win.IDNO:

View file

@ -37,14 +37,11 @@ func selectFile(opts options) (string, error) {
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:]) args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
defer setup()() defer setup()()
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
if opts.ctx != nil { if err != nil {
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil) return "", err
if err != nil {
return "", err
}
defer unhook()
} }
defer unhook()
ok := win.GetOpenFileName(&args) ok := win.GetOpenFileName(&args)
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {
@ -83,14 +80,11 @@ func selectFileMultiple(opts options) ([]string, error) {
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:]) args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
defer setup()() defer setup()()
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
if opts.ctx != nil { if err != nil {
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil) return nil, err
if err != nil {
return nil, err
}
defer unhook()
} }
defer unhook()
ok := win.GetOpenFileName(&args) ok := win.GetOpenFileName(&args)
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {
@ -160,14 +154,11 @@ func selectFileSave(opts options) (string, error) {
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:]) args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
defer setup()() defer setup()()
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
if opts.ctx != nil { if err != nil {
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil) return "", err
if err != nil {
return "", err
}
defer unhook()
} }
defer unhook()
ok := win.GetSaveFileName(&args) ok := win.GetSaveFileName(&args)
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {
@ -231,7 +222,7 @@ func pickFolders(opts options, multi bool) (string, []string, error) {
} }
} }
if opts.ctx != nil { 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
@ -302,7 +293,7 @@ func browseForFolder(opts options) (string, []string, error) {
args.CallbackFunc = syscall.NewCallback(browseForFolderCallback) args.CallbackFunc = syscall.NewCallback(browseForFolderCallback)
} }
if opts.ctx != nil { 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

View file

@ -268,6 +268,13 @@ func GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) {
return windows.GetWindowThreadProcessId(hwnd, pid) return windows.GetWindowThreadProcessId(hwnd, pid)
} }
func GetWindowText(wnd HWND) string {
len, _ := getWindowTextLength(wnd)
buf := make([]uint16, len+1)
getWindowText(wnd, &buf[0], len+1)
return syscall.UTF16ToString(buf)
}
func SendMessagePointer(wnd HWND, msg uint32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) { func SendMessagePointer(wnd HWND, msg uint32, wparam uintptr, lparam unsafe.Pointer) (ret uintptr) {
r0, _, _ := syscall.Syscall6(procSendMessageW.Addr(), 4, uintptr(wnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0) r0, _, _ := syscall.Syscall6(procSendMessageW.Addr(), 4, uintptr(wnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
ret = uintptr(r0) ret = uintptr(r0)
@ -389,16 +396,15 @@ type CWPRETSTRUCT struct {
//sys DestroyWindow(wnd HWND) (err error) = user32.DestroyWindow //sys DestroyWindow(wnd HWND) (err error) = user32.DestroyWindow
//sys DispatchMessage(msg *MSG) (ret uintptr) = user32.DispatchMessageW //sys DispatchMessage(msg *MSG) (ret uintptr) = user32.DispatchMessageW
//sys EnableWindow(wnd HWND, enable bool) (ok bool) = user32.EnableWindow //sys EnableWindow(wnd HWND, enable bool) (ok bool) = user32.EnableWindow
//sys EnumChildWindows(parent HWND, enumFunc uintptr, lparam unsafe.Pointer) = user32.EnumChildWindows
//sys EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) = user32.EnumChildWindows //sys EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) = user32.EnumChildWindows
//sys GetDlgCtrlID(wnd HWND) (ret int) = user32.GetDlgCtrlID //sys GetDlgItem(dlg HWND, dlgItemID int) (ret HWND, err error) = user32.GetDlgItem
//sys getDpiForWindow(wnd HWND) (ret int) = user32.GetDpiForWindow //sys getDpiForWindow(wnd HWND) (ret int) = user32.GetDpiForWindow
//sys GetMessage(msg *MSG, wnd HWND, msgFilterMin uint32, msgFilterMax uint32) (ret uintptr) = user32.GetMessageW //sys GetMessage(msg *MSG, wnd HWND, msgFilterMin uint32, msgFilterMax uint32) (ret uintptr) = user32.GetMessageW
//sys GetSystemMetrics(index int) (ret int) = user32.GetSystemMetrics //sys GetSystemMetrics(index int) (ret int) = user32.GetSystemMetrics
//sys GetWindowDC(wnd HWND) (ret Handle) = user32.GetWindowDC //sys GetWindowDC(wnd HWND) (ret Handle) = user32.GetWindowDC
//sys GetWindowRect(wnd HWND, cmdShow *RECT) (err error) = user32.GetWindowRect //sys GetWindowRect(wnd HWND, cmdShow *RECT) (err error) = user32.GetWindowRect
//sys GetWindowText(wnd HWND, str *uint16, maxCount int) (ret int, err error) = user32.GetWindowTextW //sys getWindowText(wnd HWND, str *uint16, maxCount int) (ret int, err error) = user32.GetWindowTextW
//sys GetWindowTextLength(wnd HWND) (ret int, err error) = user32.GetWindowTextLengthW //sys getWindowTextLength(wnd HWND) (ret int, err error) = user32.GetWindowTextLengthW
//sys IsDialogMessage(wnd HWND, msg *MSG) (ok bool) = user32.IsDialogMessageW //sys IsDialogMessage(wnd HWND, msg *MSG) (ok bool) = user32.IsDialogMessageW
//sys LoadIcon(instance Handle, resource uintptr) (ret Handle, err error) = user32.LoadIconW //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 LoadImage(instance Handle, name *uint16, typ int, cx int, cy int, load int) (ret Handle, err error) = user32.LoadImageW
@ -406,6 +412,7 @@ type CWPRETSTRUCT struct {
//sys RegisterClassEx(cls *WNDCLASSEX) (err error) = user32.RegisterClassExW //sys RegisterClassEx(cls *WNDCLASSEX) (err error) = user32.RegisterClassExW
//sys ReleaseDC(wnd HWND, dc Handle) (ok bool) = user32.ReleaseDC //sys ReleaseDC(wnd HWND, dc Handle) (ok bool) = user32.ReleaseDC
//sys SendMessage(wnd HWND, msg uint32, wparam uintptr, lparam uintptr) (ret uintptr) = user32.SendMessageW //sys SendMessage(wnd HWND, msg uint32, wparam uintptr, lparam uintptr) (ret uintptr) = user32.SendMessageW
//sys SetDlgItemText(dlg HWND, dlgItemID int, str *uint16) (err error) = user32.SetDlgItemTextW
//sys SetFocus(wnd HWND) (ret HWND, err error) = user32.SetFocus //sys SetFocus(wnd HWND) (ret HWND, err error) = user32.SetFocus
//sys SetForegroundWindow(wnd HWND) (ok bool) = user32.SetForegroundWindow //sys SetForegroundWindow(wnd HWND) (ok bool) = user32.SetForegroundWindow
//sys setThreadDpiAwarenessContext(dpiContext uintptr) (ret uintptr) = user32.SetThreadDpiAwarenessContext //sys setThreadDpiAwarenessContext(dpiContext uintptr) (ret uintptr) = user32.SetThreadDpiAwarenessContext

View file

@ -75,7 +75,7 @@ var (
procDispatchMessageW = moduser32.NewProc("DispatchMessageW") procDispatchMessageW = moduser32.NewProc("DispatchMessageW")
procEnableWindow = moduser32.NewProc("EnableWindow") procEnableWindow = moduser32.NewProc("EnableWindow")
procEnumChildWindows = moduser32.NewProc("EnumChildWindows") procEnumChildWindows = moduser32.NewProc("EnumChildWindows")
procGetDlgCtrlID = moduser32.NewProc("GetDlgCtrlID") procGetDlgItem = moduser32.NewProc("GetDlgItem")
procGetDpiForWindow = moduser32.NewProc("GetDpiForWindow") procGetDpiForWindow = moduser32.NewProc("GetDpiForWindow")
procGetMessageW = moduser32.NewProc("GetMessageW") procGetMessageW = moduser32.NewProc("GetMessageW")
procGetSystemMetrics = moduser32.NewProc("GetSystemMetrics") procGetSystemMetrics = moduser32.NewProc("GetSystemMetrics")
@ -90,6 +90,7 @@ var (
procRegisterClassExW = moduser32.NewProc("RegisterClassExW") procRegisterClassExW = moduser32.NewProc("RegisterClassExW")
procReleaseDC = moduser32.NewProc("ReleaseDC") procReleaseDC = moduser32.NewProc("ReleaseDC")
procSendMessageW = moduser32.NewProc("SendMessageW") procSendMessageW = moduser32.NewProc("SendMessageW")
procSetDlgItemTextW = moduser32.NewProc("SetDlgItemTextW")
procSetFocus = moduser32.NewProc("SetFocus") procSetFocus = moduser32.NewProc("SetFocus")
procSetForegroundWindow = moduser32.NewProc("SetForegroundWindow") procSetForegroundWindow = moduser32.NewProc("SetForegroundWindow")
procSetThreadDpiAwarenessContext = moduser32.NewProc("SetThreadDpiAwarenessContext") procSetThreadDpiAwarenessContext = moduser32.NewProc("SetThreadDpiAwarenessContext")
@ -305,11 +306,6 @@ func EnableWindow(wnd HWND, enable bool) (ok bool) {
return return
} }
func EnumChildWindows(parent HWND, enumFunc uintptr, lparam unsafe.Pointer) {
syscall.Syscall(procEnumChildWindows.Addr(), 3, uintptr(parent), uintptr(enumFunc), uintptr(lparam))
return
}
func EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) { func EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) {
r1, _, e1 := syscall.Syscall(procEnumChildWindows.Addr(), 2, uintptr(enumFunc), uintptr(lparam), 0) r1, _, e1 := syscall.Syscall(procEnumChildWindows.Addr(), 2, uintptr(enumFunc), uintptr(lparam), 0)
if r1 == 0 { if r1 == 0 {
@ -318,9 +314,12 @@ func EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) {
return return
} }
func GetDlgCtrlID(wnd HWND) (ret int) { func GetDlgItem(dlg HWND, dlgItemID int) (ret HWND, err error) {
r0, _, _ := syscall.Syscall(procGetDlgCtrlID.Addr(), 1, uintptr(wnd), 0, 0) r0, _, e1 := syscall.Syscall(procGetDlgItem.Addr(), 2, uintptr(dlg), uintptr(dlgItemID), 0)
ret = int(r0) ret = HWND(r0)
if ret == 0 {
err = errnoErr(e1)
}
return return
} }
@ -356,7 +355,7 @@ func GetWindowRect(wnd HWND, cmdShow *RECT) (err error) {
return return
} }
func GetWindowTextLength(wnd HWND) (ret int, err error) { func getWindowTextLength(wnd HWND) (ret int, err error) {
r0, _, e1 := syscall.Syscall(procGetWindowTextLengthW.Addr(), 1, uintptr(wnd), 0, 0) r0, _, e1 := syscall.Syscall(procGetWindowTextLengthW.Addr(), 1, uintptr(wnd), 0, 0)
ret = int(r0) ret = int(r0)
if ret == 0 { if ret == 0 {
@ -365,7 +364,7 @@ func GetWindowTextLength(wnd HWND) (ret int, err error) {
return return
} }
func GetWindowText(wnd HWND, str *uint16, maxCount int) (ret int, err error) { func getWindowText(wnd HWND, str *uint16, maxCount int) (ret int, err error) {
r0, _, e1 := syscall.Syscall(procGetWindowTextW.Addr(), 3, uintptr(wnd), uintptr(unsafe.Pointer(str)), uintptr(maxCount)) r0, _, e1 := syscall.Syscall(procGetWindowTextW.Addr(), 3, uintptr(wnd), uintptr(unsafe.Pointer(str)), uintptr(maxCount))
ret = int(r0) ret = int(r0)
if ret == 0 { if ret == 0 {
@ -423,6 +422,14 @@ func SendMessage(wnd HWND, msg uint32, wparam uintptr, lparam uintptr) (ret uint
return return
} }
func SetDlgItemText(dlg HWND, dlgItemID int, str *uint16) (err error) {
r1, _, e1 := syscall.Syscall(procSetDlgItemTextW.Addr(), 3, uintptr(dlg), uintptr(dlgItemID), uintptr(unsafe.Pointer(str)))
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func SetFocus(wnd HWND) (ret HWND, err error) { func SetFocus(wnd HWND) (ret HWND, err error) {
r0, _, e1 := syscall.Syscall(procSetFocus.Addr(), 1, uintptr(wnd), 0, 0) r0, _, e1 := syscall.Syscall(procSetFocus.Addr(), 1, uintptr(wnd), 0, 0)
ret = HWND(r0) ret = HWND(r0)

View file

@ -2,8 +2,6 @@ package zenity
import ( import (
"context" "context"
"syscall"
"unsafe"
"github.com/ncruces/zenity/internal/win" "github.com/ncruces/zenity/internal/win"
) )
@ -55,14 +53,11 @@ func message(kind messageKind, text string, opts options) error {
} }
defer setup()() defer setup()()
unhook, err := hookMessageDialog(opts)
if opts.ctx != nil || opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil { if err != nil {
unhook, err := hookMessageDialog(opts) return err
if err != nil {
return err
}
defer unhook()
} }
defer unhook()
var title *uint16 var title *uint16
if opts.title != nil { if opts.title != nil {
@ -88,35 +83,27 @@ func message(kind messageKind, text string, opts options) error {
} }
func hookMessageDialog(opts options) (unhook context.CancelFunc, err error) { func hookMessageDialog(opts options) (unhook context.CancelFunc, err error) {
// TODO: use GetDlgItem, SetDlgItemText instead of EnumChildWindows. var init func(wnd win.HWND)
return hookDialog(opts.ctx, opts.windowIcon, nil, func(wnd win.HWND) { if opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil {
win.EnumChildWindows(wnd, syscall.NewCallback(hookMessageDialogCallback), init = func(wnd win.HWND) {
unsafe.Pointer(&opts)) if opts.okLabel != nil {
}) win.SetDlgItemText(wnd, win.IDOK, strptr(*opts.okLabel))
} win.SetDlgItemText(wnd, win.IDYES, strptr(*opts.okLabel))
}
if opts.cancelLabel != nil {
win.SetDlgItemText(wnd, win.IDCANCEL, strptr(*opts.cancelLabel))
}
if opts.extraButton != nil {
win.SetDlgItemText(wnd, win.IDNO, strptr(*opts.extraButton))
}
func hookMessageDialogCallback(wnd win.HWND, lparam *options) uintptr { icon := getIcon(opts.icon)
ctl := win.GetDlgCtrlID(wnd) if icon.handle != 0 {
defer icon.delete()
var text *string ctl, _ := win.GetDlgItem(wnd, win.IDC_STATIC_OK)
switch ctl { win.SendMessage(ctl, win.STM_SETICON, uintptr(icon.handle), 0)
case win.IDOK, win.IDYES: }
text = lparam.okLabel
case win.IDCANCEL:
text = lparam.cancelLabel
case win.IDNO:
text = lparam.extraButton
}
if text != nil {
win.SetWindowText(wnd, strptr(*text))
}
if ctl == win.IDC_STATIC_OK {
icon := getIcon(lparam.icon)
if icon.handle != 0 {
defer icon.delete()
win.SendMessage(wnd, win.STM_SETICON, uintptr(icon.handle), 0)
} }
} }
return 1 return hookDialog(opts.ctx, opts.windowIcon, nil, init)
} }

View file

@ -183,8 +183,8 @@ func passwordProc(wnd win.HWND, msg uint32, wparam uintptr, lparam *unsafe.Point
default: default:
return 1 return 1
case win.IDOK, win.IDYES: case win.IDOK, win.IDYES:
dlg.usr = getWindowString(dlg.uEditCtl) dlg.usr = win.GetWindowText(dlg.uEditCtl)
dlg.pwd = getWindowString(dlg.pEditCtl) dlg.pwd = win.GetWindowText(dlg.pEditCtl)
case win.IDCANCEL: case win.IDCANCEL:
dlg.err = ErrCanceled dlg.err = ErrCanceled
case win.IDNO: case win.IDNO:

View file

@ -79,6 +79,9 @@ 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 {
return func() {}, nil
}
if ctx != nil && ctx.Err() != nil { if ctx != nil && ctx.Err() != nil {
return nil, ctx.Err() return nil, ctx.Err()
} }
@ -314,13 +317,6 @@ func centerWindow(wnd win.HWND) {
win.SetWindowPos(wnd, 0, x/2, y/2, 0, 0, win.SWP_NOZORDER|win.SWP_NOSIZE) win.SetWindowPos(wnd, 0, x/2, y/2, 0, 0, win.SWP_NOZORDER|win.SWP_NOSIZE)
} }
func getWindowString(wnd win.HWND) string {
len, _ := win.GetWindowTextLength(wnd)
buf := make([]uint16, len+1)
win.GetWindowText(wnd, &buf[0], len+1)
return syscall.UTF16ToString(buf)
}
func registerClass(instance, icon win.Handle, proc uintptr) (*uint16, error) { func registerClass(instance, icon win.Handle, proc uintptr) (*uint16, error) {
name := "WC_" + strconv.FormatUint(uint64(proc), 16) name := "WC_" + strconv.FormatUint(uint64(proc), 16)