zenity/msg_windows.go

130 lines
2.6 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"
2020-01-04 22:21:39 -05:00
"syscall"
"unsafe"
)
var (
2022-05-19 08:47:38 -04:00
getDlgCtrlID = user32.NewProc("GetDlgCtrlID")
messageBox = user32.NewProc("MessageBoxW")
2020-01-04 22:21:39 -05:00
)
2021-04-29 11:05:28 -04:00
func message(kind messageKind, text string, opts options) 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:
2022-03-28 22:05:46 -04:00
flags |= _MB_YESNOCANCEL
2021-03-03 22:32:55 -05:00
case kind == questionKind:
2022-03-28 22:05:46 -04:00
flags |= _MB_OKCANCEL
2021-03-03 22:32:55 -05:00
case opts.extraButton != nil:
2022-03-28 22:05:46 -04:00
flags |= _MB_YESNO
2020-01-04 22:21:39 -05:00
}
switch opts.icon {
case ErrorIcon:
2022-03-28 22:05:46 -04:00
flags |= _MB_ICONERROR
2020-01-04 22:21:39 -05:00
case QuestionIcon:
2022-03-28 22:05:46 -04:00
flags |= _MB_ICONQUESTION
2020-01-04 22:21:39 -05:00
case WarningIcon:
2022-03-28 22:05:46 -04:00
flags |= _MB_ICONWARNING
2020-01-04 22:21:39 -05:00
case InfoIcon:
2022-03-28 22:05:46 -04:00
flags |= _MB_ICONINFORMATION
2022-05-18 09:48:09 -04:00
case NoIcon:
//
default:
2022-03-25 22:56:06 -04:00
switch kind {
case errorKind:
2022-03-28 22:05:46 -04:00
flags |= _MB_ICONERROR
2022-03-25 22:56:06 -04:00
case questionKind:
2022-03-28 22:05:46 -04:00
flags |= _MB_ICONQUESTION
2022-03-25 22:56:06 -04:00
case warningKind:
2022-03-28 22:05:46 -04:00
flags |= _MB_ICONWARNING
2022-03-25 22:56:06 -04:00
case infoKind:
2022-03-28 22:05:46 -04:00
flags |= _MB_ICONINFORMATION
2022-03-25 22:56:06 -04:00
}
2020-01-04 22:21:39 -05:00
}
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 {
2022-03-28 22:05:46 -04:00
flags |= _MB_DEFBUTTON2
} else {
2022-03-28 22:05:46 -04:00
flags |= _MB_DEFBUTTON3
}
}
2021-03-26 08:40:24 -04:00
defer setup()()
2022-05-17 11:18:12 -04:00
if opts.ctx != nil || opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil {
2022-05-09 10:49:32 -04:00
unhook, err := hookMessageDialog(kind, opts)
2020-01-30 09:14:42 -05:00
if err != nil {
2021-04-29 11:05:28 -04:00
return err
}
2020-01-30 09:14:42 -05:00
defer unhook()
}
2021-09-15 08:54:35 -04:00
var title *uint16
2021-03-03 22:25:45 -05:00
if opts.title != nil {
2021-09-15 08:54:35 -04:00
title = syscall.StringToUTF16Ptr(*opts.title)
2021-03-03 22:25:45 -05:00
}
2021-09-15 08:54:35 -04:00
s, _, err := messageBox.Call(0, strptr(text), 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 {
2021-04-29 11:05:28 -04:00
return opts.ctx.Err()
2020-01-30 09:14:42 -05:00
}
2021-03-03 22:32:55 -05:00
switch s {
2022-03-28 22:05:46 -04:00
case _IDOK, _IDYES:
2021-04-29 11:05:28 -04:00
return nil
2022-03-28 22:05:46 -04:00
case _IDCANCEL:
2021-04-29 11:05:28 -04:00
return ErrCanceled
2022-03-28 22:05:46 -04:00
case _IDNO:
2021-04-29 11:05:28 -04:00
return ErrExtraButton
2021-03-03 22:32:55 -05:00
default:
2021-04-29 11:05:28 -04:00
return err
}
}
2022-05-09 10:49:32 -04:00
func hookMessageDialog(kind messageKind, opts options) (unhook context.CancelFunc, err error) {
2020-01-30 09:14:42 -05:00
return hookDialog(opts.ctx, func(wnd uintptr) {
2022-05-19 08:47:38 -04:00
if opts.windowIcon != nil {
icon := getIcon(opts.windowIcon)
if icon.handle != 0 {
defer icon.delete()
sendMessage.Call(wnd, 0x0080 /*WM_SETICON*/, 0, icon.handle)
}
}
2020-01-30 09:14:42 -05:00
enumChildWindows.Call(wnd,
2022-05-09 10:49:32 -04:00
syscall.NewCallback(hookMessageDialogCallback),
uintptr(unsafe.Pointer(&opts)))
2020-01-30 09:14:42 -05:00
})
2020-01-04 22:21:39 -05:00
}
2022-05-09 10:49:32 -04:00
func hookMessageDialogCallback(wnd uintptr, lparam *options) uintptr {
ctl, _, _ := getDlgCtrlID.Call(wnd)
var text *string
switch ctl {
case _IDOK, _IDYES:
text = lparam.okLabel
case _IDCANCEL:
text = lparam.cancelLabel
case _IDNO:
text = lparam.extraButton
}
if text != nil {
setWindowText.Call(wnd, strptr(*text))
}
2022-05-19 08:47:38 -04:00
if ctl == 20 /*IDC_STATIC_OK*/ {
icon := getIcon(lparam.icon)
if icon.handle != 0 {
defer icon.delete()
sendMessage.Call(wnd, 0x0170 /*STM_SETICON*/, icon.handle, 0)
}
}
return 1
}