Refactor (windows).

This commit is contained in:
Nuno Cruces 2022-06-20 02:14:08 +01:00
parent 4bfddad741
commit b273c0992b
14 changed files with 214 additions and 145 deletions

View file

@ -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 return time.Time{}, err
} }
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {

View file

@ -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 return "", err
} }
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {

View file

@ -17,6 +17,8 @@ const (
_FOS_FORCEFILESYSTEM = 0x00000040 _FOS_FORCEFILESYSTEM = 0x00000040
_FOS_ALLOWMULTISELECT = 0x00000200 _FOS_ALLOWMULTISELECT = 0x00000200
_FOS_FORCESHOWHIDDEN = 0x10000000 _FOS_FORCESHOWHIDDEN = 0x10000000
_SIGDN_FILESYSPATH = 0x80058000
) )
func selectFile(opts options) (string, error) { 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) { func pickFolders(opts options, multi bool) (str string, lst []string, err error) {
defer setup()() 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 != win.RPC_E_CHANGED_MODE {
if err != nil { if err != nil {
return "", nil, err return "", nil, err
@ -201,7 +203,7 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
var dialog *_IFileOpenDialog var dialog *_IFileOpenDialog
err = win.CoCreateInstance( err = win.CoCreateInstance(
_CLSID_FileOpenDialog, nil, 0x17, // CLSCTX_ALL _CLSID_FileOpenDialog, nil, win.CLSCTX_ALL,
_IID_IFileOpenDialog, unsafe.Pointer(&dialog)) _IID_IFileOpenDialog, unsafe.Pointer(&dialog))
if err != nil { if err != nil {
if multi { 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 { if opts.ctx != nil && opts.ctx.Err() != nil {
return "", nil, opts.ctx.Err() return "", nil, opts.ctx.Err()
} }
if hr == 0x800704c7 { // ERROR_CANCELLED if hr == uintptr(win.E_CANCELED) {
return "", nil, ErrCanceled return "", nil, ErrCanceled
} }
if int32(hr) < 0 { 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) defer item.Call(item.Release)
var ptr uintptr var ptr unsafe.Pointer
hr, _, _ = item.Call(item.GetDisplayName, hr, _, _ = item.Call(item.GetDisplayName,
0x80058000, // SIGDN_FILESYSPATH _SIGDN_FILESYSPATH, uintptr(unsafe.Pointer(&ptr)))
uintptr(unsafe.Pointer(&ptr)))
if int32(hr) < 0 { if int32(hr) < 0 {
return syscall.Errno(hr) 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) { func browseForFolder(opts options) (string, []string, error) {
var args win.BROWSEINFO var args win.BROWSEINFO
args.Owner, _ = opts.attach.(win.HWND) args.Owner, _ = opts.attach.(win.HWND)
args.Flags = 0x1 // BIF_RETURNONLYFSDIRS args.Flags = win.BIF_RETURNONLYFSDIRS
if opts.title != nil { if opts.title != nil {
args.Title = syscall.StringToUTF16Ptr(*opts.title) 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 { if opts.ctx != nil && opts.ctx.Err() != nil {
return "", nil, opts.ctx.Err() return "", nil, opts.ctx.Err()
} }
if ptr == 0 { if ptr == nil {
return "", nil, ErrCanceled return "", nil, ErrCanceled
} }
defer win.CoTaskMemFree(ptr) 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 { func browseForFolderCallback(wnd win.HWND, msg uint32, lparam, data uintptr) uintptr {
if msg == 1 { // BFFM_INITIALIZED if msg == win.BFFM_INITIALIZED {
win.SendMessage(wnd, 1024+103 /* BFFM_SETSELECTIONW */, 1 /* TRUE */, data) win.SendMessage(wnd, win.BFFM_SETSELECTION, 1, data)
} }
return 0 return 0
} }

View file

@ -22,7 +22,7 @@ type CHOOSECOLOR struct {
RgbResult uint32 RgbResult uint32
CustColors *[16]uint32 CustColors *[16]uint32
Flags uint32 Flags uint32
CustData uintptr CustData Pointer
FnHook uintptr FnHook uintptr
TemplateName *uint16 TemplateName *uint16
} }
@ -58,7 +58,7 @@ type OPENFILENAME struct {
FileOffset uint16 FileOffset uint16
FileExtension uint16 FileExtension uint16
DefExt *uint16 DefExt *uint16
CustData uintptr CustData Pointer
FnHook uintptr FnHook uintptr
TemplateName *uint16 TemplateName *uint16
PvReserved uintptr PvReserved uintptr

View file

@ -10,7 +10,19 @@ import (
) )
const ( 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 { func CoInitializeEx(reserved uintptr, coInit uint32) error {
@ -19,6 +31,8 @@ func CoInitializeEx(reserved uintptr, coInit uint32) error {
func CoUninitialize() { windows.CoUninitialize() } func CoUninitialize() { windows.CoUninitialize() }
func CoTaskMemFree(address unsafe.Pointer) { windows.CoTaskMemFree(address) }
// 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 {
@ -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 //sys CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) = ole32.CoCreateInstance

View file

@ -3,6 +3,11 @@
package win package win
const ( const (
BIF_RETURNONLYFSDIRS = 0x00000001
BFFM_INITIALIZED = 1
BFFM_SETSELECTION = WM_USER + 103
NIM_ADD = 0 NIM_ADD = 0
NIM_DELETE = 2 NIM_DELETE = 2
) )
@ -10,7 +15,7 @@ const (
// https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-browseinfow // https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-browseinfow
type BROWSEINFO struct { type BROWSEINFO struct {
Owner HWND Owner HWND
Root uintptr Root Pointer
DisplayName *uint16 DisplayName *uint16
Title *uint16 Title *uint16
Flags uint32 Flags uint32
@ -52,7 +57,7 @@ type _IShellItemVtbl struct {
Compare uintptr 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 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 //sys ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error) = shell32.Shell_NotifyIconW

View file

@ -2,7 +2,12 @@
package win package win
import "golang.org/x/sys/windows" import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
const ( const (
IDOK = 1 IDOK = 1
@ -49,6 +54,12 @@ const (
PBM_SETRANGE32 = WM_USER + 6 PBM_SETRANGE32 = WM_USER + 6
PBM_SETMARQUEE = WM_USER + 10 PBM_SETMARQUEE = WM_USER + 10
STM_SETICON = 0x0170 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) { 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) 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 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 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 SetWindowText(wnd HWND, text *uint16) (err error) = user32.SetWindowTextW
//sys EnumChildWindows(parent HWND, enumFunc uintptr, lparam uintptr) = user32.EnumChildWindows //sys TranslateMessage(msg *MSG) (ok bool) = user32.TranslateMessage
//sys EnumWindows(enumFunc uintptr, lparam uintptr) (err error) = user32.EnumChildWindows

View file

@ -7,5 +7,6 @@ import "golang.org/x/sys/windows"
type Handle = windows.Handle type Handle = windows.Handle
type HWND = windows.HWND type HWND = windows.HWND
type Pointer = windows.Pointer
//sys RtlGetNtVersionNumbers(major *uint32, minor *uint32, build *uint32) = ntdll.RtlGetNtVersionNumbers //sys RtlGetNtVersionNumbers(major *uint32, minor *uint32, build *uint32) = ntdll.RtlGetNtVersionNumbers

View file

@ -60,15 +60,20 @@ var (
procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW") procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW")
procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers") procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers")
procCoCreateInstance = modole32.NewProc("CoCreateInstance") procCoCreateInstance = modole32.NewProc("CoCreateInstance")
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolder") procSHBrowseForFolder = modshell32.NewProc("SHBrowseForFolder")
procSHCreateItemFromParsingName = modshell32.NewProc("SHCreateItemFromParsingName") procSHCreateItemFromParsingName = modshell32.NewProc("SHCreateItemFromParsingName")
procSHGetPathFromIDListEx = modshell32.NewProc("SHGetPathFromIDListEx") procSHGetPathFromIDListEx = modshell32.NewProc("SHGetPathFromIDListEx")
procShell_NotifyIconW = modshell32.NewProc("Shell_NotifyIconW") procShell_NotifyIconW = modshell32.NewProc("Shell_NotifyIconW")
procDispatchMessageW = moduser32.NewProc("DispatchMessageW")
procEnumChildWindows = moduser32.NewProc("EnumChildWindows") procEnumChildWindows = moduser32.NewProc("EnumChildWindows")
procGetDlgCtrlID = moduser32.NewProc("GetDlgCtrlID") procGetDlgCtrlID = moduser32.NewProc("GetDlgCtrlID")
procGetMessageW = moduser32.NewProc("GetMessageW")
procIsDialogMessageW = moduser32.NewProc("IsDialogMessageW")
procSendMessageW = moduser32.NewProc("SendMessageW") procSendMessageW = moduser32.NewProc("SendMessageW")
procSetForegroundWindow = moduser32.NewProc("SetForegroundWindow")
procSetThreadDpiAwarenessContext = moduser32.NewProc("SetThreadDpiAwarenessContext")
procSetWindowTextW = moduser32.NewProc("SetWindowTextW") procSetWindowTextW = moduser32.NewProc("SetWindowTextW")
procTranslateMessage = moduser32.NewProc("TranslateMessage")
procWTSSendMessageW = modwtsapi32.NewProc("WTSSendMessageW") procWTSSendMessageW = modwtsapi32.NewProc("WTSSendMessageW")
) )
@ -148,14 +153,9 @@ func CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32,
return return
} }
func CoTaskMemFree(address uintptr) { func SHBrowseForFolder(bi *BROWSEINFO) (ptr unsafe.Pointer) {
syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(address), 0, 0)
return
}
func SHBrowseForFolder(bi *BROWSEINFO) (ptr uintptr) {
r0, _, _ := syscall.Syscall(procSHBrowseForFolder.Addr(), 1, uintptr(unsafe.Pointer(bi)), 0, 0) r0, _, _ := syscall.Syscall(procSHBrowseForFolder.Addr(), 1, uintptr(unsafe.Pointer(bi)), 0, 0)
ptr = uintptr(r0) ptr = unsafe.Pointer(r0)
return return
} }
@ -167,7 +167,7 @@ func SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, i
return 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) r0, _, _ := syscall.Syscall6(procSHGetPathFromIDListEx.Addr(), 4, uintptr(ptr), uintptr(unsafe.Pointer(path)), uintptr(pathLen), uintptr(opts), 0, 0)
ok = r0 != 0 ok = r0 != 0
return return
@ -182,12 +182,18 @@ func ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error)
return 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)) syscall.Syscall(procEnumChildWindows.Addr(), 3, uintptr(parent), uintptr(enumFunc), uintptr(lparam))
return 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) r1, _, e1 := syscall.Syscall(procEnumChildWindows.Addr(), 2, uintptr(enumFunc), uintptr(lparam), 0)
if r1 == 0 { if r1 == 0 {
err = errnoErr(e1) err = errnoErr(e1)
@ -201,12 +207,36 @@ func GetDlgCtrlID(wnd HWND) (ret int) {
return 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) { 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) r0, _, _ := syscall.Syscall6(procSendMessageW.Addr(), 4, uintptr(wnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
ret = uintptr(r0) ret = uintptr(r0)
return 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) { func SetWindowText(wnd HWND, text *uint16) (err error) {
r1, _, e1 := syscall.Syscall(procSetWindowTextW.Addr(), 2, uintptr(wnd), uintptr(unsafe.Pointer(text)), 0) r1, _, e1 := syscall.Syscall(procSetWindowTextW.Addr(), 2, uintptr(wnd), uintptr(unsafe.Pointer(text)), 0)
if r1 == 0 { if r1 == 0 {
@ -215,6 +245,12 @@ func SetWindowText(wnd HWND, text *uint16) (err error) {
return 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) { 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 var _p0 uint32
if wait { if wait {

View file

@ -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 return nil, err
} }
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {

View file

@ -90,7 +90,7 @@ func message(kind messageKind, text string, opts options) error {
func hookMessageDialog(opts options) (unhook context.CancelFunc, err error) { func hookMessageDialog(opts options) (unhook context.CancelFunc, err error) {
return hookDialog(opts.ctx, opts.windowIcon, nil, func(wnd win.HWND) { return hookDialog(opts.ctx, opts.windowIcon, nil, func(wnd win.HWND) {
win.EnumChildWindows(wnd, syscall.NewCallback(hookMessageDialogCallback), win.EnumChildWindows(wnd, syscall.NewCallback(hookMessageDialogCallback),
uintptr(unsafe.Pointer(&opts))) unsafe.Pointer(&opts))
}) })
} }

View file

@ -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 return err
} }
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {

View file

@ -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 return "", "", err
} }
if opts.ctx != nil && opts.ctx.Err() != nil { if opts.ctx != nil && opts.ctx.Err() != nil {

View file

@ -31,16 +31,13 @@ var (
defWindowProc = user32.NewProc("DefWindowProcW") defWindowProc = user32.NewProc("DefWindowProcW")
destroyIcon = user32.NewProc("DestroyIcon") destroyIcon = user32.NewProc("DestroyIcon")
destroyWindow = user32.NewProc("DestroyWindow") destroyWindow = user32.NewProc("DestroyWindow")
dispatchMessage = user32.NewProc("DispatchMessageW")
enableWindow = user32.NewProc("EnableWindow") enableWindow = user32.NewProc("EnableWindow")
getDpiForWindow = user32.NewProc("GetDpiForWindow") getDpiForWindow = user32.NewProc("GetDpiForWindow")
getMessage = user32.NewProc("GetMessageW")
getSystemMetrics = user32.NewProc("GetSystemMetrics") getSystemMetrics = user32.NewProc("GetSystemMetrics")
getWindowDC = user32.NewProc("GetWindowDC") getWindowDC = user32.NewProc("GetWindowDC")
getWindowRect = user32.NewProc("GetWindowRect") getWindowRect = user32.NewProc("GetWindowRect")
getWindowText = user32.NewProc("GetWindowTextW") getWindowText = user32.NewProc("GetWindowTextW")
getWindowTextLength = user32.NewProc("GetWindowTextLengthW") getWindowTextLength = user32.NewProc("GetWindowTextLengthW")
isDialogMessage = user32.NewProc("IsDialogMessageW")
loadIcon = user32.NewProc("LoadIconW") loadIcon = user32.NewProc("LoadIconW")
loadImage = user32.NewProc("LoadImageW") loadImage = user32.NewProc("LoadImageW")
postQuitMessage = user32.NewProc("PostQuitMessage") postQuitMessage = user32.NewProc("PostQuitMessage")
@ -48,15 +45,12 @@ var (
releaseDC = user32.NewProc("ReleaseDC") releaseDC = user32.NewProc("ReleaseDC")
sendMessage = user32.NewProc("SendMessageW") sendMessage = user32.NewProc("SendMessageW")
setFocus = user32.NewProc("SetFocus") setFocus = user32.NewProc("SetFocus")
setForegroundWindow = user32.NewProc("SetForegroundWindow")
setThreadDpiAwarenessContext = user32.NewProc("SetThreadDpiAwarenessContext")
setWindowLong = user32.NewProc("SetWindowLongW") setWindowLong = user32.NewProc("SetWindowLongW")
setWindowPos = user32.NewProc("SetWindowPos") setWindowPos = user32.NewProc("SetWindowPos")
setWindowsHookEx = user32.NewProc("SetWindowsHookExW") setWindowsHookEx = user32.NewProc("SetWindowsHookExW")
setWindowText = user32.NewProc("SetWindowTextW") setWindowText = user32.NewProc("SetWindowTextW")
showWindow = user32.NewProc("ShowWindow") showWindow = user32.NewProc("ShowWindow")
systemParametersInfo = user32.NewProc("SystemParametersInfoW") systemParametersInfo = user32.NewProc("SystemParametersInfoW")
translateMessage = user32.NewProc("TranslateMessage")
unhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx") unhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx")
unregisterClass = user32.NewProc("UnregisterClassW") unregisterClass = user32.NewProc("UnregisterClassW")
) )
@ -73,30 +67,25 @@ func hwnd(i uint64) win.HWND { return win.HWND(uintptr(i)) }
func setup() context.CancelFunc { func setup() context.CancelFunc {
var wnd win.HWND var wnd win.HWND
win.EnumWindows(syscall.NewCallback(setupEnumCallback), uintptr(unsafe.Pointer(&wnd))) win.EnumWindows(syscall.NewCallback(setupEnumCallback), unsafe.Pointer(&wnd))
if wnd == 0 { if wnd == 0 {
wnd = win.GetConsoleWindow() wnd = win.GetConsoleWindow()
} }
if wnd != 0 { if wnd != 0 {
setForegroundWindow.Call(uintptr(wnd)) win.SetForegroundWindow(wnd)
} }
runtime.LockOSThread() runtime.LockOSThread()
var restore uintptr var restore uintptr
cookie := enableVisualStyles() cookie := enableVisualStyles()
if setThreadDpiAwarenessContext.Find() == nil { for dpi := win.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2; dpi <= win.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE; dpi++ {
// try: var err error
// DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 restore, err = win.SetThreadDpiAwarenessContext(dpi)
// DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE if restore != 0 || err != nil {
// DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
for i := -4; i <= -2; i++ {
restore, _, _ = setThreadDpiAwarenessContext.Call(uintptr(i))
if restore != 0 {
break break
} }
} }
}
var icc win.INITCOMMONCONTROLSEX var icc win.INITCOMMONCONTROLSEX
icc.Size = uint32(unsafe.Sizeof(icc)) icc.Size = uint32(unsafe.Sizeof(icc))
@ -105,7 +94,7 @@ func setup() context.CancelFunc {
return func() { return func() {
if restore != 0 { if restore != 0 {
setThreadDpiAwarenessContext.Call(restore) win.SetThreadDpiAwarenessContext(restore)
} }
if cookie != 0 { if cookie != 0 {
deactivateActCtx.Call(0, cookie) deactivateActCtx.Call(0, cookie)
@ -391,31 +380,6 @@ func registerClass(instance, icon, proc uintptr) (uintptr, error) {
return atom, err 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 // https://stackoverflow.com/questions/4308503/how-to-enable-visual-styles-without-a-manifest
func enableVisualStyles() (cookie uintptr) { func enableVisualStyles() (cookie uintptr) {
dir, err := win.GetSystemDirectory() dir, err := win.GetSystemDirectory()
@ -477,21 +441,6 @@ type _NONCLIENTMETRICS struct {
MessageFont win.LOGFONT 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 // https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-rect
type _RECT struct { type _RECT struct {
left int32 left int32