diff --git a/entry_windows.go b/entry_windows.go index 28697bb..b81607c 100644 --- a/entry_windows.go +++ b/entry_windows.go @@ -1,12 +1,10 @@ package zenity import ( - "strconv" "syscall" - "unsafe" ) -func entry(text string, opts options) (string, bool, error) { +func entry(text string, opts options) (out string, ok bool, err error) { var title string if opts.title != nil { title = *opts.title @@ -17,88 +15,14 @@ func entry(text string, opts options) (string, bool, error) { if opts.cancelLabel == nil { opts.cancelLabel = stringPtr("Cancel") } - return editBox(title, text, opts) -} - -func password(opts options) (string, string, bool, error) { - opts.hideText = true - pass, ok, err := entry("Password:", opts) - return "", pass, ok, err -} - -var ( - registerClassEx = user32.NewProc("RegisterClassExW") - unregisterClass = user32.NewProc("UnregisterClassW") - createWindowEx = user32.NewProc("CreateWindowExW") - destroyWindow = user32.NewProc("DestroyWindow") - postQuitMessage = user32.NewProc("PostQuitMessage") - defWindowProc = user32.NewProc("DefWindowProcW") - getWindowRect = user32.NewProc("GetWindowRect") - setWindowPos = user32.NewProc("SetWindowPos") - setFocus = user32.NewProc("SetFocus") - showWindow = user32.NewProc("ShowWindow") - getSystemMetrics = user32.NewProc("GetSystemMetrics") -) - -// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassexw -type _WNDCLASSEX struct { - Size uint32 - Style uint32 - WndProc uintptr - ClsExtra int32 - WndExtra int32 - Instance uintptr - Icon uintptr - Cursor uintptr - Background uintptr - MenuName *uint16 - ClassName *uint16 - IconSm uintptr -} - -func getWindowString(wnd uintptr) string { - len, _, _ := getWindowTextLength.Call(wnd) - buf := make([]uint16, len+1) - getWindowText.Call(wnd, uintptr(unsafe.Pointer(&buf[0])), len+1) - return syscall.UTF16ToString(buf) -} - -func centerWindow(wnd uintptr) { - getMetric := func(i uintptr) int32 { - ret, _, _ := getSystemMetrics.Call(i) - return int32(ret) - } - - var rect _RECT - getWindowRect.Call(wnd, uintptr(unsafe.Pointer(&rect))) - x := (getMetric(0 /* SM_CXSCREEN */) - (rect.right - rect.left)) / 2 - y := (getMetric(1 /* SM_CYSCREEN */) - (rect.bottom - rect.top)) / 2 - setWindowPos.Call(wnd, 0, uintptr(x), uintptr(y), 0, 0, 0x5) // SWP_NOZORDER|SWP_NOSIZE -} - -func registerClass(instance, proc uintptr) (uintptr, error) { - name := "WC_" + strconv.FormatUint(uint64(proc), 16) - - var wcx _WNDCLASSEX - wcx.Size = uint32(unsafe.Sizeof(wcx)) - wcx.WndProc = proc - wcx.Instance = instance - wcx.Background = 5 // COLOR_WINDOW - wcx.ClassName = syscall.StringToUTF16Ptr(name) - - ret, _, err := registerClassEx.Call(uintptr(unsafe.Pointer(&wcx))) - return ret, err -} - -func editBox(title, text string, opts options) (out string, ok bool, err error) { - var wnd, textCtl, editCtl uintptr - var okBtn, cancelBtn, extraBtn uintptr - defWindowProc := defWindowProc.Addr() defer setup()() - font := getFont() defer font.Delete() + defWindowProc := defWindowProc.Addr() + + var wnd, textCtl, editCtl uintptr + var okBtn, cancelBtn, extraBtn uintptr layout := func(dpi dpi) { hfont := font.ForDPI(dpi) @@ -232,3 +156,9 @@ func editBox(title, text string, opts options) (out string, ok bool, err error) } return out, ok, err } + +func password(opts options) (string, string, bool, error) { + opts.hideText = true + str, ok, err := entry("Password:", opts) + return "", str, ok, err +} diff --git a/utils_unix.go b/util_unix.go similarity index 100% rename from utils_unix.go rename to util_unix.go diff --git a/util_windows.go b/util_windows.go index a9f7f07..9ec6050 100644 --- a/util_windows.go +++ b/util_windows.go @@ -6,6 +6,7 @@ import ( "os" "reflect" "runtime" + "strconv" "sync/atomic" "syscall" "unsafe" @@ -37,6 +38,7 @@ var ( getMessage = user32.NewProc("GetMessageW") sendMessage = user32.NewProc("SendMessageW") + postQuitMessage = user32.NewProc("PostQuitMessage") isDialogMessage = user32.NewProc("IsDialogMessageW") dispatchMessage = user32.NewProc("DispatchMessageW") translateMessage = user32.NewProc("TranslateMessage") @@ -56,6 +58,16 @@ var ( releaseDC = user32.NewProc("ReleaseDC") getWindowDC = user32.NewProc("GetWindowDC") systemParametersInfo = user32.NewProc("SystemParametersInfoW") + setWindowPos = user32.NewProc("SetWindowPos") + getWindowRect = user32.NewProc("GetWindowRect") + getSystemMetrics = user32.NewProc("GetSystemMetrics") + unregisterClass = user32.NewProc("UnregisterClassW") + registerClassEx = user32.NewProc("RegisterClassExW") + destroyWindow = user32.NewProc("DestroyWindow") + createWindowEx = user32.NewProc("CreateWindowExW") + showWindow = user32.NewProc("ShowWindow") + setFocus = user32.NewProc("SetFocus") + defWindowProc = user32.NewProc("DefWindowProcW") ) func intptr(i int64) uintptr { @@ -238,6 +250,40 @@ func (f *font) Delete() { } } +func centerWindow(wnd uintptr) { + getMetric := func(i uintptr) int32 { + ret, _, _ := getSystemMetrics.Call(i) + return int32(ret) + } + + var rect _RECT + getWindowRect.Call(wnd, uintptr(unsafe.Pointer(&rect))) + x := (getMetric(0 /* SM_CXSCREEN */) - (rect.right - rect.left)) / 2 + y := (getMetric(1 /* SM_CYSCREEN */) - (rect.bottom - rect.top)) / 2 + setWindowPos.Call(wnd, 0, uintptr(x), uintptr(y), 0, 0, 0x5) // SWP_NOZORDER|SWP_NOSIZE +} + +func getWindowString(wnd uintptr) string { + len, _, _ := getWindowTextLength.Call(wnd) + buf := make([]uint16, len+1) + getWindowText.Call(wnd, uintptr(unsafe.Pointer(&buf[0])), len+1) + return syscall.UTF16ToString(buf) +} + +func registerClass(instance, proc uintptr) (uintptr, error) { + name := "WC_" + strconv.FormatUint(uint64(proc), 16) + + var wcx _WNDCLASSEX + wcx.Size = uint32(unsafe.Sizeof(wcx)) + wcx.WndProc = proc + wcx.Instance = instance + wcx.Background = 5 // COLOR_WINDOW + wcx.ClassName = syscall.StringToUTF16Ptr(name) + + ret, _, err := registerClassEx.Call(uintptr(unsafe.Pointer(&wcx))) + return ret, err +} + // https://docs.microsoft.com/en-us/windows/win32/winmsg/using-messages-and-message-queues func messageLoop(wnd uintptr) error { getMessage := getMessage.Addr() @@ -332,6 +378,22 @@ type _RECT struct { bottom int32 } +// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassexw +type _WNDCLASSEX struct { + Size uint32 + Style uint32 + WndProc uintptr + ClsExtra int32 + WndExtra int32 + Instance uintptr + Icon uintptr + Cursor uintptr + Background uintptr + MenuName *uint16 + ClassName *uint16 + IconSm uintptr +} + // https://github.com/wine-mirror/wine/blob/master/include/unknwn.idl type _IUnknownVtbl struct { diff --git a/util_windows_test.go b/util_windows_test.go deleted file mode 100644 index f1a4489..0000000 --- a/util_windows_test.go +++ /dev/null @@ -1,5 +0,0 @@ -package zenity - -func init() { - user32.NewProc("SetProcessDPIAware").Call() -}