Refactor (windows).
This commit is contained in:
parent
176a3d48a1
commit
d33a18d05a
13 changed files with 403 additions and 220 deletions
|
@ -1,6 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
cd "${BASH_SOURCE%/*}"
|
||||
|
||||
go generate ../../...
|
||||
|
||||
TAG=$(git tag --points-at HEAD)
|
||||
echo 'package main; const tag = "'$TAG'"' > tag.go
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ import (
|
|||
"image/color"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
)
|
||||
|
||||
var (
|
||||
chooseColor = comdlg32.NewProc("ChooseColorW")
|
||||
|
||||
savedColors [16]uint32
|
||||
colorsMutex sync.Mutex
|
||||
)
|
||||
|
@ -19,32 +19,26 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
const (
|
||||
_CC_RGBINIT = 0x00000001
|
||||
_CC_FULLOPEN = 0x00000002
|
||||
_CC_PREVENTFULLOPEN = 0x00000004
|
||||
)
|
||||
|
||||
func selectColor(opts options) (color.Color, error) {
|
||||
// load custom colors
|
||||
colorsMutex.Lock()
|
||||
customColors := savedColors
|
||||
colorsMutex.Unlock()
|
||||
|
||||
var args _CHOOSECOLOR
|
||||
var args win.CHOOSECOLOR
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
args.Owner, _ = opts.attach.(uintptr)
|
||||
args.CustColors = &customColors
|
||||
|
||||
if opts.color != nil {
|
||||
args.Flags |= _CC_RGBINIT
|
||||
args.Flags |= win.CC_RGBINIT
|
||||
n := color.NRGBAModel.Convert(opts.color).(color.NRGBA)
|
||||
args.RgbResult = uint32(n.R) | uint32(n.G)<<8 | uint32(n.B)<<16
|
||||
}
|
||||
if opts.showPalette {
|
||||
args.Flags |= _CC_PREVENTFULLOPEN
|
||||
args.Flags |= win.CC_PREVENTFULLOPEN
|
||||
} else {
|
||||
args.Flags |= _CC_FULLOPEN
|
||||
args.Flags |= win.CC_FULLOPEN
|
||||
}
|
||||
|
||||
defer setup()()
|
||||
|
@ -57,12 +51,12 @@ func selectColor(opts options) (color.Color, error) {
|
|||
defer unhook()
|
||||
}
|
||||
|
||||
s, _, _ := chooseColor.Call(uintptr(unsafe.Pointer(&args)))
|
||||
ok := win.ChooseColor(&args)
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return nil, opts.ctx.Err()
|
||||
}
|
||||
if s == 0 {
|
||||
return nil, commDlgError()
|
||||
if !ok {
|
||||
return nil, win.CommDlgError()
|
||||
}
|
||||
|
||||
// save custom colors back
|
||||
|
@ -75,16 +69,3 @@ func selectColor(opts options) (color.Color, error) {
|
|||
b := uint8(args.RgbResult >> 16)
|
||||
return color.RGBA{R: r, G: g, B: b, A: 255}, nil
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-choosecolorw-r1
|
||||
type _CHOOSECOLOR struct {
|
||||
StructSize uint32
|
||||
Owner uintptr
|
||||
Instance uintptr
|
||||
RgbResult uint32
|
||||
CustColors *[16]uint32
|
||||
Flags uint32
|
||||
CustData uintptr
|
||||
FnHook uintptr
|
||||
TemplateName *uint16
|
||||
}
|
||||
|
|
162
file_windows.go
162
file_windows.go
|
@ -7,27 +7,11 @@ import (
|
|||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
getOpenFileName = comdlg32.NewProc("GetOpenFileNameW")
|
||||
getSaveFileName = comdlg32.NewProc("GetSaveFileNameW")
|
||||
shBrowseForFolder = shell32.NewProc("SHBrowseForFolderW")
|
||||
shCreateItemFromParsingName = shell32.NewProc("SHCreateItemFromParsingName")
|
||||
shGetPathFromIDListEx = shell32.NewProc("SHGetPathFromIDListEx")
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
)
|
||||
|
||||
const (
|
||||
_OFN_OVERWRITEPROMPT = 0x00000002
|
||||
_OFN_NOCHANGEDIR = 0x00000008
|
||||
_OFN_ALLOWMULTISELECT = 0x00000200
|
||||
_OFN_PATHMUSTEXIST = 0x00000800
|
||||
_OFN_FILEMUSTEXIST = 0x00001000
|
||||
_OFN_CREATEPROMPT = 0x00002000
|
||||
_OFN_NOREADONLYRETURN = 0x00008000
|
||||
_OFN_EXPLORER = 0x00080000
|
||||
_OFN_FORCESHOWHIDDEN = 0x10000000
|
||||
|
||||
_FOS_NOCHANGEDIR = 0x00000008
|
||||
_FOS_PICKFOLDERS = 0x00000020
|
||||
_FOS_FORCEFILESYSTEM = 0x00000040
|
||||
|
@ -41,16 +25,16 @@ func selectFile(opts options) (string, error) {
|
|||
return res, err
|
||||
}
|
||||
|
||||
var args _OPENFILENAME
|
||||
var args win.OPENFILENAME
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
args.Owner, _ = opts.attach.(uintptr)
|
||||
args.Flags = _OFN_NOCHANGEDIR | _OFN_FILEMUSTEXIST | _OFN_EXPLORER
|
||||
args.Flags = win.OFN_NOCHANGEDIR | win.OFN_FILEMUSTEXIST | win.OFN_EXPLORER
|
||||
|
||||
if opts.title != nil {
|
||||
args.Title = syscall.StringToUTF16Ptr(*opts.title)
|
||||
}
|
||||
if opts.showHidden {
|
||||
args.Flags |= _OFN_FORCESHOWHIDDEN
|
||||
args.Flags |= win.OFN_FORCESHOWHIDDEN
|
||||
}
|
||||
if opts.fileFilters != nil {
|
||||
args.Filter = &initFilters(opts.fileFilters)[0]
|
||||
|
@ -71,12 +55,12 @@ func selectFile(opts options) (string, error) {
|
|||
defer unhook()
|
||||
}
|
||||
|
||||
s, _, _ := getOpenFileName.Call(uintptr(unsafe.Pointer(&args)))
|
||||
ok := win.GetOpenFileName(&args)
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return "", opts.ctx.Err()
|
||||
}
|
||||
if s == 0 {
|
||||
return "", commDlgError()
|
||||
if !ok {
|
||||
return "", win.CommDlgError()
|
||||
}
|
||||
return syscall.UTF16ToString(res[:]), nil
|
||||
}
|
||||
|
@ -87,16 +71,16 @@ func selectFileMultiple(opts options) ([]string, error) {
|
|||
return res, err
|
||||
}
|
||||
|
||||
var args _OPENFILENAME
|
||||
var args win.OPENFILENAME
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
args.Owner, _ = opts.attach.(uintptr)
|
||||
args.Flags = _OFN_NOCHANGEDIR | _OFN_ALLOWMULTISELECT | _OFN_FILEMUSTEXIST | _OFN_EXPLORER
|
||||
args.Flags = win.OFN_NOCHANGEDIR | win.OFN_ALLOWMULTISELECT | win.OFN_FILEMUSTEXIST | win.OFN_EXPLORER
|
||||
|
||||
if opts.title != nil {
|
||||
args.Title = syscall.StringToUTF16Ptr(*opts.title)
|
||||
}
|
||||
if opts.showHidden {
|
||||
args.Flags |= _OFN_FORCESHOWHIDDEN
|
||||
args.Flags |= win.OFN_FORCESHOWHIDDEN
|
||||
}
|
||||
if opts.fileFilters != nil {
|
||||
args.Filter = &initFilters(opts.fileFilters)[0]
|
||||
|
@ -117,12 +101,12 @@ func selectFileMultiple(opts options) ([]string, error) {
|
|||
defer unhook()
|
||||
}
|
||||
|
||||
s, _, _ := getOpenFileName.Call(uintptr(unsafe.Pointer(&args)))
|
||||
ok := win.GetOpenFileName(&args)
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return nil, opts.ctx.Err()
|
||||
}
|
||||
if s == 0 {
|
||||
return nil, commDlgError()
|
||||
if !ok {
|
||||
return nil, win.CommDlgError()
|
||||
}
|
||||
|
||||
var i int
|
||||
|
@ -158,22 +142,22 @@ func selectFileSave(opts options) (string, error) {
|
|||
return res, err
|
||||
}
|
||||
|
||||
var args _OPENFILENAME
|
||||
var args win.OPENFILENAME
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
args.Owner, _ = opts.attach.(uintptr)
|
||||
args.Flags = _OFN_NOCHANGEDIR | _OFN_PATHMUSTEXIST | _OFN_NOREADONLYRETURN | _OFN_EXPLORER
|
||||
args.Flags = win.OFN_NOCHANGEDIR | win.OFN_PATHMUSTEXIST | win.OFN_NOREADONLYRETURN | win.OFN_EXPLORER
|
||||
|
||||
if opts.title != nil {
|
||||
args.Title = syscall.StringToUTF16Ptr(*opts.title)
|
||||
}
|
||||
if opts.confirmOverwrite {
|
||||
args.Flags |= _OFN_OVERWRITEPROMPT
|
||||
args.Flags |= win.OFN_OVERWRITEPROMPT
|
||||
}
|
||||
if opts.confirmCreate {
|
||||
args.Flags |= _OFN_CREATEPROMPT
|
||||
args.Flags |= win.OFN_CREATEPROMPT
|
||||
}
|
||||
if opts.showHidden {
|
||||
args.Flags |= _OFN_FORCESHOWHIDDEN
|
||||
args.Flags |= win.OFN_FORCESHOWHIDDEN
|
||||
}
|
||||
if opts.fileFilters != nil {
|
||||
args.Filter = &initFilters(opts.fileFilters)[0]
|
||||
|
@ -194,12 +178,12 @@ func selectFileSave(opts options) (string, error) {
|
|||
defer unhook()
|
||||
}
|
||||
|
||||
s, _, _ := getSaveFileName.Call(uintptr(unsafe.Pointer(&args)))
|
||||
ok := win.GetSaveFileName(&args)
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return "", opts.ctx.Err()
|
||||
}
|
||||
if s == 0 {
|
||||
return "", commDlgError()
|
||||
if !ok {
|
||||
return "", win.CommDlgError()
|
||||
}
|
||||
return syscall.UTF16ToString(res[:]), nil
|
||||
}
|
||||
|
@ -207,19 +191,19 @@ func selectFileSave(opts options) (string, error) {
|
|||
func pickFolders(opts options, multi bool) (str string, lst []string, err error) {
|
||||
defer setup()()
|
||||
|
||||
hr, _, _ := coInitializeEx.Call(0, 0x6) // COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE
|
||||
if hr != 0x80010106 { // RPC_E_CHANGED_MODE
|
||||
if int32(hr) < 0 {
|
||||
return "", nil, syscall.Errno(hr)
|
||||
err = win.CoInitializeEx(0, 0x6) // COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE
|
||||
if err != win.RPC_E_CHANGED_MODE {
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
defer coUninitialize.Call()
|
||||
defer win.CoUninitialize()
|
||||
}
|
||||
|
||||
var dialog *_IFileOpenDialog
|
||||
hr, _, _ = coCreateInstance.Call(
|
||||
_CLSID_FileOpenDialog, 0, 0x17, // CLSCTX_ALL
|
||||
_IID_IFileOpenDialog, uintptr(unsafe.Pointer(&dialog)))
|
||||
if int32(hr) < 0 {
|
||||
err = win.CoCreateInstance(
|
||||
_CLSID_FileOpenDialog, nil, 0x17, // CLSCTX_ALL
|
||||
_IID_IFileOpenDialog, unsafe.Pointer(&dialog))
|
||||
if err != nil {
|
||||
if multi {
|
||||
return "", nil, fmt.Errorf("%w: multiple directory", ErrUnsupported)
|
||||
}
|
||||
|
@ -228,7 +212,7 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
|||
defer dialog.Call(dialog.Release)
|
||||
|
||||
var flgs int
|
||||
hr, _, _ = dialog.Call(dialog.GetOptions, uintptr(unsafe.Pointer(&flgs)))
|
||||
hr, _, _ := dialog.Call(dialog.GetOptions, uintptr(unsafe.Pointer(&flgs)))
|
||||
if int32(hr) < 0 {
|
||||
return "", nil, syscall.Errno(hr)
|
||||
}
|
||||
|
@ -250,12 +234,9 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
|||
}
|
||||
|
||||
if opts.filename != "" {
|
||||
var item *_IShellItem
|
||||
var item *win.IShellItem
|
||||
ptr := syscall.StringToUTF16Ptr(opts.filename)
|
||||
hr, _, _ = shCreateItemFromParsingName.Call(
|
||||
uintptr(unsafe.Pointer(ptr)), 0,
|
||||
_IID_IShellItem,
|
||||
uintptr(unsafe.Pointer(&item)))
|
||||
win.SHCreateItemFromParsingName(ptr, nil, _IID_IShellItem, &item)
|
||||
|
||||
if int32(hr) >= 0 && item != nil {
|
||||
dialog.Call(dialog.SetFolder, uintptr(unsafe.Pointer(item)))
|
||||
|
@ -283,8 +264,8 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
|||
return "", nil, syscall.Errno(hr)
|
||||
}
|
||||
|
||||
shellItemPath := func(obj *_COMObject, trap uintptr, a ...uintptr) error {
|
||||
var item *_IShellItem
|
||||
shellItemPath := func(obj *win.COMObject, trap uintptr, a ...uintptr) error {
|
||||
var item *win.IShellItem
|
||||
hr, _, _ := obj.Call(trap, append(a, uintptr(unsafe.Pointer(&item)))...)
|
||||
if int32(hr) < 0 {
|
||||
return syscall.Errno(hr)
|
||||
|
@ -298,11 +279,11 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
|||
if int32(hr) < 0 {
|
||||
return syscall.Errno(hr)
|
||||
}
|
||||
defer coTaskMemFree.Call(ptr)
|
||||
defer win.CoTaskMemFree(ptr)
|
||||
|
||||
var res []uint16
|
||||
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&res))
|
||||
hdr.Data, hdr.Len, hdr.Cap = ptr, 32768, 32768
|
||||
hdr.Data, hdr.Len, hdr.Cap = uintptr(ptr), 32768, 32768
|
||||
str = syscall.UTF16ToString(res)
|
||||
lst = append(lst, str)
|
||||
return nil
|
||||
|
@ -322,16 +303,16 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
|||
return "", nil, syscall.Errno(hr)
|
||||
}
|
||||
for i := uintptr(0); i < uintptr(count) && err == nil; i++ {
|
||||
err = shellItemPath(&items._COMObject, items.GetItemAt, i)
|
||||
err = shellItemPath(&items.COMObject, items.GetItemAt, i)
|
||||
}
|
||||
} else {
|
||||
err = shellItemPath(&dialog._COMObject, dialog.GetResult)
|
||||
err = shellItemPath(&dialog.COMObject, dialog.GetResult)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func browseForFolder(opts options) (string, []string, error) {
|
||||
var args _BROWSEINFO
|
||||
var args win.BROWSEINFO
|
||||
args.Owner, _ = opts.attach.(uintptr)
|
||||
args.Flags = 0x1 // BIF_RETURNONLYFSDIRS
|
||||
|
||||
|
@ -351,17 +332,17 @@ func browseForFolder(opts options) (string, []string, error) {
|
|||
defer unhook()
|
||||
}
|
||||
|
||||
ptr, _, _ := shBrowseForFolder.Call(uintptr(unsafe.Pointer(&args)))
|
||||
ptr := win.SHBrowseForFolder(&args)
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return "", nil, opts.ctx.Err()
|
||||
}
|
||||
if ptr == 0 {
|
||||
return "", nil, ErrCanceled
|
||||
}
|
||||
defer coTaskMemFree.Call(ptr)
|
||||
defer win.CoTaskMemFree(ptr)
|
||||
|
||||
var res [32768]uint16
|
||||
shGetPathFromIDListEx.Call(ptr, uintptr(unsafe.Pointer(&res[0])), uintptr(len(res)), 0)
|
||||
win.SHGetPathFromIDListEx(ptr, &res[0], len(res), 0)
|
||||
|
||||
str := syscall.UTF16ToString(res[:])
|
||||
return str, []string{str}, nil
|
||||
|
@ -408,45 +389,6 @@ func initFilters(filters FileFilters) []uint16 {
|
|||
return res
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamew
|
||||
type _OPENFILENAME struct {
|
||||
StructSize uint32
|
||||
Owner uintptr
|
||||
Instance uintptr
|
||||
Filter *uint16
|
||||
CustomFilter *uint16
|
||||
MaxCustomFilter uint32
|
||||
FilterIndex uint32
|
||||
File *uint16
|
||||
MaxFile uint32
|
||||
FileTitle *uint16
|
||||
MaxFileTitle uint32
|
||||
InitialDir *uint16
|
||||
Title *uint16
|
||||
Flags uint32
|
||||
FileOffset uint16
|
||||
FileExtension uint16
|
||||
DefExt *uint16
|
||||
CustData uintptr
|
||||
FnHook uintptr
|
||||
TemplateName *uint16
|
||||
PvReserved uintptr
|
||||
DwReserved uint32
|
||||
FlagsEx uint32
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-browseinfow
|
||||
type _BROWSEINFO struct {
|
||||
Owner uintptr
|
||||
Root uintptr
|
||||
DisplayName *uint16
|
||||
Title *uint16
|
||||
Flags uint32
|
||||
CallbackFunc uintptr
|
||||
LParam *uint16
|
||||
Image int32
|
||||
}
|
||||
|
||||
// https://github.com/wine-mirror/wine/blob/master/include/shobjidl.idl
|
||||
|
||||
var (
|
||||
|
@ -456,17 +398,12 @@ var (
|
|||
)
|
||||
|
||||
type _IFileOpenDialog struct {
|
||||
_COMObject
|
||||
win.COMObject
|
||||
*_IFileOpenDialogVtbl
|
||||
}
|
||||
|
||||
type _IShellItem struct {
|
||||
_COMObject
|
||||
*_IShellItemVtbl
|
||||
}
|
||||
|
||||
type _IShellItemArray struct {
|
||||
_COMObject
|
||||
win.COMObject
|
||||
*_IShellItemArrayVtbl
|
||||
}
|
||||
|
||||
|
@ -508,15 +445,6 @@ type _IModalWindowVtbl struct {
|
|||
Show uintptr
|
||||
}
|
||||
|
||||
type _IShellItemVtbl struct {
|
||||
_IUnknownVtbl
|
||||
BindToHandler uintptr
|
||||
GetParent uintptr
|
||||
GetDisplayName uintptr
|
||||
GetAttributes uintptr
|
||||
Compare uintptr
|
||||
}
|
||||
|
||||
type _IShellItemArrayVtbl struct {
|
||||
_IUnknownVtbl
|
||||
BindToHandler uintptr
|
||||
|
|
4
go.mod
4
go.mod
|
@ -8,8 +8,8 @@ require (
|
|||
github.com/ncruces/go-strftime v0.1.8
|
||||
github.com/randall77/makefat v0.0.0-20210315173500-7ddd0e42c844
|
||||
go.uber.org/goleak v1.1.12 // test
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd
|
||||
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d
|
||||
golang.org/x/image v0.0.0-20220617043117-41969df76e82
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
8
go.sum
8
go.sum
|
@ -24,8 +24,8 @@ go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
|||
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd h1:9NbNcTg//wfC5JskFW4Z3sqwVnjmJKHxLAol1bW2qgw=
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
golang.org/x/image v0.0.0-20220617043117-41969df76e82 h1:KpZB5pUSBvrHltNEdK/tw0xlPeD13M6M6aGP32gKqiw=
|
||||
golang.org/x/image v0.0.0-20220617043117-41969df76e82/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
|
@ -42,8 +42,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d h1:Zu/JngovGLVi6t2J3nmAf3AoTDwuzw85YZ3b9o4yU7s=
|
||||
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU=
|
||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
|
11
internal/win/comctl32.go
Normal file
11
internal/win/comctl32.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
//go:build windows
|
||||
|
||||
package win
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-initcommoncontrolsex
|
||||
type INITCOMMONCONTROLSEX struct {
|
||||
Size uint32
|
||||
ICC uint32
|
||||
}
|
||||
|
||||
//sys InitCommonControlsEx(icc *INITCOMMONCONTROLSEX) (ok bool) = comctl32.InitCommonControlsEx
|
80
internal/win/comdlg32.go
Normal file
80
internal/win/comdlg32.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
//go:build windows
|
||||
|
||||
package win
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ncruces/zenity/internal/zenutil"
|
||||
)
|
||||
|
||||
const (
|
||||
CC_RGBINIT = 0x00000001
|
||||
CC_FULLOPEN = 0x00000002
|
||||
CC_PREVENTFULLOPEN = 0x00000004
|
||||
)
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-choosecolorw-r1
|
||||
type CHOOSECOLOR struct {
|
||||
StructSize uint32
|
||||
Owner uintptr
|
||||
Instance uintptr
|
||||
RgbResult uint32
|
||||
CustColors *[16]uint32
|
||||
Flags uint32
|
||||
CustData uintptr
|
||||
FnHook uintptr
|
||||
TemplateName *uint16
|
||||
}
|
||||
|
||||
const (
|
||||
OFN_OVERWRITEPROMPT = 0x00000002
|
||||
OFN_NOCHANGEDIR = 0x00000008
|
||||
OFN_ALLOWMULTISELECT = 0x00000200
|
||||
OFN_PATHMUSTEXIST = 0x00000800
|
||||
OFN_FILEMUSTEXIST = 0x00001000
|
||||
OFN_CREATEPROMPT = 0x00002000
|
||||
OFN_NOREADONLYRETURN = 0x00008000
|
||||
OFN_EXPLORER = 0x00080000
|
||||
OFN_FORCESHOWHIDDEN = 0x10000000
|
||||
)
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamew
|
||||
type OPENFILENAME struct {
|
||||
StructSize uint32
|
||||
Owner uintptr
|
||||
Instance uintptr
|
||||
Filter *uint16
|
||||
CustomFilter *uint16
|
||||
MaxCustomFilter uint32
|
||||
FilterIndex uint32
|
||||
File *uint16
|
||||
MaxFile uint32
|
||||
FileTitle *uint16
|
||||
MaxFileTitle uint32
|
||||
InitialDir *uint16
|
||||
Title *uint16
|
||||
Flags uint32
|
||||
FileOffset uint16
|
||||
FileExtension uint16
|
||||
DefExt *uint16
|
||||
CustData uintptr
|
||||
FnHook uintptr
|
||||
TemplateName *uint16
|
||||
PvReserved uintptr
|
||||
DwReserved uint32
|
||||
FlagsEx uint32
|
||||
}
|
||||
|
||||
func CommDlgError() error {
|
||||
if code := commDlgExtendedError(); code == 0 {
|
||||
return zenutil.ErrCanceled
|
||||
} else {
|
||||
return fmt.Errorf("Common Dialog error: %x", code)
|
||||
}
|
||||
}
|
||||
|
||||
//sys commDlgExtendedError() (code int) = comdlg32.CommDlgExtendedError
|
||||
//sys ChooseColor(cc *CHOOSECOLOR) (ok bool) = comdlg32.ChooseColorW
|
||||
//sys GetOpenFileName(ofn *OPENFILENAME) (ok bool) = comdlg32.GetOpenFileNameW
|
||||
//sys GetSaveFileName(ofn *OPENFILENAME) (ok bool) = comdlg32.GetSaveFileNameW
|
47
internal/win/ole32.go
Normal file
47
internal/win/ole32.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
//go:build windows
|
||||
|
||||
package win
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
RPC_E_CHANGED_MODE syscall.Errno = 0x80010106
|
||||
)
|
||||
|
||||
func CoInitializeEx(reserved uintptr, coInit uint32) error {
|
||||
return windows.CoInitializeEx(reserved, coInit)
|
||||
}
|
||||
|
||||
func CoUninitialize() { windows.CoUninitialize() }
|
||||
|
||||
// https://github.com/wine-mirror/wine/blob/master/include/unknwn.idl
|
||||
|
||||
type IUnknownVtbl struct {
|
||||
QueryInterface uintptr
|
||||
AddRef uintptr
|
||||
Release uintptr
|
||||
}
|
||||
|
||||
type COMObject struct{}
|
||||
|
||||
//go:uintptrescapes
|
||||
func (o *COMObject) Call(trap uintptr, a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||
switch nargs := uintptr(len(a)); nargs {
|
||||
case 0:
|
||||
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(o)), 0, 0)
|
||||
case 1:
|
||||
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(o)), a[0], 0)
|
||||
case 2:
|
||||
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(o)), a[0], a[1])
|
||||
default:
|
||||
panic("COM call with too many arguments.")
|
||||
}
|
||||
}
|
||||
|
||||
//sys CoTaskMemFree(address uintptr) = ole32.CoTaskMemFree
|
||||
//sys CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (ret error) = ole32.CoCreateInstance
|
5
internal/win/pkg.go
Normal file
5
internal/win/pkg.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Package win is internal. DO NOT USE.
|
||||
package win
|
||||
|
||||
//go:generate -command mkwinsyscall go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go
|
||||
//go:generate mkwinsyscall comctl32.go comdlg32.go ole32.go shell32.go
|
58
internal/win/shell32.go
Normal file
58
internal/win/shell32.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
//go:build windows
|
||||
|
||||
package win
|
||||
|
||||
const (
|
||||
NIM_ADD = 0
|
||||
NIM_DELETE = 2
|
||||
)
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/ns-shlobj_core-browseinfow
|
||||
type BROWSEINFO struct {
|
||||
Owner uintptr
|
||||
Root uintptr
|
||||
DisplayName *uint16
|
||||
Title *uint16
|
||||
Flags uint32
|
||||
CallbackFunc uintptr
|
||||
LParam *uint16
|
||||
Image int32
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataw
|
||||
type NOTIFYICONDATA struct {
|
||||
StructSize uint32
|
||||
Wnd uintptr
|
||||
ID uint32
|
||||
Flags uint32
|
||||
CallbackMessage uint32
|
||||
Icon uintptr
|
||||
Tip [128]uint16 // NOTIFYICONDATAA_V1_SIZE
|
||||
State uint32
|
||||
StateMask uint32
|
||||
Info [256]uint16
|
||||
Version uint32
|
||||
InfoTitle [64]uint16
|
||||
InfoFlags uint32
|
||||
// GuidItem [16]byte // NOTIFYICONDATAA_V2_SIZE
|
||||
// BalloonIcon syscall.Handle // NOTIFYICONDATAA_V3_SIZE
|
||||
}
|
||||
|
||||
type IShellItem struct {
|
||||
COMObject
|
||||
*_IShellItemVtbl
|
||||
}
|
||||
|
||||
type _IShellItemVtbl struct {
|
||||
IUnknownVtbl
|
||||
BindToHandler uintptr
|
||||
GetParent uintptr
|
||||
GetDisplayName uintptr
|
||||
GetAttributes uintptr
|
||||
Compare uintptr
|
||||
}
|
||||
|
||||
//sys SHBrowseForFolder(bi *BROWSEINFO) (ptr uintptr) = shell32.SHBrowseForFolder
|
||||
//sys SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (err error) = shell32.SHCreateItemFromParsingName
|
||||
//sys SHGetPathFromIDListEx(ptr uintptr, path *uint16, pathLen int, opts int) (err error) = shell32.SHGetPathFromIDListEx
|
||||
//sys ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error) = shell32.Shell_NotifyIconW
|
131
internal/win/zsyscall_windows.go
Normal file
131
internal/win/zsyscall_windows.go
Normal file
|
@ -0,0 +1,131 @@
|
|||
// Code generated by 'go generate'; DO NOT EDIT.
|
||||
|
||||
package win
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
// Do the interface allocations only once for common
|
||||
// Errno values.
|
||||
const (
|
||||
errnoERROR_IO_PENDING = 997
|
||||
)
|
||||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
errERROR_EINVAL error = syscall.EINVAL
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
// allocations at runtime.
|
||||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return errERROR_EINVAL
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
var (
|
||||
modcomctl32 = windows.NewLazySystemDLL("comctl32.dll")
|
||||
modcomdlg32 = windows.NewLazySystemDLL("comdlg32.dll")
|
||||
modole32 = windows.NewLazySystemDLL("ole32.dll")
|
||||
modshell32 = windows.NewLazySystemDLL("shell32.dll")
|
||||
|
||||
procInitCommonControlsEx = modcomctl32.NewProc("InitCommonControlsEx")
|
||||
procChooseColorW = modcomdlg32.NewProc("ChooseColorW")
|
||||
procCommDlgExtendedError = modcomdlg32.NewProc("CommDlgExtendedError")
|
||||
procGetOpenFileNameW = modcomdlg32.NewProc("GetOpenFileNameW")
|
||||
procGetSaveFileNameW = modcomdlg32.NewProc("GetSaveFileNameW")
|
||||
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")
|
||||
)
|
||||
|
||||
func InitCommonControlsEx(icc *INITCOMMONCONTROLSEX) (ok bool) {
|
||||
r0, _, _ := syscall.Syscall(procInitCommonControlsEx.Addr(), 1, uintptr(unsafe.Pointer(icc)), 0, 0)
|
||||
ok = r0 != 0
|
||||
return
|
||||
}
|
||||
|
||||
func ChooseColor(cc *CHOOSECOLOR) (ok bool) {
|
||||
r0, _, _ := syscall.Syscall(procChooseColorW.Addr(), 1, uintptr(unsafe.Pointer(cc)), 0, 0)
|
||||
ok = r0 != 0
|
||||
return
|
||||
}
|
||||
|
||||
func commDlgExtendedError() (code int) {
|
||||
r0, _, _ := syscall.Syscall(procCommDlgExtendedError.Addr(), 0, 0, 0, 0)
|
||||
code = int(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func GetOpenFileName(ofn *OPENFILENAME) (ok bool) {
|
||||
r0, _, _ := syscall.Syscall(procGetOpenFileNameW.Addr(), 1, uintptr(unsafe.Pointer(ofn)), 0, 0)
|
||||
ok = r0 != 0
|
||||
return
|
||||
}
|
||||
|
||||
func GetSaveFileName(ofn *OPENFILENAME) (ok bool) {
|
||||
r0, _, _ := syscall.Syscall(procGetSaveFileNameW.Addr(), 1, uintptr(unsafe.Pointer(ofn)), 0, 0)
|
||||
ok = r0 != 0
|
||||
return
|
||||
}
|
||||
|
||||
func CoCreateInstance(clsid uintptr, unkOuter unsafe.Pointer, clsContext int32, iid uintptr, address unsafe.Pointer) (ret error) {
|
||||
r0, _, _ := syscall.Syscall6(procCoCreateInstance.Addr(), 5, uintptr(clsid), uintptr(unkOuter), uintptr(clsContext), uintptr(iid), uintptr(address), 0)
|
||||
if r0 != 0 {
|
||||
ret = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func CoTaskMemFree(address uintptr) {
|
||||
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)
|
||||
ptr = uintptr(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func SHCreateItemFromParsingName(path *uint16, bc unsafe.Pointer, iid uintptr, item **IShellItem) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procSHCreateItemFromParsingName.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(bc), uintptr(iid), uintptr(unsafe.Pointer(item)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func SHGetPathFromIDListEx(ptr uintptr, path *uint16, pathLen int, opts int) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procSHGetPathFromIDListEx.Addr(), 4, uintptr(ptr), uintptr(unsafe.Pointer(path)), uintptr(pathLen), uintptr(opts), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ShellNotifyIcon(message uint32, data *NOTIFYICONDATA) (ret int, err error) {
|
||||
r0, _, e1 := syscall.Syscall(procShell_NotifyIconW.Addr(), 2, uintptr(message), uintptr(unsafe.Pointer(data)), 0)
|
||||
ret = int(r0)
|
||||
if ret == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
|
@ -7,12 +7,12 @@ import (
|
|||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
"github.com/ncruces/zenity/internal/zenutil"
|
||||
)
|
||||
|
||||
var (
|
||||
rtlGetNtVersionNumbers = ntdll.NewProc("RtlGetNtVersionNumbers")
|
||||
shellNotifyIcon = shell32.NewProc("Shell_NotifyIconW")
|
||||
wtsSendMessage = wtsapi32.NewProc("WTSSendMessageW")
|
||||
)
|
||||
|
||||
|
@ -21,7 +21,7 @@ func notify(text string, opts options) error {
|
|||
return opts.ctx.Err()
|
||||
}
|
||||
|
||||
var args _NOTIFYICONDATA
|
||||
var args win.NOTIFYICONDATA
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
args.ID = rand.Uint32()
|
||||
args.Flags = 0x00000010 // NIF_INFO
|
||||
|
@ -55,7 +55,7 @@ func notify(text string, opts options) error {
|
|||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
s, _, err := shellNotifyIcon.Call(0 /* NIM_ADD */, uintptr(unsafe.Pointer(&args)))
|
||||
s, err := win.ShellNotifyIcon(win.NIM_ADD, &args)
|
||||
if s == 0 {
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == 0 {
|
||||
return wtsMessage(text, opts)
|
||||
|
@ -81,7 +81,7 @@ func notify(text string, opts options) error {
|
|||
}
|
||||
}
|
||||
|
||||
shellNotifyIcon.Call(2 /* NIM_DELETE */, uintptr(unsafe.Pointer(&args)))
|
||||
win.ShellNotifyIcon(win.NIM_DELETE, &args)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -125,22 +125,3 @@ func wtsMessage(text string, opts options) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataw
|
||||
type _NOTIFYICONDATA struct {
|
||||
StructSize uint32
|
||||
Wnd uintptr
|
||||
ID uint32
|
||||
Flags uint32
|
||||
CallbackMessage uint32
|
||||
Icon uintptr
|
||||
Tip [128]uint16 // NOTIFYICONDATAA_V1_SIZE
|
||||
State uint32
|
||||
StateMask uint32
|
||||
Info [256]uint16
|
||||
Version uint32
|
||||
InfoTitle [64]uint16
|
||||
InfoFlags uint32
|
||||
// GuidItem [16]byte // NOTIFYICONDATAA_V2_SIZE
|
||||
// BalloonIcon syscall.Handle // NOTIFYICONDATAA_V3_SIZE
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package zenity
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
|
@ -13,23 +12,17 @@ import (
|
|||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ncruces/zenity/internal/win"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
comctl32 = windows.NewLazySystemDLL("comctl32.dll")
|
||||
comdlg32 = windows.NewLazySystemDLL("comdlg32.dll")
|
||||
gdi32 = windows.NewLazySystemDLL("gdi32.dll")
|
||||
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
ntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
ole32 = windows.NewLazySystemDLL("ole32.dll")
|
||||
shell32 = windows.NewLazySystemDLL("shell32.dll")
|
||||
user32 = windows.NewLazySystemDLL("user32.dll")
|
||||
wtsapi32 = windows.NewLazySystemDLL("wtsapi32.dll")
|
||||
|
||||
commDlgExtendedError = comdlg32.NewProc("CommDlgExtendedError")
|
||||
initCommonControlsEx = comctl32.NewProc("InitCommonControlsEx")
|
||||
|
||||
createFontIndirect = gdi32.NewProc("CreateFontIndirectW")
|
||||
deleteObject = gdi32.NewProc("DeleteObject")
|
||||
getDeviceCaps = gdi32.NewProc("GetDeviceCaps")
|
||||
|
@ -42,11 +35,6 @@ var (
|
|||
getModuleHandle = kernel32.NewProc("GetModuleHandleW")
|
||||
getSystemDirectory = kernel32.NewProc("GetSystemDirectoryW")
|
||||
|
||||
coCreateInstance = ole32.NewProc("CoCreateInstance")
|
||||
coInitializeEx = ole32.NewProc("CoInitializeEx")
|
||||
coTaskMemFree = ole32.NewProc("CoTaskMemFree")
|
||||
coUninitialize = ole32.NewProc("CoUninitialize")
|
||||
|
||||
callNextHookEx = user32.NewProc("CallNextHookEx")
|
||||
createIconFromResource = user32.NewProc("CreateIconFromResource")
|
||||
createWindowEx = user32.NewProc("CreateWindowExW")
|
||||
|
@ -121,10 +109,10 @@ func setup() context.CancelFunc {
|
|||
}
|
||||
}
|
||||
|
||||
var icc _INITCOMMONCONTROLSEX
|
||||
var icc win.INITCOMMONCONTROLSEX
|
||||
icc.Size = uint32(unsafe.Sizeof(icc))
|
||||
icc.ICC = 0x00004020 // ICC_STANDARD_CLASSES|ICC_PROGRESS_CLASS
|
||||
initCommonControlsEx.Call(uintptr(unsafe.Pointer(&icc)))
|
||||
win.InitCommonControlsEx(&icc)
|
||||
|
||||
return func() {
|
||||
if restore != 0 {
|
||||
|
@ -147,15 +135,6 @@ func setupEnumCallback(wnd uintptr, lparam *uintptr) uintptr {
|
|||
return 1 // continue enumeration
|
||||
}
|
||||
|
||||
func commDlgError() error {
|
||||
s, _, _ := commDlgExtendedError.Call()
|
||||
if s == 0 {
|
||||
return ErrCanceled
|
||||
} else {
|
||||
return fmt.Errorf("Common Dialog error: %x", s)
|
||||
}
|
||||
}
|
||||
|
||||
func hookDialog(ctx context.Context, icon any, title *string, init func(wnd uintptr)) (unhook context.CancelFunc, err error) {
|
||||
if ctx != nil && ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
|
@ -482,12 +461,6 @@ type _ACTCTX struct {
|
|||
Module uintptr
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-initcommoncontrolsex
|
||||
type _INITCOMMONCONTROLSEX struct {
|
||||
Size uint32
|
||||
ICC uint32
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-cwpretstruct
|
||||
type _CWPRETSTRUCT struct {
|
||||
Result uintptr
|
||||
|
@ -596,19 +569,3 @@ type _IUnknownVtbl struct {
|
|||
func uuid(s string) uintptr {
|
||||
return (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
|
||||
}
|
||||
|
||||
type _COMObject struct{}
|
||||
|
||||
//go:uintptrescapes
|
||||
func (o *_COMObject) Call(trap uintptr, a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||
switch nargs := uintptr(len(a)); nargs {
|
||||
case 0:
|
||||
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(o)), 0, 0)
|
||||
case 1:
|
||||
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(o)), a[0], 0)
|
||||
case 2:
|
||||
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(o)), a[0], a[1])
|
||||
default:
|
||||
panic("COM call with too many arguments.")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue