Refactor (windows).
This commit is contained in:
parent
762d54a00d
commit
a52a097be2
8 changed files with 77 additions and 92 deletions
|
@ -42,14 +42,11 @@ func selectColor(opts options) (color.Color, error) {
|
|||
}
|
||||
|
||||
defer setup()()
|
||||
|
||||
if opts.ctx != nil || opts.title != nil {
|
||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, opts.title, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer unhook()
|
||||
}
|
||||
|
||||
ok := win.ChooseColor(&args)
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
|
|
|
@ -163,7 +163,7 @@ func entryProc(wnd win.HWND, msg uint32, wparam uintptr, lparam *unsafe.Pointer)
|
|||
default:
|
||||
return 1
|
||||
case win.IDOK, win.IDYES:
|
||||
dlg.out = getWindowString(dlg.editCtl)
|
||||
dlg.out = win.GetWindowText(dlg.editCtl)
|
||||
case win.IDCANCEL:
|
||||
dlg.err = ErrCanceled
|
||||
case win.IDNO:
|
||||
|
|
|
@ -37,14 +37,11 @@ func selectFile(opts options) (string, error) {
|
|||
args.InitialDir, args.DefExt = initDirNameExt(opts.filename, res[:])
|
||||
|
||||
defer setup()()
|
||||
|
||||
if opts.ctx != nil {
|
||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer unhook()
|
||||
}
|
||||
|
||||
ok := win.GetOpenFileName(&args)
|
||||
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[:])
|
||||
|
||||
defer setup()()
|
||||
|
||||
if opts.ctx != nil {
|
||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer unhook()
|
||||
}
|
||||
|
||||
ok := win.GetOpenFileName(&args)
|
||||
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[:])
|
||||
|
||||
defer setup()()
|
||||
|
||||
if opts.ctx != nil {
|
||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer unhook()
|
||||
}
|
||||
|
||||
ok := win.GetSaveFileName(&args)
|
||||
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)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
|
@ -302,7 +293,7 @@ func browseForFolder(opts options) (string, []string, error) {
|
|||
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)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
|
|
|
@ -268,6 +268,13 @@ func GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) {
|
|||
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) {
|
||||
r0, _, _ := syscall.Syscall6(procSendMessageW.Addr(), 4, uintptr(wnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
|
||||
ret = uintptr(r0)
|
||||
|
@ -389,16 +396,15 @@ type CWPRETSTRUCT struct {
|
|||
//sys DestroyWindow(wnd HWND) (err error) = user32.DestroyWindow
|
||||
//sys DispatchMessage(msg *MSG) (ret uintptr) = user32.DispatchMessageW
|
||||
//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 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 GetMessage(msg *MSG, wnd HWND, msgFilterMin uint32, msgFilterMax uint32) (ret uintptr) = user32.GetMessageW
|
||||
//sys GetSystemMetrics(index int) (ret int) = user32.GetSystemMetrics
|
||||
//sys GetWindowDC(wnd HWND) (ret Handle) = user32.GetWindowDC
|
||||
//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 GetWindowTextLength(wnd HWND) (ret int, err error) = user32.GetWindowTextLengthW
|
||||
//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 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
|
||||
|
@ -406,6 +412,7 @@ type CWPRETSTRUCT struct {
|
|||
//sys RegisterClassEx(cls *WNDCLASSEX) (err error) = user32.RegisterClassExW
|
||||
//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 SetDlgItemText(dlg HWND, dlgItemID int, str *uint16) (err error) = user32.SetDlgItemTextW
|
||||
//sys SetFocus(wnd HWND) (ret HWND, err error) = user32.SetFocus
|
||||
//sys SetForegroundWindow(wnd HWND) (ok bool) = user32.SetForegroundWindow
|
||||
//sys setThreadDpiAwarenessContext(dpiContext uintptr) (ret uintptr) = user32.SetThreadDpiAwarenessContext
|
||||
|
|
|
@ -75,7 +75,7 @@ var (
|
|||
procDispatchMessageW = moduser32.NewProc("DispatchMessageW")
|
||||
procEnableWindow = moduser32.NewProc("EnableWindow")
|
||||
procEnumChildWindows = moduser32.NewProc("EnumChildWindows")
|
||||
procGetDlgCtrlID = moduser32.NewProc("GetDlgCtrlID")
|
||||
procGetDlgItem = moduser32.NewProc("GetDlgItem")
|
||||
procGetDpiForWindow = moduser32.NewProc("GetDpiForWindow")
|
||||
procGetMessageW = moduser32.NewProc("GetMessageW")
|
||||
procGetSystemMetrics = moduser32.NewProc("GetSystemMetrics")
|
||||
|
@ -90,6 +90,7 @@ var (
|
|||
procRegisterClassExW = moduser32.NewProc("RegisterClassExW")
|
||||
procReleaseDC = moduser32.NewProc("ReleaseDC")
|
||||
procSendMessageW = moduser32.NewProc("SendMessageW")
|
||||
procSetDlgItemTextW = moduser32.NewProc("SetDlgItemTextW")
|
||||
procSetFocus = moduser32.NewProc("SetFocus")
|
||||
procSetForegroundWindow = moduser32.NewProc("SetForegroundWindow")
|
||||
procSetThreadDpiAwarenessContext = moduser32.NewProc("SetThreadDpiAwarenessContext")
|
||||
|
@ -305,11 +306,6 @@ func EnableWindow(wnd HWND, enable bool) (ok bool) {
|
|||
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) {
|
||||
r1, _, e1 := syscall.Syscall(procEnumChildWindows.Addr(), 2, uintptr(enumFunc), uintptr(lparam), 0)
|
||||
if r1 == 0 {
|
||||
|
@ -318,9 +314,12 @@ func EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func GetDlgCtrlID(wnd HWND) (ret int) {
|
||||
r0, _, _ := syscall.Syscall(procGetDlgCtrlID.Addr(), 1, uintptr(wnd), 0, 0)
|
||||
ret = int(r0)
|
||||
func GetDlgItem(dlg HWND, dlgItemID int) (ret HWND, err error) {
|
||||
r0, _, e1 := syscall.Syscall(procGetDlgItem.Addr(), 2, uintptr(dlg), uintptr(dlgItemID), 0)
|
||||
ret = HWND(r0)
|
||||
if ret == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -356,7 +355,7 @@ func GetWindowRect(wnd HWND, cmdShow *RECT) (err error) {
|
|||
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)
|
||||
ret = int(r0)
|
||||
if ret == 0 {
|
||||
|
@ -365,7 +364,7 @@ func GetWindowTextLength(wnd HWND) (ret int, err error) {
|
|||
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))
|
||||
ret = int(r0)
|
||||
if ret == 0 {
|
||||
|
@ -423,6 +422,14 @@ func SendMessage(wnd HWND, msg uint32, wparam uintptr, lparam uintptr) (ret uint
|
|||
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) {
|
||||
r0, _, e1 := syscall.Syscall(procSetFocus.Addr(), 1, uintptr(wnd), 0, 0)
|
||||
ret = HWND(r0)
|
||||
|
|
|
@ -2,8 +2,6 @@ package zenity
|
|||
|
||||
import (
|
||||
"context"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
)
|
||||
|
@ -55,14 +53,11 @@ func message(kind messageKind, text string, opts options) error {
|
|||
}
|
||||
|
||||
defer setup()()
|
||||
|
||||
if opts.ctx != nil || opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil {
|
||||
unhook, err := hookMessageDialog(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer unhook()
|
||||
}
|
||||
|
||||
var title *uint16
|
||||
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) {
|
||||
// TODO: use GetDlgItem, SetDlgItemText instead of EnumChildWindows.
|
||||
return hookDialog(opts.ctx, opts.windowIcon, nil, func(wnd win.HWND) {
|
||||
win.EnumChildWindows(wnd, syscall.NewCallback(hookMessageDialogCallback),
|
||||
unsafe.Pointer(&opts))
|
||||
})
|
||||
}
|
||||
|
||||
func hookMessageDialogCallback(wnd win.HWND, lparam *options) uintptr {
|
||||
ctl := win.GetDlgCtrlID(wnd)
|
||||
|
||||
var text *string
|
||||
switch ctl {
|
||||
case win.IDOK, win.IDYES:
|
||||
text = lparam.okLabel
|
||||
case win.IDCANCEL:
|
||||
text = lparam.cancelLabel
|
||||
case win.IDNO:
|
||||
text = lparam.extraButton
|
||||
var init func(wnd win.HWND)
|
||||
if opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil {
|
||||
init = func(wnd win.HWND) {
|
||||
if opts.okLabel != nil {
|
||||
win.SetDlgItemText(wnd, win.IDOK, strptr(*opts.okLabel))
|
||||
win.SetDlgItemText(wnd, win.IDYES, strptr(*opts.okLabel))
|
||||
}
|
||||
if text != nil {
|
||||
win.SetWindowText(wnd, strptr(*text))
|
||||
if opts.cancelLabel != nil {
|
||||
win.SetDlgItemText(wnd, win.IDCANCEL, strptr(*opts.cancelLabel))
|
||||
}
|
||||
if opts.extraButton != nil {
|
||||
win.SetDlgItemText(wnd, win.IDNO, strptr(*opts.extraButton))
|
||||
}
|
||||
|
||||
if ctl == win.IDC_STATIC_OK {
|
||||
icon := getIcon(lparam.icon)
|
||||
icon := getIcon(opts.icon)
|
||||
if icon.handle != 0 {
|
||||
defer icon.delete()
|
||||
win.SendMessage(wnd, win.STM_SETICON, uintptr(icon.handle), 0)
|
||||
ctl, _ := win.GetDlgItem(wnd, win.IDC_STATIC_OK)
|
||||
win.SendMessage(ctl, win.STM_SETICON, uintptr(icon.handle), 0)
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
return hookDialog(opts.ctx, opts.windowIcon, nil, init)
|
||||
}
|
||||
|
|
|
@ -183,8 +183,8 @@ func passwordProc(wnd win.HWND, msg uint32, wparam uintptr, lparam *unsafe.Point
|
|||
default:
|
||||
return 1
|
||||
case win.IDOK, win.IDYES:
|
||||
dlg.usr = getWindowString(dlg.uEditCtl)
|
||||
dlg.pwd = getWindowString(dlg.pEditCtl)
|
||||
dlg.usr = win.GetWindowText(dlg.uEditCtl)
|
||||
dlg.pwd = win.GetWindowText(dlg.pEditCtl)
|
||||
case win.IDCANCEL:
|
||||
dlg.err = ErrCanceled
|
||||
case win.IDNO:
|
||||
|
|
|
@ -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) {
|
||||
if ctx == nil && icon == nil && init == nil {
|
||||
return func() {}, nil
|
||||
}
|
||||
if ctx != nil && ctx.Err() != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
name := "WC_" + strconv.FormatUint(uint64(proc), 16)
|
||||
|
||||
|
|
Loading…
Reference in a new issue