Refactor (windows).

This commit is contained in:
Nuno Cruces 2021-04-09 01:05:48 +01:00
parent a16177f604
commit 1ca281d701
4 changed files with 73 additions and 86 deletions

View file

@ -1,12 +1,10 @@
package zenity package zenity
import ( import (
"strconv"
"syscall" "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 var title string
if opts.title != nil { if opts.title != nil {
title = *opts.title title = *opts.title
@ -17,88 +15,14 @@ func entry(text string, opts options) (string, bool, error) {
if opts.cancelLabel == nil { if opts.cancelLabel == nil {
opts.cancelLabel = stringPtr("Cancel") 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()() defer setup()()
font := getFont() font := getFont()
defer font.Delete() defer font.Delete()
defWindowProc := defWindowProc.Addr()
var wnd, textCtl, editCtl uintptr
var okBtn, cancelBtn, extraBtn uintptr
layout := func(dpi dpi) { layout := func(dpi dpi) {
hfont := font.ForDPI(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 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
}

View file

@ -6,6 +6,7 @@ import (
"os" "os"
"reflect" "reflect"
"runtime" "runtime"
"strconv"
"sync/atomic" "sync/atomic"
"syscall" "syscall"
"unsafe" "unsafe"
@ -37,6 +38,7 @@ var (
getMessage = user32.NewProc("GetMessageW") getMessage = user32.NewProc("GetMessageW")
sendMessage = user32.NewProc("SendMessageW") sendMessage = user32.NewProc("SendMessageW")
postQuitMessage = user32.NewProc("PostQuitMessage")
isDialogMessage = user32.NewProc("IsDialogMessageW") isDialogMessage = user32.NewProc("IsDialogMessageW")
dispatchMessage = user32.NewProc("DispatchMessageW") dispatchMessage = user32.NewProc("DispatchMessageW")
translateMessage = user32.NewProc("TranslateMessage") translateMessage = user32.NewProc("TranslateMessage")
@ -56,6 +58,16 @@ var (
releaseDC = user32.NewProc("ReleaseDC") releaseDC = user32.NewProc("ReleaseDC")
getWindowDC = user32.NewProc("GetWindowDC") getWindowDC = user32.NewProc("GetWindowDC")
systemParametersInfo = user32.NewProc("SystemParametersInfoW") 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 { 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 // https://docs.microsoft.com/en-us/windows/win32/winmsg/using-messages-and-message-queues
func messageLoop(wnd uintptr) error { func messageLoop(wnd uintptr) error {
getMessage := getMessage.Addr() getMessage := getMessage.Addr()
@ -332,6 +378,22 @@ type _RECT struct {
bottom int32 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 // https://github.com/wine-mirror/wine/blob/master/include/unknwn.idl
type _IUnknownVtbl struct { type _IUnknownVtbl struct {

View file

@ -1,5 +0,0 @@
package zenity
func init() {
user32.NewProc("SetProcessDPIAware").Call()
}