zenity/msg_windows.go

111 lines
2.4 KiB
Go
Raw Normal View History

2020-01-04 22:21:39 -05:00
package zenity
import (
2020-01-30 09:14:42 -05:00
"context"
"runtime"
2020-01-04 22:21:39 -05:00
"syscall"
"unsafe"
)
var (
messageBox = user32.NewProc("MessageBoxW")
)
2021-03-04 07:42:30 -05:00
func message(kind messageKind, text string, opts options) (bool, error) {
2020-01-27 13:11:38 -05:00
var flags uintptr
2020-01-04 22:21:39 -05:00
switch {
2021-03-03 22:25:45 -05:00
case kind == questionKind && opts.extraButton != nil:
2020-01-04 22:21:39 -05:00
flags |= 0x3 // MB_YESNOCANCEL
2021-03-03 22:32:55 -05:00
case kind == questionKind:
2020-01-04 22:21:39 -05:00
flags |= 0x1 // MB_OKCANCEL
2021-03-03 22:32:55 -05:00
case opts.extraButton != nil:
flags |= 0x4 // MB_YESNO
2020-01-04 22:21:39 -05:00
}
switch opts.icon {
case ErrorIcon:
flags |= 0x10 // MB_ICONERROR
case QuestionIcon:
flags |= 0x20 // MB_ICONQUESTION
case WarningIcon:
flags |= 0x30 // MB_ICONWARNING
case InfoIcon:
flags |= 0x40 // MB_ICONINFORMATION
}
2020-01-24 07:52:45 -05:00
if kind == questionKind && opts.defaultCancel {
2021-03-03 22:25:45 -05:00
if opts.extraButton == nil {
flags |= 0x100 // MB_DEFBUTTON2
} else {
flags |= 0x200 // MB_DEFBUTTON3
}
}
2021-03-03 22:25:45 -05:00
if opts.ctx != nil || opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
2020-01-30 09:14:42 -05:00
unhook, err := hookMessageLabels(kind, opts)
if err != nil {
return false, err
}
2020-01-30 09:14:42 -05:00
defer unhook()
}
2021-03-03 22:25:45 -05:00
var title *uint16
if opts.title != nil {
title = syscall.StringToUTF16Ptr(*opts.title)
}
2021-01-05 10:20:42 -05:00
activate()
2020-01-29 09:15:21 -05:00
s, _, err := messageBox.Call(0,
2020-01-04 22:21:39 -05:00
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))),
2021-03-03 22:25:45 -05:00
uintptr(unsafe.Pointer(title)), flags)
2020-01-04 22:21:39 -05:00
2020-01-30 09:14:42 -05:00
if opts.ctx != nil && opts.ctx.Err() != nil {
return false, opts.ctx.Err()
}
2021-03-03 22:32:55 -05:00
switch s {
case 1, 6: // IDOK, IDYES
return true, nil
2021-03-03 22:32:55 -05:00
case 2: // IDCANCEL
return false, nil
case 7: // IDNO
return false, ErrExtraButton
default:
return false, err
}
}
2020-01-30 09:14:42 -05:00
func hookMessageLabels(kind messageKind, opts options) (unhook context.CancelFunc, err error) {
return hookDialog(opts.ctx, func(wnd uintptr) {
enumChildWindows.Call(wnd,
syscall.NewCallback(func(wnd, lparam uintptr) uintptr {
name := [8]uint16{}
getClassName.Call(wnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name)))
if syscall.UTF16ToString(name[:]) == "Button" {
ctl, _, _ := getDlgCtrlID.Call(wnd)
2021-03-03 22:25:45 -05:00
var text *string
2020-01-30 09:14:42 -05:00
switch ctl {
case 1, 6: // IDOK, IDYES
text = opts.okLabel
case 2: // IDCANCEL
if kind == questionKind {
text = opts.cancelLabel
} else {
text = opts.okLabel
}
case 7: // IDNO
text = opts.extraButton
}
2021-03-03 22:25:45 -05:00
if text != nil {
ptr := syscall.StringToUTF16Ptr(*text)
2020-01-30 09:14:42 -05:00
setWindowText.Call(wnd, uintptr(unsafe.Pointer(ptr)))
}
}
2020-01-30 09:14:42 -05:00
return 1
}), 0)
})
2020-01-04 22:21:39 -05:00
}