From b273c0992b8bfc1807dc66fd33c94102e8bbb0e9 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Mon, 20 Jun 2022 02:14:08 +0100 Subject: [PATCH] Refactor (windows). --- date_windows.go | 2 +- entry_windows.go | 2 +- file_windows.go | 21 +++--- internal/win/comdlg32.go | 4 +- internal/win/ole32.go | 17 ++++- internal/win/shell32.go | 11 ++- internal/win/user32.go | 70 +++++++++++++++++- internal/win/win32.go | 1 + internal/win/zsyscall_windows.go | 100 +++++++++++++++++-------- list_windows.go | 2 +- msg_windows.go | 2 +- progress_windows.go | 2 +- pwd_windows.go | 2 +- util_windows.go | 123 +++++++++---------------------- 14 files changed, 214 insertions(+), 145 deletions(-) diff --git a/date_windows.go b/date_windows.go index f70f5c8..b0c286c 100644 --- a/date_windows.go +++ b/date_windows.go @@ -117,7 +117,7 @@ func (dlg *calendarDialog) setup(text string, opts options) (time.Time, error) { }() } - if err := messageLoop(dlg.wnd); err != nil { + if err := win.MessageLoop(win.HWND(dlg.wnd)); err != nil { return time.Time{}, err } if opts.ctx != nil && opts.ctx.Err() != nil { diff --git a/entry_windows.go b/entry_windows.go index 13af8f6..22273f2 100644 --- a/entry_windows.go +++ b/entry_windows.go @@ -111,7 +111,7 @@ func (dlg *entryDialog) setup(text string, opts options) (string, error) { }() } - if err := messageLoop(dlg.wnd); err != nil { + if err := win.MessageLoop(win.HWND(dlg.wnd)); err != nil { return "", err } if opts.ctx != nil && opts.ctx.Err() != nil { diff --git a/file_windows.go b/file_windows.go index 939e8db..fcac4ea 100644 --- a/file_windows.go +++ b/file_windows.go @@ -17,6 +17,8 @@ const ( _FOS_FORCEFILESYSTEM = 0x00000040 _FOS_ALLOWMULTISELECT = 0x00000200 _FOS_FORCESHOWHIDDEN = 0x10000000 + + _SIGDN_FILESYSPATH = 0x80058000 ) func selectFile(opts options) (string, error) { @@ -191,7 +193,7 @@ func selectFileSave(opts options) (string, error) { func pickFolders(opts options, multi bool) (str string, lst []string, err error) { defer setup()() - err = win.CoInitializeEx(0, 0x6) // COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE + err = win.CoInitializeEx(0, win.COINIT_APARTMENTTHREADED|win.COINIT_DISABLE_OLE1DDE) if err != win.RPC_E_CHANGED_MODE { if err != nil { return "", nil, err @@ -201,7 +203,7 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error) var dialog *_IFileOpenDialog err = win.CoCreateInstance( - _CLSID_FileOpenDialog, nil, 0x17, // CLSCTX_ALL + _CLSID_FileOpenDialog, nil, win.CLSCTX_ALL, _IID_IFileOpenDialog, unsafe.Pointer(&dialog)) if err != nil { if multi { @@ -257,7 +259,7 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error) if opts.ctx != nil && opts.ctx.Err() != nil { return "", nil, opts.ctx.Err() } - if hr == 0x800704c7 { // ERROR_CANCELLED + if hr == uintptr(win.E_CANCELED) { return "", nil, ErrCanceled } if int32(hr) < 0 { @@ -272,10 +274,9 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error) } defer item.Call(item.Release) - var ptr uintptr + var ptr unsafe.Pointer hr, _, _ = item.Call(item.GetDisplayName, - 0x80058000, // SIGDN_FILESYSPATH - uintptr(unsafe.Pointer(&ptr))) + _SIGDN_FILESYSPATH, uintptr(unsafe.Pointer(&ptr))) if int32(hr) < 0 { return syscall.Errno(hr) } @@ -314,7 +315,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.(win.HWND) - args.Flags = 0x1 // BIF_RETURNONLYFSDIRS + args.Flags = win.BIF_RETURNONLYFSDIRS if opts.title != nil { args.Title = syscall.StringToUTF16Ptr(*opts.title) @@ -336,7 +337,7 @@ func browseForFolder(opts options) (string, []string, error) { if opts.ctx != nil && opts.ctx.Err() != nil { return "", nil, opts.ctx.Err() } - if ptr == 0 { + if ptr == nil { return "", nil, ErrCanceled } defer win.CoTaskMemFree(ptr) @@ -349,8 +350,8 @@ func browseForFolder(opts options) (string, []string, error) { } func browseForFolderCallback(wnd win.HWND, msg uint32, lparam, data uintptr) uintptr { - if msg == 1 { // BFFM_INITIALIZED - win.SendMessage(wnd, 1024+103 /* BFFM_SETSELECTIONW */, 1 /* TRUE */, data) + if msg == win.BFFM_INITIALIZED { + win.SendMessage(wnd, win.BFFM_SETSELECTION, 1, data) } return 0 } diff --git a/internal/win/comdlg32.go b/internal/win/comdlg32.go index 02e6344..2c74c9b 100644 --- a/internal/win/comdlg32.go +++ b/internal/win/comdlg32.go @@ -22,7 +22,7 @@ type CHOOSECOLOR struct { RgbResult uint32 CustColors *[16]uint32 Flags uint32 - CustData uintptr + CustData Pointer FnHook uintptr TemplateName *uint16 } @@ -58,7 +58,7 @@ type OPENFILENAME struct { FileOffset uint16 FileExtension uint16 DefExt *uint16 - CustData uintptr + CustData Pointer FnHook uintptr TemplateName *uint16 PvReserved uintptr diff --git a/internal/win/ole32.go b/internal/win/ole32.go index 7be6ded..e925e20 100644 --- a/internal/win/ole32.go +++ b/internal/win/ole32.go @@ -10,7 +10,19 @@ import ( ) const ( - RPC_E_CHANGED_MODE syscall.Errno = 0x80010106 + COINIT_MULTITHREADED = windows.COINIT_MULTITHREADED + COINIT_APARTMENTTHREADED = windows.COINIT_APARTMENTTHREADED + COINIT_DISABLE_OLE1DDE = windows.COINIT_DISABLE_OLE1DDE + COINIT_SPEED_OVER_MEMORY = windows.COINIT_SPEED_OVER_MEMORY + + CLSCTX_INPROC_SERVER = windows.CLSCTX_INPROC_SERVER + CLSCTX_INPROC_HANDLER = windows.CLSCTX_INPROC_HANDLER + CLSCTX_LOCAL_SERVER = windows.CLSCTX_LOCAL_SERVER + CLSCTX_REMOTE_SERVER = windows.CLSCTX_REMOTE_SERVER + CLSCTX_ALL = windows.CLSCTX_INPROC_SERVER | windows.CLSCTX_INPROC_HANDLER | windows.CLSCTX_LOCAL_SERVER | windows.CLSCTX_REMOTE_SERVER + + E_CANCELED = windows.ERROR_CANCELLED | windows.FACILITY_WIN32<<16 | 0x80000000 + RPC_E_CHANGED_MODE = syscall.Errno(windows.RPC_E_CHANGED_MODE) ) func CoInitializeEx(reserved uintptr, coInit uint32) error { @@ -19,6 +31,8 @@ func CoInitializeEx(reserved uintptr, coInit uint32) error { func CoUninitialize() { windows.CoUninitialize() } +func CoTaskMemFree(address unsafe.Pointer) { windows.CoTaskMemFree(address) } + // https://github.com/wine-mirror/wine/blob/master/include/unknwn.idl type IUnknownVtbl struct { @@ -43,5 +57,4 @@ func (o *COMObject) Call(trap uintptr, a ...uintptr) (r1, r2 uintptr, lastErr er } } -//sys CoTaskMemFree(address uintptr) = ole32.CoTaskMemFree //sys CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) = ole32.CoCreateInstance diff --git a/internal/win/shell32.go b/internal/win/shell32.go index fb00314..8f2bfca 100644 --- a/internal/win/shell32.go +++ b/internal/win/shell32.go @@ -3,6 +3,11 @@ package win const ( + BIF_RETURNONLYFSDIRS = 0x00000001 + + BFFM_INITIALIZED = 1 + BFFM_SETSELECTION = WM_USER + 103 + NIM_ADD = 0 NIM_DELETE = 2 ) @@ -10,7 +15,7 @@ const ( // https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-browseinfow type BROWSEINFO struct { Owner HWND - Root uintptr + Root Pointer DisplayName *uint16 Title *uint16 Flags uint32 @@ -52,7 +57,7 @@ type _IShellItemVtbl struct { Compare uintptr } -//sys SHBrowseForFolder(bi *BROWSEINFO) (ptr uintptr) = shell32.SHBrowseForFolder +//sys SHBrowseForFolder(bi *BROWSEINFO) (ptr unsafe.Pointer) = shell32.SHBrowseForFolder //sys SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (res error) = shell32.SHCreateItemFromParsingName -//sys SHGetPathFromIDListEx(ptr uintptr, path *uint16, pathLen int, opts int) (ok bool) = shell32.SHGetPathFromIDListEx +//sys SHGetPathFromIDListEx(ptr unsafe.Pointer, path *uint16, pathLen int, opts int) (ok bool) = shell32.SHGetPathFromIDListEx //sys ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error) = shell32.Shell_NotifyIconW diff --git a/internal/win/user32.go b/internal/win/user32.go index 748bb05..0e8adf2 100644 --- a/internal/win/user32.go +++ b/internal/win/user32.go @@ -2,7 +2,12 @@ package win -import "golang.org/x/sys/windows" +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) const ( IDOK = 1 @@ -49,6 +54,12 @@ const ( PBM_SETRANGE32 = WM_USER + 6 PBM_SETMARQUEE = WM_USER + 10 STM_SETICON = 0x0170 + + DPI_AWARENESS_CONTEXT_UNAWARE = ^uintptr(1) + 1 + DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = ^uintptr(2) + 1 + DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ^uintptr(3) + 1 + DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = ^uintptr(4) + 1 + DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED = ^uintptr(5) + 1 ) func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) { @@ -59,8 +70,61 @@ func GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) { return windows.GetWindowThreadProcessId(hwnd, pid) } +func SetThreadDpiAwarenessContext(dpiContext uintptr) (ret uintptr, err error) { + if err := procSetThreadDpiAwarenessContext.Find(); err != nil { + return 0, err + } + return setThreadDpiAwarenessContext(dpiContext), nil +} + +// https://docs.microsoft.com/en-us/windows/win32/winmsg/using-messages-and-message-queues +func MessageLoop(wnd HWND) error { + getMessage := procGetMessageW.Addr() + translateMessage := procTranslateMessage.Addr() + dispatchMessage := procDispatchMessageW.Addr() + isDialogMessage := procIsDialogMessageW.Addr() + + for { + var msg MSG + s, _, err := syscall.Syscall6(getMessage, 4, uintptr(unsafe.Pointer(&msg)), 0, 0, 0, 0, 0) + if int32(s) == -1 { + return err + } + if s == 0 { + return nil + } + + s, _, _ = syscall.Syscall(isDialogMessage, 2, uintptr(wnd), uintptr(unsafe.Pointer(&msg)), 0) + if s == 0 { + syscall.Syscall(translateMessage, 1, uintptr(unsafe.Pointer(&msg)), 0, 0) + syscall.Syscall(dispatchMessage, 1, uintptr(unsafe.Pointer(&msg)), 0, 0) + } + } +} + +// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msg +type MSG struct { + Owner syscall.Handle + Message uint32 + WParam uintptr + LParam uintptr + Time uint32 + Pt POINT +} + +// https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-point +type POINT struct { + x, y int32 +} + +//sys DispatchMessage(msg *MSG) (ret uintptr) = user32.DispatchMessageW +//sys EnumChildWindows(parent HWND, enumFunc uintptr, lparam unsafe.Pointer) = user32.EnumChildWindows +//sys EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) = user32.EnumChildWindows //sys GetDlgCtrlID(wnd HWND) (ret int) = user32.GetDlgCtrlID +//sys GetMessage(msg *MSG, wnd HWND, msgFilterMin uint32, msgFilterMax uint32) (ret uintptr) = user32.GetMessageW +//sys IsDialogMessage(wnd HWND, msg *MSG) (ok bool) = user32.IsDialogMessageW //sys SendMessage(wnd HWND, msg uint32, wparam uintptr, lparam uintptr) (ret uintptr) = user32.SendMessageW +//sys SetForegroundWindow(wnd HWND) (ok bool) = user32.SetForegroundWindow +//sys setThreadDpiAwarenessContext(dpiContext uintptr) (ret uintptr) = user32.SetThreadDpiAwarenessContext //sys SetWindowText(wnd HWND, text *uint16) (err error) = user32.SetWindowTextW -//sys EnumChildWindows(parent HWND, enumFunc uintptr, lparam uintptr) = user32.EnumChildWindows -//sys EnumWindows(enumFunc uintptr, lparam uintptr) (err error) = user32.EnumChildWindows +//sys TranslateMessage(msg *MSG) (ok bool) = user32.TranslateMessage diff --git a/internal/win/win32.go b/internal/win/win32.go index d989756..b290a33 100644 --- a/internal/win/win32.go +++ b/internal/win/win32.go @@ -7,5 +7,6 @@ import "golang.org/x/sys/windows" type Handle = windows.Handle type HWND = windows.HWND +type Pointer = windows.Pointer //sys RtlGetNtVersionNumbers(major *uint32, minor *uint32, build *uint32) = ntdll.RtlGetNtVersionNumbers diff --git a/internal/win/zsyscall_windows.go b/internal/win/zsyscall_windows.go index c18b38d..1fa8b07 100644 --- a/internal/win/zsyscall_windows.go +++ b/internal/win/zsyscall_windows.go @@ -48,28 +48,33 @@ var ( moduser32 = windows.NewLazySystemDLL("user32.dll") modwtsapi32 = windows.NewLazySystemDLL("wtsapi32.dll") - procInitCommonControlsEx = modcomctl32.NewProc("InitCommonControlsEx") - procChooseColorW = modcomdlg32.NewProc("ChooseColorW") - procCommDlgExtendedError = modcomdlg32.NewProc("CommDlgExtendedError") - procGetOpenFileNameW = modcomdlg32.NewProc("GetOpenFileNameW") - procGetSaveFileNameW = modcomdlg32.NewProc("GetSaveFileNameW") - procCreateFontIndirectW = modgdi32.NewProc("CreateFontIndirectW") - procDeleteObject = modgdi32.NewProc("DeleteObject") - procGetDeviceCaps = modgdi32.NewProc("GetDeviceCaps") - procGetConsoleWindow = modkernel32.NewProc("GetConsoleWindow") - procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW") - procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers") - procCoCreateInstance = modole32.NewProc("CoCreateInstance") - procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") - procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolder") - procSHCreateItemFromParsingName = modshell32.NewProc("SHCreateItemFromParsingName") - procSHGetPathFromIDListEx = modshell32.NewProc("SHGetPathFromIDListEx") - procShell_NotifyIconW = modshell32.NewProc("Shell_NotifyIconW") - procEnumChildWindows = moduser32.NewProc("EnumChildWindows") - procGetDlgCtrlID = moduser32.NewProc("GetDlgCtrlID") - procSendMessageW = moduser32.NewProc("SendMessageW") - procSetWindowTextW = moduser32.NewProc("SetWindowTextW") - procWTSSendMessageW = modwtsapi32.NewProc("WTSSendMessageW") + procInitCommonControlsEx = modcomctl32.NewProc("InitCommonControlsEx") + procChooseColorW = modcomdlg32.NewProc("ChooseColorW") + procCommDlgExtendedError = modcomdlg32.NewProc("CommDlgExtendedError") + procGetOpenFileNameW = modcomdlg32.NewProc("GetOpenFileNameW") + procGetSaveFileNameW = modcomdlg32.NewProc("GetSaveFileNameW") + procCreateFontIndirectW = modgdi32.NewProc("CreateFontIndirectW") + procDeleteObject = modgdi32.NewProc("DeleteObject") + procGetDeviceCaps = modgdi32.NewProc("GetDeviceCaps") + procGetConsoleWindow = modkernel32.NewProc("GetConsoleWindow") + procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW") + procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers") + procCoCreateInstance = modole32.NewProc("CoCreateInstance") + procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolder") + procSHCreateItemFromParsingName = modshell32.NewProc("SHCreateItemFromParsingName") + procSHGetPathFromIDListEx = modshell32.NewProc("SHGetPathFromIDListEx") + procShell_NotifyIconW = modshell32.NewProc("Shell_NotifyIconW") + procDispatchMessageW = moduser32.NewProc("DispatchMessageW") + procEnumChildWindows = moduser32.NewProc("EnumChildWindows") + procGetDlgCtrlID = moduser32.NewProc("GetDlgCtrlID") + procGetMessageW = moduser32.NewProc("GetMessageW") + procIsDialogMessageW = moduser32.NewProc("IsDialogMessageW") + procSendMessageW = moduser32.NewProc("SendMessageW") + procSetForegroundWindow = moduser32.NewProc("SetForegroundWindow") + procSetThreadDpiAwarenessContext = moduser32.NewProc("SetThreadDpiAwarenessContext") + procSetWindowTextW = moduser32.NewProc("SetWindowTextW") + procTranslateMessage = moduser32.NewProc("TranslateMessage") + procWTSSendMessageW = modwtsapi32.NewProc("WTSSendMessageW") ) func InitCommonControlsEx(icc *INITCOMMONCONTROLSEX) (ok bool) { @@ -148,14 +153,9 @@ func CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, return } -func CoTaskMemFree(address uintptr) { - syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(address), 0, 0) - return -} - -func SHBrowseForFolder(bi *BROWSEINFO) (ptr uintptr) { +func SHBrowseForFolder(bi *BROWSEINFO) (ptr unsafe.Pointer) { r0, _, _ := syscall.Syscall(procSHBrowseForFolder.Addr(), 1, uintptr(unsafe.Pointer(bi)), 0, 0) - ptr = uintptr(r0) + ptr = unsafe.Pointer(r0) return } @@ -167,7 +167,7 @@ func SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, i return } -func SHGetPathFromIDListEx(ptr uintptr, path *uint16, pathLen int, opts int) (ok bool) { +func SHGetPathFromIDListEx(ptr unsafe.Pointer, path *uint16, pathLen int, opts int) (ok bool) { r0, _, _ := syscall.Syscall6(procSHGetPathFromIDListEx.Addr(), 4, uintptr(ptr), uintptr(unsafe.Pointer(path)), uintptr(pathLen), uintptr(opts), 0, 0) ok = r0 != 0 return @@ -182,12 +182,18 @@ func ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error) return } -func EnumChildWindows(parent HWND, enumFunc uintptr, lparam uintptr) { +func DispatchMessage(msg *MSG) (ret uintptr) { + r0, _, _ := syscall.Syscall(procDispatchMessageW.Addr(), 1, uintptr(unsafe.Pointer(msg)), 0, 0) + ret = uintptr(r0) + return +} + +func EnumChildWindows(parent HWND, enumFunc uintptr, lparam unsafe.Pointer) { syscall.Syscall(procEnumChildWindows.Addr(), 3, uintptr(parent), uintptr(enumFunc), uintptr(lparam)) return } -func EnumWindows(enumFunc uintptr, lparam uintptr) (err error) { +func EnumWindows(enumFunc uintptr, lparam unsafe.Pointer) (err error) { r1, _, e1 := syscall.Syscall(procEnumChildWindows.Addr(), 2, uintptr(enumFunc), uintptr(lparam), 0) if r1 == 0 { err = errnoErr(e1) @@ -201,12 +207,36 @@ func GetDlgCtrlID(wnd HWND) (ret int) { return } +func GetMessage(msg *MSG, wnd HWND, msgFilterMin uint32, msgFilterMax uint32) (ret uintptr) { + r0, _, _ := syscall.Syscall6(procGetMessageW.Addr(), 4, uintptr(unsafe.Pointer(msg)), uintptr(wnd), uintptr(msgFilterMin), uintptr(msgFilterMax), 0, 0) + ret = uintptr(r0) + return +} + +func IsDialogMessage(wnd HWND, msg *MSG) (ok bool) { + r0, _, _ := syscall.Syscall(procIsDialogMessageW.Addr(), 2, uintptr(wnd), uintptr(unsafe.Pointer(msg)), 0) + ok = r0 != 0 + return +} + func SendMessage(wnd HWND, msg uint32, wparam uintptr, lparam uintptr) (ret uintptr) { r0, _, _ := syscall.Syscall6(procSendMessageW.Addr(), 4, uintptr(wnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0) ret = uintptr(r0) return } +func SetForegroundWindow(wnd HWND) (ok bool) { + r0, _, _ := syscall.Syscall(procSetForegroundWindow.Addr(), 1, uintptr(wnd), 0, 0) + ok = r0 != 0 + return +} + +func setThreadDpiAwarenessContext(dpiContext uintptr) (ret uintptr) { + r0, _, _ := syscall.Syscall(procSetThreadDpiAwarenessContext.Addr(), 1, uintptr(dpiContext), 0, 0) + ret = uintptr(r0) + return +} + func SetWindowText(wnd HWND, text *uint16) (err error) { r1, _, e1 := syscall.Syscall(procSetWindowTextW.Addr(), 2, uintptr(wnd), uintptr(unsafe.Pointer(text)), 0) if r1 == 0 { @@ -215,6 +245,12 @@ func SetWindowText(wnd HWND, text *uint16) (err error) { return } +func TranslateMessage(msg *MSG) (ok bool) { + r0, _, _ := syscall.Syscall(procTranslateMessage.Addr(), 1, uintptr(unsafe.Pointer(msg)), 0, 0) + ok = r0 != 0 + return +} + func WTSSendMessage(server Handle, sessionID uint32, title *uint16, titleLength int, message *uint16, messageLength int, style uint32, timeout int, response *uint32, wait bool) (err error) { var _p0 uint32 if wait { diff --git a/list_windows.go b/list_windows.go index e5c5b36..df18879 100644 --- a/list_windows.go +++ b/list_windows.go @@ -131,7 +131,7 @@ func (dlg *listDialog) setup(text string, opts options) ([]string, error) { }() } - if err := messageLoop(dlg.wnd); err != nil { + if err := win.MessageLoop(win.HWND(dlg.wnd)); err != nil { return nil, err } if opts.ctx != nil && opts.ctx.Err() != nil { diff --git a/msg_windows.go b/msg_windows.go index cb9101a..5e7c62f 100644 --- a/msg_windows.go +++ b/msg_windows.go @@ -90,7 +90,7 @@ func message(kind messageKind, text string, opts options) error { func hookMessageDialog(opts options) (unhook context.CancelFunc, err error) { return hookDialog(opts.ctx, opts.windowIcon, nil, func(wnd win.HWND) { win.EnumChildWindows(wnd, syscall.NewCallback(hookMessageDialogCallback), - uintptr(unsafe.Pointer(&opts))) + unsafe.Pointer(&opts)) }) } diff --git a/progress_windows.go b/progress_windows.go index 0d021d7..fba9651 100644 --- a/progress_windows.go +++ b/progress_windows.go @@ -197,7 +197,7 @@ func (dlg *progressDialog) setup(opts options) error { }() } - if err := messageLoop(dlg.wnd); err != nil { + if err := win.MessageLoop(win.HWND(dlg.wnd)); err != nil { return err } if opts.ctx != nil && opts.ctx.Err() != nil { diff --git a/pwd_windows.go b/pwd_windows.go index 9bd79d1..b96ee79 100644 --- a/pwd_windows.go +++ b/pwd_windows.go @@ -128,7 +128,7 @@ func (dlg *passwordDialog) setup(opts options) (string, string, error) { }() } - if err := messageLoop(dlg.wnd); err != nil { + if err := win.MessageLoop(win.HWND(dlg.wnd)); err != nil { return "", "", err } if opts.ctx != nil && opts.ctx.Err() != nil { diff --git a/util_windows.go b/util_windows.go index 1a66f3a..7c44672 100644 --- a/util_windows.go +++ b/util_windows.go @@ -25,40 +25,34 @@ var ( deactivateActCtx = kernel32.NewProc("DeactivateActCtx") getModuleHandle = kernel32.NewProc("GetModuleHandleW") - callNextHookEx = user32.NewProc("CallNextHookEx") - createIconFromResource = user32.NewProc("CreateIconFromResource") - createWindowEx = user32.NewProc("CreateWindowExW") - defWindowProc = user32.NewProc("DefWindowProcW") - destroyIcon = user32.NewProc("DestroyIcon") - destroyWindow = user32.NewProc("DestroyWindow") - dispatchMessage = user32.NewProc("DispatchMessageW") - enableWindow = user32.NewProc("EnableWindow") - getDpiForWindow = user32.NewProc("GetDpiForWindow") - getMessage = user32.NewProc("GetMessageW") - getSystemMetrics = user32.NewProc("GetSystemMetrics") - getWindowDC = user32.NewProc("GetWindowDC") - getWindowRect = user32.NewProc("GetWindowRect") - getWindowText = user32.NewProc("GetWindowTextW") - getWindowTextLength = user32.NewProc("GetWindowTextLengthW") - isDialogMessage = user32.NewProc("IsDialogMessageW") - loadIcon = user32.NewProc("LoadIconW") - loadImage = user32.NewProc("LoadImageW") - postQuitMessage = user32.NewProc("PostQuitMessage") - registerClassEx = user32.NewProc("RegisterClassExW") - releaseDC = user32.NewProc("ReleaseDC") - sendMessage = user32.NewProc("SendMessageW") - setFocus = user32.NewProc("SetFocus") - setForegroundWindow = user32.NewProc("SetForegroundWindow") - setThreadDpiAwarenessContext = user32.NewProc("SetThreadDpiAwarenessContext") - setWindowLong = user32.NewProc("SetWindowLongW") - setWindowPos = user32.NewProc("SetWindowPos") - setWindowsHookEx = user32.NewProc("SetWindowsHookExW") - setWindowText = user32.NewProc("SetWindowTextW") - showWindow = user32.NewProc("ShowWindow") - systemParametersInfo = user32.NewProc("SystemParametersInfoW") - translateMessage = user32.NewProc("TranslateMessage") - unhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx") - unregisterClass = user32.NewProc("UnregisterClassW") + callNextHookEx = user32.NewProc("CallNextHookEx") + createIconFromResource = user32.NewProc("CreateIconFromResource") + createWindowEx = user32.NewProc("CreateWindowExW") + defWindowProc = user32.NewProc("DefWindowProcW") + destroyIcon = user32.NewProc("DestroyIcon") + destroyWindow = user32.NewProc("DestroyWindow") + enableWindow = user32.NewProc("EnableWindow") + getDpiForWindow = user32.NewProc("GetDpiForWindow") + getSystemMetrics = user32.NewProc("GetSystemMetrics") + getWindowDC = user32.NewProc("GetWindowDC") + getWindowRect = user32.NewProc("GetWindowRect") + getWindowText = user32.NewProc("GetWindowTextW") + getWindowTextLength = user32.NewProc("GetWindowTextLengthW") + loadIcon = user32.NewProc("LoadIconW") + loadImage = user32.NewProc("LoadImageW") + postQuitMessage = user32.NewProc("PostQuitMessage") + registerClassEx = user32.NewProc("RegisterClassExW") + releaseDC = user32.NewProc("ReleaseDC") + sendMessage = user32.NewProc("SendMessageW") + setFocus = user32.NewProc("SetFocus") + setWindowLong = user32.NewProc("SetWindowLongW") + setWindowPos = user32.NewProc("SetWindowPos") + setWindowsHookEx = user32.NewProc("SetWindowsHookExW") + setWindowText = user32.NewProc("SetWindowTextW") + showWindow = user32.NewProc("ShowWindow") + systemParametersInfo = user32.NewProc("SystemParametersInfoW") + unhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx") + unregisterClass = user32.NewProc("UnregisterClassW") ) func intptr(i int64) uintptr { @@ -73,28 +67,23 @@ func hwnd(i uint64) win.HWND { return win.HWND(uintptr(i)) } func setup() context.CancelFunc { var wnd win.HWND - win.EnumWindows(syscall.NewCallback(setupEnumCallback), uintptr(unsafe.Pointer(&wnd))) + win.EnumWindows(syscall.NewCallback(setupEnumCallback), unsafe.Pointer(&wnd)) if wnd == 0 { wnd = win.GetConsoleWindow() } if wnd != 0 { - setForegroundWindow.Call(uintptr(wnd)) + win.SetForegroundWindow(wnd) } runtime.LockOSThread() var restore uintptr cookie := enableVisualStyles() - if setThreadDpiAwarenessContext.Find() == nil { - // try: - // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 - // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE - // DPI_AWARENESS_CONTEXT_SYSTEM_AWARE - for i := -4; i <= -2; i++ { - restore, _, _ = setThreadDpiAwarenessContext.Call(uintptr(i)) - if restore != 0 { - break - } + for dpi := win.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2; dpi <= win.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE; dpi++ { + var err error + restore, err = win.SetThreadDpiAwarenessContext(dpi) + if restore != 0 || err != nil { + break } } @@ -105,7 +94,7 @@ func setup() context.CancelFunc { return func() { if restore != 0 { - setThreadDpiAwarenessContext.Call(restore) + win.SetThreadDpiAwarenessContext(restore) } if cookie != 0 { deactivateActCtx.Call(0, cookie) @@ -391,31 +380,6 @@ func registerClass(instance, icon, proc uintptr) (uintptr, error) { return atom, err } -// https://docs.microsoft.com/en-us/windows/win32/winmsg/using-messages-and-message-queues -func messageLoop(wnd uintptr) error { - getMessage := getMessage.Addr() - isDialogMessage := isDialogMessage.Addr() - translateMessage := translateMessage.Addr() - dispatchMessage := dispatchMessage.Addr() - - for { - var msg _MSG - s, _, err := syscall.Syscall6(getMessage, 4, uintptr(unsafe.Pointer(&msg)), 0, 0, 0, 0, 0) - if int32(s) == -1 { - return err - } - if s == 0 { - return nil - } - - s, _, _ = syscall.Syscall(isDialogMessage, 2, wnd, uintptr(unsafe.Pointer(&msg)), 0) - if s == 0 { - syscall.Syscall(translateMessage, 1, uintptr(unsafe.Pointer(&msg)), 0, 0) - syscall.Syscall(dispatchMessage, 1, uintptr(unsafe.Pointer(&msg)), 0, 0) - } - } -} - // https://stackoverflow.com/questions/4308503/how-to-enable-visual-styles-without-a-manifest func enableVisualStyles() (cookie uintptr) { dir, err := win.GetSystemDirectory() @@ -477,21 +441,6 @@ type _NONCLIENTMETRICS struct { MessageFont win.LOGFONT } -// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msg -type _MSG struct { - Owner syscall.Handle - Message uint32 - WParam uintptr - LParam uintptr - Time uint32 - Pt _POINT -} - -// https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-point -type _POINT struct { - x, y int32 -} - // https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect type _RECT struct { left int32