Message dialogs improvements (windows).
This commit is contained in:
parent
ec8eb571eb
commit
fd22f9bf8e
3 changed files with 106 additions and 11 deletions
|
@ -11,17 +11,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
comdlg32 = syscall.NewLazyDLL("comdlg32.dll")
|
|
||||||
ole32 = syscall.NewLazyDLL("ole32.dll")
|
|
||||||
shell32 = syscall.NewLazyDLL("shell32.dll")
|
|
||||||
|
|
||||||
getOpenFileName = comdlg32.NewProc("GetOpenFileNameW")
|
getOpenFileName = comdlg32.NewProc("GetOpenFileNameW")
|
||||||
getSaveFileName = comdlg32.NewProc("GetSaveFileNameW")
|
getSaveFileName = comdlg32.NewProc("GetSaveFileNameW")
|
||||||
commDlgExtendedError = comdlg32.NewProc("CommDlgExtendedError")
|
commDlgExtendedError = comdlg32.NewProc("CommDlgExtendedError")
|
||||||
coInitializeEx = ole32.NewProc("CoInitializeEx")
|
|
||||||
coUninitialize = ole32.NewProc("CoUninitialize")
|
|
||||||
coCreateInstance = ole32.NewProc("CoCreateInstance")
|
|
||||||
coTaskMemFree = ole32.NewProc("CoTaskMemFree")
|
|
||||||
shBrowseForFolder = shell32.NewProc("SHBrowseForFolderW")
|
shBrowseForFolder = shell32.NewProc("SHBrowseForFolderW")
|
||||||
shGetPathFromIDListEx = shell32.NewProc("SHGetPathFromIDListEx")
|
shGetPathFromIDListEx = shell32.NewProc("SHGetPathFromIDListEx")
|
||||||
shCreateItemFromParsingName = shell32.NewProc("SHCreateItemFromParsingName")
|
shCreateItemFromParsingName = shell32.NewProc("SHCreateItemFromParsingName")
|
||||||
|
|
34
init_windows.go
Normal file
34
init_windows.go
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package zenity
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
var (
|
||||||
|
comdlg32 = syscall.NewLazyDLL("comdlg32.dll")
|
||||||
|
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||||
|
ole32 = syscall.NewLazyDLL("ole32.dll")
|
||||||
|
shell32 = syscall.NewLazyDLL("shell32.dll")
|
||||||
|
user32 = syscall.NewLazyDLL("user32.dll")
|
||||||
|
|
||||||
|
getCurrentThreadId = kernel32.NewProc("GetCurrentThreadId")
|
||||||
|
|
||||||
|
coInitializeEx = ole32.NewProc("CoInitializeEx")
|
||||||
|
coUninitialize = ole32.NewProc("CoUninitialize")
|
||||||
|
coCreateInstance = ole32.NewProc("CoCreateInstance")
|
||||||
|
coTaskMemFree = ole32.NewProc("CoTaskMemFree")
|
||||||
|
|
||||||
|
getClassName = user32.NewProc("GetClassNameA")
|
||||||
|
setWindowsHookEx = user32.NewProc("SetWindowsHookExW")
|
||||||
|
unhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx")
|
||||||
|
callNextHookEx = user32.NewProc("CallNextHookEx")
|
||||||
|
enumChildWindows = user32.NewProc("EnumChildWindows")
|
||||||
|
getDlgCtrlID = user32.NewProc("GetDlgCtrlID")
|
||||||
|
setWindowText = user32.NewProc("SetWindowTextW")
|
||||||
|
)
|
||||||
|
|
||||||
|
type _CWPRETSTRUCT struct {
|
||||||
|
Result uintptr
|
||||||
|
LParam uintptr
|
||||||
|
WParam uintptr
|
||||||
|
Message uint32
|
||||||
|
HWnd uintptr
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
package zenity
|
package zenity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
user32 = syscall.NewLazyDLL("user32.dll")
|
|
||||||
messageBox = user32.NewProc("MessageBoxW")
|
messageBox = user32.NewProc("MessageBoxW")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,17 +49,86 @@ func message(typ int, text string, options []Option) (bool, error) {
|
||||||
flags |= 0x40 // MB_ICONINFORMATION
|
flags |= 0x40 // MB_ICONINFORMATION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if typ == 2 && opts.defcancel {
|
||||||
|
if opts.extra == "" {
|
||||||
|
flags |= 0x100 // MB_DEFBUTTON2
|
||||||
|
} else {
|
||||||
|
flags |= 0x200 // MB_DEFBUTTON3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if opts.title != "" {
|
if opts.title != "" {
|
||||||
caption = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(opts.title)))
|
caption = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(opts.title)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.ok != "" || opts.cancel != "" || opts.extra != "" {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
defer runtime.UnlockOSThread()
|
||||||
|
|
||||||
|
hook, err := hookMessageLabels(typ, opts)
|
||||||
|
if hook == 0 {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer unhookWindowsHookEx.Call(hook)
|
||||||
|
}
|
||||||
|
|
||||||
n, _, err := messageBox.Call(0,
|
n, _, err := messageBox.Call(0,
|
||||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))),
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))),
|
||||||
caption, flags)
|
caption, flags)
|
||||||
|
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return false, err
|
return false, err
|
||||||
|
}
|
||||||
|
if n == 7 || n == 2 && typ != 2 { // IDNO
|
||||||
|
return false, ErrExtraButton
|
||||||
|
}
|
||||||
|
if n == 1 || n == 6 { // IDOK, IDYES
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hookMessageLabels(typ int, opts options) (hook uintptr, err error) {
|
||||||
|
tid, _, _ := getCurrentThreadId.Call()
|
||||||
|
hook, _, err = setWindowsHookEx.Call(12, // WH_CALLWNDPROCRET
|
||||||
|
syscall.NewCallback(func(code int, wparam, lparam uintptr) uintptr {
|
||||||
|
msg := *(*_CWPRETSTRUCT)(unsafe.Pointer(lparam))
|
||||||
|
if msg.Message == 0x0110 { // WM_INITDIALOG
|
||||||
|
name := [7]byte{}
|
||||||
|
n, _, _ := getClassName.Call(msg.HWnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name)))
|
||||||
|
if string(name[:n]) == "#32770" {
|
||||||
|
enumChildWindows.Call(msg.HWnd,
|
||||||
|
syscall.NewCallback(func(hwnd, lparam uintptr) uintptr {
|
||||||
|
name := [7]byte{}
|
||||||
|
n, _, _ := getClassName.Call(hwnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name)))
|
||||||
|
if string(name[:n]) == "Button" {
|
||||||
|
ctl, _, _ := getDlgCtrlID.Call(hwnd)
|
||||||
|
var text string
|
||||||
|
switch ctl {
|
||||||
|
case 1, 6: // IDOK, IDYES
|
||||||
|
text = opts.ok
|
||||||
|
case 2: // IDCANCEL
|
||||||
|
if typ == 2 {
|
||||||
|
text = opts.cancel
|
||||||
|
} else if opts.extra != "" {
|
||||||
|
text = opts.extra
|
||||||
} else {
|
} else {
|
||||||
return n == 1 /* IDOK */ || n == 6 /* IDYES */, nil
|
text = opts.ok
|
||||||
|
}
|
||||||
|
case 7: // IDNO
|
||||||
|
text = opts.extra
|
||||||
|
}
|
||||||
|
if text != "" {
|
||||||
|
ptr := syscall.StringToUTF16Ptr(text)
|
||||||
|
setWindowText.Call(hwnd, uintptr(unsafe.Pointer(ptr)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 1
|
||||||
|
}), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next, _, _ := callNextHookEx.Call(hook, uintptr(code), wparam, lparam)
|
||||||
|
return next
|
||||||
|
}), 0, tid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue