Refactor (windows).
This commit is contained in:
parent
d33a18d05a
commit
d47150a866
24 changed files with 222 additions and 145 deletions
|
@ -27,7 +27,7 @@ func selectColor(opts options) (color.Color, error) {
|
|||
|
||||
var args win.CHOOSECOLOR
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
args.Owner, _ = opts.attach.(uintptr)
|
||||
args.Owner, _ = opts.attach.(win.HWND)
|
||||
args.CustColors = &customColors
|
||||
|
||||
if opts.color != nil {
|
||||
|
|
|
@ -37,22 +37,6 @@ const (
|
|||
_SWP_NOMOVE = 0x0002
|
||||
_SWP_NOZORDER = 0x0004
|
||||
|
||||
_MB_OKCANCEL = 0x00000001
|
||||
_MB_YESNOCANCEL = 0x00000003
|
||||
_MB_YESNO = 0x00000004
|
||||
_MB_ICONERROR = 0x00000010
|
||||
_MB_ICONQUESTION = 0x00000020
|
||||
_MB_ICONWARNING = 0x00000030
|
||||
_MB_ICONINFORMATION = 0x00000040
|
||||
_MB_DEFBUTTON1 = 0x00000000
|
||||
_MB_DEFBUTTON2 = 0x00000100
|
||||
_MB_DEFBUTTON3 = 0x00000200
|
||||
|
||||
_IDOK = 1
|
||||
_IDCANCEL = 2
|
||||
_IDYES = 6
|
||||
_IDNO = 7
|
||||
|
||||
_SC_CLOSE = 0xf060
|
||||
|
||||
_WM_DESTROY = 0x0002
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
)
|
||||
|
||||
func calendar(text string, opts options) (time.Time, error) {
|
||||
|
@ -56,12 +58,12 @@ func (dlg *calendarDialog) setup(text string, opts options) (time.Time, error) {
|
|||
}
|
||||
defer unregisterClass.Call(cls, instance)
|
||||
|
||||
owner, _ := opts.attach.(uintptr)
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
dlg.wnd, _, _ = createWindowEx.Call(_WS_EX_CONTROLPARENT|_WS_EX_WINDOWEDGE|_WS_EX_DLGMODALFRAME,
|
||||
cls, strptr(*opts.title),
|
||||
_WS_POPUPWINDOW|_WS_CLIPSIBLINGS|_WS_DLGFRAME,
|
||||
_CW_USEDEFAULT, _CW_USEDEFAULT,
|
||||
281, 281, owner, 0, instance, uintptr(unsafe.Pointer(dlg)))
|
||||
281, 281, uintptr(owner), 0, instance, uintptr(unsafe.Pointer(dlg)))
|
||||
|
||||
dlg.textCtl, _, _ = createWindowEx.Call(0,
|
||||
strptr("STATIC"), strptr(text),
|
||||
|
@ -77,16 +79,16 @@ func (dlg *calendarDialog) setup(text string, opts options) (time.Time, error) {
|
|||
dlg.okBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.okLabel),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP|_BS_DEFPUSHBUTTON,
|
||||
12, 206, 75, 24, dlg.wnd, _IDOK, instance, 0)
|
||||
12, 206, 75, 24, dlg.wnd, win.IDOK, instance, 0)
|
||||
dlg.cancelBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.cancelLabel),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP,
|
||||
12, 206, 75, 24, dlg.wnd, _IDCANCEL, instance, 0)
|
||||
12, 206, 75, 24, dlg.wnd, win.IDCANCEL, instance, 0)
|
||||
if opts.extraButton != nil {
|
||||
dlg.extraBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.extraButton),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP,
|
||||
12, 206, 75, 24, dlg.wnd, _IDNO, instance, 0)
|
||||
12, 206, 75, 24, dlg.wnd, win.IDNO, instance, 0)
|
||||
}
|
||||
|
||||
if opts.time != nil {
|
||||
|
@ -168,13 +170,13 @@ func calendarProc(wnd uintptr, msg uint32, wparam uintptr, lparam *unsafe.Pointe
|
|||
switch wparam {
|
||||
default:
|
||||
return 1
|
||||
case _IDOK, _IDYES:
|
||||
case win.IDOK, win.IDYES:
|
||||
var date _SYSTEMTIME
|
||||
sendMessage.Call(dlg.dateCtl, _MCM_GETCURSEL, 0, uintptr(unsafe.Pointer(&date)))
|
||||
dlg.out = time.Date(int(date.year), time.Month(date.month), int(date.day), 0, 0, 0, 0, time.UTC)
|
||||
case _IDCANCEL:
|
||||
case win.IDCANCEL:
|
||||
dlg.err = ErrCanceled
|
||||
case _IDNO:
|
||||
case win.IDNO:
|
||||
dlg.err = ErrExtraButton
|
||||
}
|
||||
destroyWindow.Call(wnd)
|
||||
|
|
|
@ -3,6 +3,8 @@ package zenity
|
|||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
)
|
||||
|
||||
func entry(text string, opts options) (string, error) {
|
||||
|
@ -55,12 +57,12 @@ func (dlg *entryDialog) setup(text string, opts options) (string, error) {
|
|||
}
|
||||
defer unregisterClass.Call(cls, instance)
|
||||
|
||||
owner, _ := opts.attach.(uintptr)
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
dlg.wnd, _, _ = createWindowEx.Call(_WS_EX_CONTROLPARENT|_WS_EX_WINDOWEDGE|_WS_EX_DLGMODALFRAME,
|
||||
cls, strptr(*opts.title),
|
||||
_WS_POPUPWINDOW|_WS_CLIPSIBLINGS|_WS_DLGFRAME,
|
||||
_CW_USEDEFAULT, _CW_USEDEFAULT,
|
||||
281, 141, owner, 0, instance, uintptr(unsafe.Pointer(dlg)))
|
||||
281, 141, uintptr(owner), 0, instance, uintptr(unsafe.Pointer(dlg)))
|
||||
|
||||
dlg.textCtl, _, _ = createWindowEx.Call(0,
|
||||
strptr("STATIC"), strptr(text),
|
||||
|
@ -79,16 +81,16 @@ func (dlg *entryDialog) setup(text string, opts options) (string, error) {
|
|||
dlg.okBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.okLabel),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP|_BS_DEFPUSHBUTTON,
|
||||
12, 66, 75, 24, dlg.wnd, _IDOK, instance, 0)
|
||||
12, 66, 75, 24, dlg.wnd, win.IDOK, instance, 0)
|
||||
dlg.cancelBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.cancelLabel),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP,
|
||||
12, 66, 75, 24, dlg.wnd, _IDCANCEL, instance, 0)
|
||||
12, 66, 75, 24, dlg.wnd, win.IDCANCEL, instance, 0)
|
||||
if opts.extraButton != nil {
|
||||
dlg.extraBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.extraButton),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP,
|
||||
12, 66, 75, 24, dlg.wnd, _IDNO, instance, 0)
|
||||
12, 66, 75, 24, dlg.wnd, win.IDNO, instance, 0)
|
||||
}
|
||||
|
||||
dlg.layout(getDPI(dlg.wnd))
|
||||
|
@ -162,11 +164,11 @@ func entryProc(wnd uintptr, msg uint32, wparam uintptr, lparam *unsafe.Pointer)
|
|||
switch wparam {
|
||||
default:
|
||||
return 1
|
||||
case _IDOK, _IDYES:
|
||||
case win.IDOK, win.IDYES:
|
||||
dlg.out = getWindowString(dlg.editCtl)
|
||||
case _IDCANCEL:
|
||||
case win.IDCANCEL:
|
||||
dlg.err = ErrCanceled
|
||||
case _IDNO:
|
||||
case win.IDNO:
|
||||
dlg.err = ErrExtraButton
|
||||
}
|
||||
destroyWindow.Call(wnd)
|
||||
|
|
|
@ -27,7 +27,7 @@ func selectFile(opts options) (string, error) {
|
|||
|
||||
var args win.OPENFILENAME
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
args.Owner, _ = opts.attach.(uintptr)
|
||||
args.Owner, _ = opts.attach.(win.HWND)
|
||||
args.Flags = win.OFN_NOCHANGEDIR | win.OFN_FILEMUSTEXIST | win.OFN_EXPLORER
|
||||
|
||||
if opts.title != nil {
|
||||
|
@ -73,7 +73,7 @@ func selectFileMultiple(opts options) ([]string, error) {
|
|||
|
||||
var args win.OPENFILENAME
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
args.Owner, _ = opts.attach.(uintptr)
|
||||
args.Owner, _ = opts.attach.(win.HWND)
|
||||
args.Flags = win.OFN_NOCHANGEDIR | win.OFN_ALLOWMULTISELECT | win.OFN_FILEMUSTEXIST | win.OFN_EXPLORER
|
||||
|
||||
if opts.title != nil {
|
||||
|
@ -144,7 +144,7 @@ func selectFileSave(opts options) (string, error) {
|
|||
|
||||
var args win.OPENFILENAME
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
args.Owner, _ = opts.attach.(uintptr)
|
||||
args.Owner, _ = opts.attach.(win.HWND)
|
||||
args.Flags = win.OFN_NOCHANGEDIR | win.OFN_PATHMUSTEXIST | win.OFN_NOREADONLYRETURN | win.OFN_EXPLORER
|
||||
|
||||
if opts.title != nil {
|
||||
|
@ -252,8 +252,8 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
|||
defer unhook()
|
||||
}
|
||||
|
||||
owner, _ := opts.attach.(uintptr)
|
||||
hr, _, _ = dialog.Call(dialog.Show, owner)
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
hr, _, _ = dialog.Call(dialog.Show, uintptr(owner))
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return "", nil, opts.ctx.Err()
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
|||
|
||||
func browseForFolder(opts options) (string, []string, error) {
|
||||
var args win.BROWSEINFO
|
||||
args.Owner, _ = opts.attach.(uintptr)
|
||||
args.Owner, _ = opts.attach.(win.HWND)
|
||||
args.Flags = 0x1 // BIF_RETURNONLYFSDIRS
|
||||
|
||||
if opts.title != nil {
|
||||
|
|
|
@ -17,8 +17,8 @@ const (
|
|||
// https://docs.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-choosecolorw-r1
|
||||
type CHOOSECOLOR struct {
|
||||
StructSize uint32
|
||||
Owner uintptr
|
||||
Instance uintptr
|
||||
Owner HWND
|
||||
Instance HWND
|
||||
RgbResult uint32
|
||||
CustColors *[16]uint32
|
||||
Flags uint32
|
||||
|
@ -42,8 +42,8 @@ const (
|
|||
// https://docs.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamew
|
||||
type OPENFILENAME struct {
|
||||
StructSize uint32
|
||||
Owner uintptr
|
||||
Instance uintptr
|
||||
Owner HWND
|
||||
Instance Handle
|
||||
Filter *uint16
|
||||
CustomFilter *uint16
|
||||
MaxCustomFilter uint32
|
||||
|
|
30
internal/win/gdi32.go
Normal file
30
internal/win/gdi32.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
//go:build windows
|
||||
|
||||
package win
|
||||
|
||||
const (
|
||||
LOGPIXELSX = 88
|
||||
LOGPIXELSY = 90
|
||||
)
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-logfontw
|
||||
type LOGFONT struct {
|
||||
Height int32
|
||||
Width int32
|
||||
Escapement int32
|
||||
Orientation int32
|
||||
Weight int32
|
||||
Italic byte
|
||||
Underline byte
|
||||
StrikeOut byte
|
||||
CharSet byte
|
||||
OutPrecision byte
|
||||
ClipPrecision byte
|
||||
Quality byte
|
||||
PitchAndFamily byte
|
||||
FaceName [32]uint16
|
||||
}
|
||||
|
||||
//sys CreateFontIndirect(lf *LOGFONT) (font Handle) = gdi32.CreateFontIndirectW
|
||||
//sys DeleteObject(o Handle) (ok bool) = gdi32.DeleteObject
|
||||
//sys GetDeviceCaps(dc Handle, index int) (cap uintptr) = gdi32.GetDeviceCaps
|
|
@ -1,5 +1,6 @@
|
|||
// Package win is internal. DO NOT USE.
|
||||
package win
|
||||
//go:build generate
|
||||
|
||||
//go:generate -command mkwinsyscall go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go
|
||||
//go:generate mkwinsyscall comctl32.go comdlg32.go ole32.go shell32.go
|
||||
//go:generate mkwinsyscall comctl32.go comdlg32.go gdi32.go ole32.go shell32.go user32.go
|
||||
|
||||
package win
|
|
@ -9,7 +9,7 @@ const (
|
|||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-browseinfow
|
||||
type BROWSEINFO struct {
|
||||
Owner uintptr
|
||||
Owner HWND
|
||||
Root uintptr
|
||||
DisplayName *uint16
|
||||
Title *uint16
|
||||
|
@ -22,11 +22,11 @@ type BROWSEINFO struct {
|
|||
// https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataw
|
||||
type NOTIFYICONDATA struct {
|
||||
StructSize uint32
|
||||
Wnd uintptr
|
||||
Wnd HWND
|
||||
ID uint32
|
||||
Flags uint32
|
||||
CallbackMessage uint32
|
||||
Icon uintptr
|
||||
Icon Handle
|
||||
Tip [128]uint16 // NOTIFYICONDATAA_V1_SIZE
|
||||
State uint32
|
||||
StateMask uint32
|
||||
|
@ -35,7 +35,7 @@ type NOTIFYICONDATA struct {
|
|||
InfoTitle [64]uint16
|
||||
InfoFlags uint32
|
||||
// GuidItem [16]byte // NOTIFYICONDATAA_V2_SIZE
|
||||
// BalloonIcon syscall.Handle // NOTIFYICONDATAA_V3_SIZE
|
||||
// BalloonIcon Handle // NOTIFYICONDATAA_V3_SIZE
|
||||
}
|
||||
|
||||
type IShellItem struct {
|
||||
|
|
34
internal/win/user32.go
Normal file
34
internal/win/user32.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
//go:build windows
|
||||
|
||||
package win
|
||||
|
||||
import "golang.org/x/sys/windows"
|
||||
|
||||
const (
|
||||
IDOK = 1
|
||||
IDCANCEL = 2
|
||||
IDABORT = 3
|
||||
IDRETRY = 4
|
||||
IDIGNORE = 5
|
||||
IDYES = 6
|
||||
IDNO = 7
|
||||
|
||||
MB_OK = windows.MB_OK
|
||||
MB_OKCANCEL = windows.MB_OKCANCEL
|
||||
MB_ABORTRETRYIGNORE = windows.MB_ABORTRETRYIGNORE
|
||||
MB_YESNOCANCEL = windows.MB_YESNOCANCEL
|
||||
MB_YESNO = windows.MB_YESNO
|
||||
MB_RETRYCANCEL = windows.MB_RETRYCANCEL
|
||||
MB_CANCELTRYCONTINUE = windows.MB_CANCELTRYCONTINUE
|
||||
MB_ICONERROR = windows.MB_ICONERROR
|
||||
MB_ICONQUESTION = windows.MB_ICONQUESTION
|
||||
MB_ICONWARNING = windows.MB_ICONWARNING
|
||||
MB_ICONINFORMATION = windows.MB_ICONINFORMATION
|
||||
MB_DEFBUTTON1 = windows.MB_DEFBUTTON1
|
||||
MB_DEFBUTTON2 = windows.MB_DEFBUTTON2
|
||||
MB_DEFBUTTON3 = windows.MB_DEFBUTTON3
|
||||
)
|
||||
|
||||
func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) {
|
||||
return windows.MessageBox(hwnd, text, caption, boxtype)
|
||||
}
|
9
internal/win/win32.go
Normal file
9
internal/win/win32.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
//go:build windows
|
||||
|
||||
// Package win is internal. DO NOT USE.
|
||||
package win
|
||||
|
||||
import "golang.org/x/sys/windows"
|
||||
|
||||
type Handle = windows.Handle
|
||||
type HWND = windows.HWND
|
|
@ -40,6 +40,7 @@ func errnoErr(e syscall.Errno) error {
|
|||
var (
|
||||
modcomctl32 = windows.NewLazySystemDLL("comctl32.dll")
|
||||
modcomdlg32 = windows.NewLazySystemDLL("comdlg32.dll")
|
||||
modgdi32 = windows.NewLazySystemDLL("gdi32.dll")
|
||||
modole32 = windows.NewLazySystemDLL("ole32.dll")
|
||||
modshell32 = windows.NewLazySystemDLL("shell32.dll")
|
||||
|
||||
|
@ -48,6 +49,9 @@ var (
|
|||
procCommDlgExtendedError = modcomdlg32.NewProc("CommDlgExtendedError")
|
||||
procGetOpenFileNameW = modcomdlg32.NewProc("GetOpenFileNameW")
|
||||
procGetSaveFileNameW = modcomdlg32.NewProc("GetSaveFileNameW")
|
||||
procCreateFontIndirectW = modgdi32.NewProc("CreateFontIndirectW")
|
||||
procDeleteObject = modgdi32.NewProc("DeleteObject")
|
||||
procGetDeviceCaps = modgdi32.NewProc("GetDeviceCaps")
|
||||
procCoCreateInstance = modole32.NewProc("CoCreateInstance")
|
||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||
procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolder")
|
||||
|
@ -86,6 +90,24 @@ func GetSaveFileName(ofn *OPENFILENAME) (ok bool) {
|
|||
return
|
||||
}
|
||||
|
||||
func CreateFontIndirect(lf *LOGFONT) (font Handle) {
|
||||
r0, _, _ := syscall.Syscall(procCreateFontIndirectW.Addr(), 1, uintptr(unsafe.Pointer(lf)), 0, 0)
|
||||
font = Handle(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteObject(o Handle) (ok bool) {
|
||||
r0, _, _ := syscall.Syscall(procDeleteObject.Addr(), 1, uintptr(o), 0, 0)
|
||||
ok = r0 != 0
|
||||
return
|
||||
}
|
||||
|
||||
func GetDeviceCaps(dc Handle, index int) (cap uintptr) {
|
||||
r0, _, _ := syscall.Syscall(procGetDeviceCaps.Addr(), 2, uintptr(dc), uintptr(index), 0)
|
||||
cap = uintptr(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (ret error) {
|
||||
r0, _, _ := syscall.Syscall6(procCoCreateInstance.Addr(), 5, uintptr(clsid), uintptr(unkOuter), uintptr(clsContext), uintptr(iid), uintptr(address), 0)
|
||||
if r0 != 0 {
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
package zenutil
|
||||
|
||||
//go:generate go run osa_generator.go osascripts/
|
|
@ -1,4 +1,5 @@
|
|||
// Code generated by zenity; DO NOT EDIT.
|
||||
|
||||
//go:build darwin
|
||||
|
||||
package zenutil
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
//go:build tools
|
||||
//go:build generate
|
||||
|
||||
//go:generate go run osa_generator.go osascripts/
|
||||
|
||||
package main
|
||||
|
||||
|
@ -102,6 +104,7 @@ func minify(data []byte) ([]byte, error) {
|
|||
}
|
||||
|
||||
var generator = template.Must(template.New("").Parse(`// Code generated by zenity; DO NOT EDIT.
|
||||
|
||||
//go:build darwin
|
||||
|
||||
package zenutil
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package zenutil
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// ParseWindowId is internal.
|
||||
func ParseWindowId(id string) uintptr {
|
||||
func ParseWindowId(id string) windows.HWND {
|
||||
hwnd, _ := strconv.ParseUint(id, 0, 64)
|
||||
return uintptr(hwnd)
|
||||
return windows.HWND(uintptr(hwnd))
|
||||
}
|
||||
|
||||
// GetParentWindowId is internal.
|
||||
|
|
|
@ -3,6 +3,8 @@ package zenity
|
|||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
)
|
||||
|
||||
func list(text string, items []string, opts options) (string, error) {
|
||||
|
@ -72,12 +74,12 @@ func (dlg *listDialog) setup(text string, opts options) ([]string, error) {
|
|||
}
|
||||
defer unregisterClass.Call(cls, instance)
|
||||
|
||||
owner, _ := opts.attach.(uintptr)
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
dlg.wnd, _, _ = createWindowEx.Call(_WS_EX_CONTROLPARENT|_WS_EX_WINDOWEDGE|_WS_EX_DLGMODALFRAME,
|
||||
cls, strptr(*opts.title),
|
||||
_WS_POPUPWINDOW|_WS_CLIPSIBLINGS|_WS_DLGFRAME,
|
||||
_CW_USEDEFAULT, _CW_USEDEFAULT,
|
||||
281, 281, owner, 0, instance, uintptr(unsafe.Pointer(dlg)))
|
||||
281, 281, uintptr(owner), 0, instance, uintptr(unsafe.Pointer(dlg)))
|
||||
|
||||
dlg.textCtl, _, _ = createWindowEx.Call(0,
|
||||
strptr("STATIC"), strptr(text),
|
||||
|
@ -96,16 +98,16 @@ func (dlg *listDialog) setup(text string, opts options) ([]string, error) {
|
|||
dlg.okBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.okLabel),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP|_BS_DEFPUSHBUTTON,
|
||||
12, 206, 75, 24, dlg.wnd, _IDOK, instance, 0)
|
||||
12, 206, 75, 24, dlg.wnd, win.IDOK, instance, 0)
|
||||
dlg.cancelBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.cancelLabel),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP,
|
||||
12, 206, 75, 24, dlg.wnd, _IDCANCEL, instance, 0)
|
||||
12, 206, 75, 24, dlg.wnd, win.IDCANCEL, instance, 0)
|
||||
if opts.extraButton != nil {
|
||||
dlg.extraBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.extraButton),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP,
|
||||
12, 206, 75, 24, dlg.wnd, _IDNO, instance, 0)
|
||||
12, 206, 75, 24, dlg.wnd, win.IDNO, instance, 0)
|
||||
}
|
||||
|
||||
for _, item := range dlg.items {
|
||||
|
@ -182,7 +184,7 @@ func listProc(wnd uintptr, msg uint32, wparam uintptr, lparam *unsafe.Pointer) u
|
|||
switch wparam {
|
||||
default:
|
||||
return 1
|
||||
case _IDOK, _IDYES:
|
||||
case win.IDOK, win.IDYES:
|
||||
if dlg.multiple {
|
||||
if len, _, _ := sendMessage.Call(dlg.listCtl, _LB_GETSELCOUNT, 0, 0); int32(len) >= 0 {
|
||||
dlg.out = make([]string, len)
|
||||
|
@ -201,9 +203,9 @@ func listProc(wnd uintptr, msg uint32, wparam uintptr, lparam *unsafe.Pointer) u
|
|||
dlg.out = []string{}
|
||||
}
|
||||
}
|
||||
case _IDCANCEL:
|
||||
case win.IDCANCEL:
|
||||
dlg.err = ErrCanceled
|
||||
case _IDNO:
|
||||
case win.IDNO:
|
||||
dlg.err = ErrExtraButton
|
||||
}
|
||||
destroyWindow.Call(wnd)
|
||||
|
|
|
@ -4,54 +4,55 @@ import (
|
|||
"context"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
)
|
||||
|
||||
var (
|
||||
getDlgCtrlID = user32.NewProc("GetDlgCtrlID")
|
||||
messageBox = user32.NewProc("MessageBoxW")
|
||||
)
|
||||
|
||||
func message(kind messageKind, text string, opts options) error {
|
||||
var flags uintptr
|
||||
var flags uint32
|
||||
|
||||
switch {
|
||||
case kind == questionKind && opts.extraButton != nil:
|
||||
flags |= _MB_YESNOCANCEL
|
||||
flags |= win.MB_YESNOCANCEL
|
||||
case kind == questionKind:
|
||||
flags |= _MB_OKCANCEL
|
||||
flags |= win.MB_OKCANCEL
|
||||
case opts.extraButton != nil:
|
||||
flags |= _MB_YESNO
|
||||
flags |= win.MB_YESNO
|
||||
}
|
||||
|
||||
switch opts.icon {
|
||||
case ErrorIcon:
|
||||
flags |= _MB_ICONERROR
|
||||
flags |= win.MB_ICONERROR
|
||||
case QuestionIcon:
|
||||
flags |= _MB_ICONQUESTION
|
||||
flags |= win.MB_ICONQUESTION
|
||||
case WarningIcon:
|
||||
flags |= _MB_ICONWARNING
|
||||
flags |= win.MB_ICONWARNING
|
||||
case InfoIcon:
|
||||
flags |= _MB_ICONINFORMATION
|
||||
flags |= win.MB_ICONINFORMATION
|
||||
case NoIcon:
|
||||
//
|
||||
default:
|
||||
switch kind {
|
||||
case errorKind:
|
||||
flags |= _MB_ICONERROR
|
||||
flags |= win.MB_ICONERROR
|
||||
case questionKind:
|
||||
flags |= _MB_ICONQUESTION
|
||||
flags |= win.MB_ICONQUESTION
|
||||
case warningKind:
|
||||
flags |= _MB_ICONWARNING
|
||||
flags |= win.MB_ICONWARNING
|
||||
case infoKind:
|
||||
flags |= _MB_ICONINFORMATION
|
||||
flags |= win.MB_ICONINFORMATION
|
||||
}
|
||||
}
|
||||
|
||||
if kind == questionKind && opts.defaultCancel {
|
||||
if opts.extraButton == nil {
|
||||
flags |= _MB_DEFBUTTON2
|
||||
flags |= win.MB_DEFBUTTON2
|
||||
} else {
|
||||
flags |= _MB_DEFBUTTON3
|
||||
flags |= win.MB_DEFBUTTON3
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,18 +71,18 @@ func message(kind messageKind, text string, opts options) error {
|
|||
title = syscall.StringToUTF16Ptr(*opts.title)
|
||||
}
|
||||
|
||||
owner, _ := opts.attach.(uintptr)
|
||||
s, _, err := messageBox.Call(owner, strptr(text), uintptr(unsafe.Pointer(title)), flags)
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
s, err := win.MessageBox(owner, syscall.StringToUTF16Ptr(text), title, flags)
|
||||
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return opts.ctx.Err()
|
||||
}
|
||||
switch s {
|
||||
case _IDOK, _IDYES:
|
||||
case win.IDOK, win.IDYES:
|
||||
return nil
|
||||
case _IDCANCEL:
|
||||
case win.IDCANCEL:
|
||||
return ErrCanceled
|
||||
case _IDNO:
|
||||
case win.IDNO:
|
||||
return ErrExtraButton
|
||||
default:
|
||||
return err
|
||||
|
@ -101,11 +102,11 @@ func hookMessageDialogCallback(wnd uintptr, lparam *options) uintptr {
|
|||
|
||||
var text *string
|
||||
switch ctl {
|
||||
case _IDOK, _IDYES:
|
||||
case win.IDOK, win.IDYES:
|
||||
text = lparam.okLabel
|
||||
case _IDCANCEL:
|
||||
case win.IDCANCEL:
|
||||
text = lparam.cancelLabel
|
||||
case _IDNO:
|
||||
case win.IDNO:
|
||||
text = lparam.extraButton
|
||||
}
|
||||
if text != nil {
|
||||
|
|
|
@ -46,7 +46,7 @@ func notify(text string, opts options) error {
|
|||
icon := getIcon(opts.icon)
|
||||
if icon.handle != 0 {
|
||||
defer icon.delete()
|
||||
args.Icon = icon.handle
|
||||
args.Icon = win.Handle(icon.handle)
|
||||
args.Flags |= 0x00000002 // NIF_ICON
|
||||
args.InfoFlags |= 0x4 // NIIF_USER
|
||||
}
|
||||
|
@ -90,13 +90,13 @@ func wtsMessage(text string, opts options) error {
|
|||
|
||||
switch opts.icon {
|
||||
case ErrorIcon:
|
||||
flags |= _MB_ICONERROR
|
||||
flags |= win.MB_ICONERROR
|
||||
case QuestionIcon:
|
||||
flags |= _MB_ICONQUESTION
|
||||
flags |= win.MB_ICONQUESTION
|
||||
case WarningIcon:
|
||||
flags |= _MB_ICONWARNING
|
||||
flags |= win.MB_ICONWARNING
|
||||
case InfoIcon:
|
||||
flags |= _MB_ICONINFORMATION
|
||||
flags |= win.MB_ICONINFORMATION
|
||||
}
|
||||
|
||||
title := opts.title
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
)
|
||||
|
||||
func progress(opts options) (ProgressDialog, error) {
|
||||
|
@ -135,12 +137,12 @@ func (dlg *progressDialog) setup(opts options) error {
|
|||
}
|
||||
defer unregisterClass.Call(cls, instance)
|
||||
|
||||
owner, _ := opts.attach.(uintptr)
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
dlg.wnd, _, _ = createWindowEx.Call(_WS_EX_CONTROLPARENT|_WS_EX_WINDOWEDGE|_WS_EX_DLGMODALFRAME,
|
||||
cls, strptr(*opts.title),
|
||||
_WS_POPUPWINDOW|_WS_CLIPSIBLINGS|_WS_DLGFRAME,
|
||||
_CW_USEDEFAULT, _CW_USEDEFAULT,
|
||||
281, 133, owner, 0, instance, uintptr(unsafe.Pointer(dlg)))
|
||||
281, 133, uintptr(owner), 0, instance, uintptr(unsafe.Pointer(dlg)))
|
||||
|
||||
dlg.textCtl, _, _ = createWindowEx.Call(0,
|
||||
strptr("STATIC"), 0,
|
||||
|
@ -159,18 +161,18 @@ func (dlg *progressDialog) setup(opts options) error {
|
|||
dlg.okBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.okLabel),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP|_BS_DEFPUSHBUTTON|_WS_DISABLED,
|
||||
12, 58, 75, 24, dlg.wnd, _IDOK, instance, 0)
|
||||
12, 58, 75, 24, dlg.wnd, win.IDOK, instance, 0)
|
||||
if !opts.noCancel {
|
||||
dlg.cancelBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.cancelLabel),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP,
|
||||
12, 58, 75, 24, dlg.wnd, _IDCANCEL, instance, 0)
|
||||
12, 58, 75, 24, dlg.wnd, win.IDCANCEL, instance, 0)
|
||||
}
|
||||
if opts.extraButton != nil {
|
||||
dlg.extraBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.extraButton),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP,
|
||||
12, 58, 75, 24, dlg.wnd, _IDNO, instance, 0)
|
||||
12, 58, 75, 24, dlg.wnd, win.IDNO, instance, 0)
|
||||
}
|
||||
|
||||
dlg.layout(getDPI(dlg.wnd))
|
||||
|
@ -256,11 +258,11 @@ func progressProc(wnd uintptr, msg uint32, wparam uintptr, lparam *unsafe.Pointe
|
|||
switch wparam {
|
||||
default:
|
||||
return 1
|
||||
case _IDOK, _IDYES:
|
||||
case win.IDOK, win.IDYES:
|
||||
//
|
||||
case _IDCANCEL:
|
||||
case win.IDCANCEL:
|
||||
dlg.err = ErrCanceled
|
||||
case _IDNO:
|
||||
case win.IDNO:
|
||||
dlg.err = ErrExtraButton
|
||||
}
|
||||
destroyWindow.Call(wnd)
|
||||
|
|
|
@ -3,6 +3,8 @@ package zenity
|
|||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
)
|
||||
|
||||
func password(opts options) (string, string, error) {
|
||||
|
@ -65,12 +67,12 @@ func (dlg *passwordDialog) setup(opts options) (string, string, error) {
|
|||
}
|
||||
defer unregisterClass.Call(cls, instance)
|
||||
|
||||
owner, _ := opts.attach.(uintptr)
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
dlg.wnd, _, _ = createWindowEx.Call(_WS_EX_CONTROLPARENT|_WS_EX_WINDOWEDGE|_WS_EX_DLGMODALFRAME,
|
||||
cls, strptr(*opts.title),
|
||||
_WS_POPUPWINDOW|_WS_CLIPSIBLINGS|_WS_DLGFRAME,
|
||||
_CW_USEDEFAULT, _CW_USEDEFAULT,
|
||||
281, 191, owner, 0, instance, uintptr(unsafe.Pointer(dlg)))
|
||||
281, 191, uintptr(owner), 0, instance, uintptr(unsafe.Pointer(dlg)))
|
||||
|
||||
dlg.uTextCtl, _, _ = createWindowEx.Call(0,
|
||||
strptr("STATIC"), strptr("Username:"),
|
||||
|
@ -96,16 +98,16 @@ func (dlg *passwordDialog) setup(opts options) (string, string, error) {
|
|||
dlg.okBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.okLabel),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP|_BS_DEFPUSHBUTTON,
|
||||
12, 116, 75, 24, dlg.wnd, _IDOK, instance, 0)
|
||||
12, 116, 75, 24, dlg.wnd, win.IDOK, instance, 0)
|
||||
dlg.cancelBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.cancelLabel),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP,
|
||||
12, 116, 75, 24, dlg.wnd, _IDCANCEL, instance, 0)
|
||||
12, 116, 75, 24, dlg.wnd, win.IDCANCEL, instance, 0)
|
||||
if opts.extraButton != nil {
|
||||
dlg.extraBtn, _, _ = createWindowEx.Call(0,
|
||||
strptr("BUTTON"), strptr(*opts.extraButton),
|
||||
_WS_CHILD|_WS_VISIBLE|_WS_GROUP|_WS_TABSTOP,
|
||||
12, 116, 75, 24, dlg.wnd, _IDNO, instance, 0)
|
||||
12, 116, 75, 24, dlg.wnd, win.IDNO, instance, 0)
|
||||
}
|
||||
|
||||
dlg.layout(getDPI(dlg.wnd))
|
||||
|
@ -183,12 +185,12 @@ func passwordProc(wnd uintptr, msg uint32, wparam uintptr, lparam *unsafe.Pointe
|
|||
switch wparam {
|
||||
default:
|
||||
return 1
|
||||
case _IDOK, _IDYES:
|
||||
case win.IDOK, win.IDYES:
|
||||
dlg.usr = getWindowString(dlg.uEditCtl)
|
||||
dlg.pwd = getWindowString(dlg.pEditCtl)
|
||||
case _IDCANCEL:
|
||||
case win.IDCANCEL:
|
||||
dlg.err = ErrCanceled
|
||||
case _IDNO:
|
||||
case win.IDNO:
|
||||
dlg.err = ErrExtraButton
|
||||
}
|
||||
destroyWindow.Call(wnd)
|
||||
|
|
|
@ -98,6 +98,8 @@ func pwdResult(sep string, opts options, out []byte, err error) (string, string,
|
|||
return "", str, err
|
||||
}
|
||||
|
||||
func hwnd(i uint64) uintptr { return uintptr(i) }
|
||||
|
||||
// Replace with strings.Cut after 1.18.
|
||||
func cut(s, sep string) (before, after string, found bool) {
|
||||
if i := strings.Index(s, sep); i >= 0 {
|
||||
|
|
|
@ -17,16 +17,11 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
gdi32 = windows.NewLazySystemDLL("gdi32.dll")
|
||||
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
ntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
user32 = windows.NewLazySystemDLL("user32.dll")
|
||||
wtsapi32 = windows.NewLazySystemDLL("wtsapi32.dll")
|
||||
|
||||
createFontIndirect = gdi32.NewProc("CreateFontIndirectW")
|
||||
deleteObject = gdi32.NewProc("DeleteObject")
|
||||
getDeviceCaps = gdi32.NewProc("GetDeviceCaps")
|
||||
|
||||
activateActCtx = kernel32.NewProc("ActivateActCtx")
|
||||
createActCtx = kernel32.NewProc("CreateActCtxW")
|
||||
deactivateActCtx = kernel32.NewProc("DeactivateActCtx")
|
||||
|
@ -82,6 +77,8 @@ func strptr(s string) uintptr {
|
|||
return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))
|
||||
}
|
||||
|
||||
func hwnd(i uint64) win.HWND { return win.HWND(uintptr(i)) }
|
||||
|
||||
func setup() context.CancelFunc {
|
||||
var wnd uintptr
|
||||
enumWindows.Call(syscall.NewCallback(setupEnumCallback), uintptr(unsafe.Pointer(&wnd)))
|
||||
|
@ -264,7 +261,7 @@ func getDPI(wnd uintptr) dpi {
|
|||
if wnd != 0 && getDpiForWindow.Find() == nil {
|
||||
res, _, _ = getDpiForWindow.Call(wnd)
|
||||
} else if dc, _, _ := getWindowDC.Call(wnd); dc != 0 {
|
||||
res, _, _ = getDeviceCaps.Call(dc, 90) // LOGPIXELSY
|
||||
res = win.GetDeviceCaps(win.Handle(dc), win.LOGPIXELSY)
|
||||
releaseDC.Call(0, dc)
|
||||
}
|
||||
|
||||
|
@ -282,8 +279,8 @@ func (d dpi) scale(dim uintptr) uintptr {
|
|||
}
|
||||
|
||||
type font struct {
|
||||
handle uintptr
|
||||
logical _LOGFONT
|
||||
handle win.Handle
|
||||
logical win.LOGFONT
|
||||
}
|
||||
|
||||
func getFont() font {
|
||||
|
@ -298,14 +295,14 @@ func (f *font) forDPI(dpi dpi) uintptr {
|
|||
if h := -int32(dpi.scale(12)); f.handle == 0 || f.logical.Height != h {
|
||||
f.delete()
|
||||
f.logical.Height = h
|
||||
f.handle, _, _ = createFontIndirect.Call(uintptr(unsafe.Pointer(&f.logical)))
|
||||
f.handle = win.CreateFontIndirect(&f.logical)
|
||||
}
|
||||
return f.handle
|
||||
return uintptr(f.handle)
|
||||
}
|
||||
|
||||
func (f *font) delete() {
|
||||
if f.handle != 0 {
|
||||
deleteObject.Call(f.handle)
|
||||
win.DeleteObject(f.handle)
|
||||
f.handle = 0
|
||||
}
|
||||
}
|
||||
|
@ -470,24 +467,6 @@ type _CWPRETSTRUCT struct {
|
|||
Wnd uintptr
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-logfontw
|
||||
type _LOGFONT struct {
|
||||
Height int32
|
||||
Width int32
|
||||
Escapement int32
|
||||
Orientation int32
|
||||
Weight int32
|
||||
Italic byte
|
||||
Underline byte
|
||||
StrikeOut byte
|
||||
CharSet byte
|
||||
OutPrecision byte
|
||||
ClipPrecision byte
|
||||
Quality byte
|
||||
PitchAndFamily byte
|
||||
FaceName [32]uint16
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-nonclientmetricsw
|
||||
type _NONCLIENTMETRICS struct {
|
||||
Size uint32
|
||||
|
@ -496,15 +475,15 @@ type _NONCLIENTMETRICS struct {
|
|||
ScrollHeight int32
|
||||
CaptionWidth int32
|
||||
CaptionHeight int32
|
||||
CaptionFont _LOGFONT
|
||||
CaptionFont win.LOGFONT
|
||||
SmCaptionWidth int32
|
||||
SmCaptionHeight int32
|
||||
SmCaptionFont _LOGFONT
|
||||
SmCaptionFont win.LOGFONT
|
||||
MenuWidth int32
|
||||
MenuHeight int32
|
||||
MenuFont _LOGFONT
|
||||
StatusFont _LOGFONT
|
||||
MessageFont _LOGFONT
|
||||
MenuFont win.LOGFONT
|
||||
StatusFont win.LOGFONT
|
||||
MessageFont win.LOGFONT
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msg
|
||||
|
|
|
@ -201,7 +201,7 @@ func Attach(id any) Option {
|
|||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
if v := reflect.ValueOf(id); v.Kind() == reflect.Uintptr {
|
||||
id = uintptr(v.Uint())
|
||||
id = hwnd(v.Uint())
|
||||
} else {
|
||||
panic("interface conversion: expected uintptr")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue