Refactor (windows).
This commit is contained in:
parent
4bfddad741
commit
b273c0992b
14 changed files with 214 additions and 145 deletions
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
123
util_windows.go
123
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
|
||||
|
|
Loading…
Reference in a new issue