Refactor (windows).
This commit is contained in:
parent
e2dc86414f
commit
762d54a00d
13 changed files with 225 additions and 152 deletions
|
@ -72,7 +72,6 @@ func TestCalendar_script(t *testing.T) {
|
||||||
if skip, err := skip(err); skip {
|
if skip, err := skip(err); skip {
|
||||||
t.Skip("skipping:", err)
|
t.Skip("skipping:", err)
|
||||||
}
|
}
|
||||||
got.Date()
|
|
||||||
if !DateEquals(got, tt.want) || err != tt.err {
|
if !DateEquals(got, tt.want) || err != tt.err {
|
||||||
t.Errorf("Calendar() = %v, %v; want %v, %v", got, err, tt.want, tt.err)
|
t.Errorf("Calendar() = %v, %v; want %v, %v", got, err, tt.want, tt.err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ func TestSelectFile_script(t *testing.T) {
|
||||||
t.Skip("skipping:", err)
|
t.Skip("skipping:", err)
|
||||||
}
|
}
|
||||||
if str == "" || err != nil {
|
if str == "" || err != nil {
|
||||||
t.Errorf("SelectFile() = %q, %v; want [path], nil", str, err)
|
t.Fatalf("SelectFile() = %q, %v; want [path], nil", str, err)
|
||||||
}
|
}
|
||||||
if _, serr := os.Stat(str); serr != nil {
|
if _, serr := os.Stat(str); serr != nil {
|
||||||
t.Errorf("SelectFile() = %q, %v; %v", str, err, serr)
|
t.Errorf("SelectFile() = %q, %v; %v", str, err, serr)
|
||||||
|
@ -152,7 +152,7 @@ func TestSelectFile_script(t *testing.T) {
|
||||||
t.Skip("skipping:", err)
|
t.Skip("skipping:", err)
|
||||||
}
|
}
|
||||||
if str == "" || err != nil {
|
if str == "" || err != nil {
|
||||||
t.Errorf("SelectFile() = %q, %v; want [path], nil", str, err)
|
t.Fatalf("SelectFile() = %q, %v; want [path], nil", str, err)
|
||||||
}
|
}
|
||||||
if s, serr := os.Stat(str); serr != nil {
|
if s, serr := os.Stat(str); serr != nil {
|
||||||
t.Errorf("SelectFile() = %q, %v; %v", str, err, serr)
|
t.Errorf("SelectFile() = %q, %v; %v", str, err, serr)
|
||||||
|
@ -183,7 +183,7 @@ func TestSelectFileMultiple_script(t *testing.T) {
|
||||||
t.Skip("skipping:", err)
|
t.Skip("skipping:", err)
|
||||||
}
|
}
|
||||||
if lst == nil || err != nil {
|
if lst == nil || err != nil {
|
||||||
t.Errorf("SelectFileMultiple() = %v, %v; want [path, path], nil", lst, err)
|
t.Fatalf("SelectFileMultiple() = %v, %v; want [path, path], nil", lst, err)
|
||||||
}
|
}
|
||||||
for _, str := range lst {
|
for _, str := range lst {
|
||||||
if _, serr := os.Stat(str); serr != nil {
|
if _, serr := os.Stat(str); serr != nil {
|
||||||
|
@ -201,7 +201,7 @@ func TestSelectFileMultiple_script(t *testing.T) {
|
||||||
t.Skip("was not unsupported:", err)
|
t.Skip("was not unsupported:", err)
|
||||||
}
|
}
|
||||||
if lst == nil || err != nil {
|
if lst == nil || err != nil {
|
||||||
t.Errorf("SelectFileMultiple() = %v, %v; want [path, path], nil", lst, err)
|
t.Fatalf("SelectFileMultiple() = %v, %v; want [path, path], nil", lst, err)
|
||||||
}
|
}
|
||||||
for _, str := range lst {
|
for _, str := range lst {
|
||||||
if s, serr := os.Stat(str); serr != nil {
|
if s, serr := os.Stat(str); serr != nil {
|
||||||
|
|
|
@ -10,16 +10,6 @@ import (
|
||||||
"github.com/ncruces/zenity/internal/win"
|
"github.com/ncruces/zenity/internal/win"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
_FOS_NOCHANGEDIR = 0x00000008
|
|
||||||
_FOS_PICKFOLDERS = 0x00000020
|
|
||||||
_FOS_FORCEFILESYSTEM = 0x00000040
|
|
||||||
_FOS_ALLOWMULTISELECT = 0x00000200
|
|
||||||
_FOS_FORCESHOWHIDDEN = 0x10000000
|
|
||||||
|
|
||||||
_SIGDN_FILESYSPATH = 0x80058000
|
|
||||||
)
|
|
||||||
|
|
||||||
func selectFile(opts options) (string, error) {
|
func selectFile(opts options) (string, error) {
|
||||||
if opts.directory {
|
if opts.directory {
|
||||||
res, _, err := pickFolders(opts, false)
|
res, _, err := pickFolders(opts, false)
|
||||||
|
@ -189,10 +179,10 @@ func selectFileSave(opts options) (string, error) {
|
||||||
return syscall.UTF16ToString(res[:]), nil
|
return syscall.UTF16ToString(res[:]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func pickFolders(opts options, multi bool) (str string, lst []string, err error) {
|
func pickFolders(opts options, multi bool) (string, []string, error) {
|
||||||
defer setup()()
|
defer setup()()
|
||||||
|
|
||||||
err = win.CoInitializeEx(0, win.COINIT_APARTMENTTHREADED|win.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
|
||||||
|
@ -216,12 +206,12 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
flgs |= _FOS_NOCHANGEDIR | _FOS_PICKFOLDERS | _FOS_FORCEFILESYSTEM
|
flgs |= win.FOS_NOCHANGEDIR | win.FOS_PICKFOLDERS | win.FOS_FORCEFILESYSTEM
|
||||||
if multi {
|
if multi {
|
||||||
flgs |= _FOS_ALLOWMULTISELECT
|
flgs |= win.FOS_ALLOWMULTISELECT
|
||||||
}
|
}
|
||||||
if opts.showHidden {
|
if opts.showHidden {
|
||||||
flgs |= _FOS_FORCESHOWHIDDEN
|
flgs |= win.FOS_FORCESHOWHIDDEN
|
||||||
}
|
}
|
||||||
err = dialog.SetOptions(flgs)
|
err = dialog.SetOptions(flgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -236,8 +226,8 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
||||||
var item *win.IShellItem
|
var item *win.IShellItem
|
||||||
win.SHCreateItemFromParsingName(strptr(opts.filename), nil, win.IID_IShellItem, &item)
|
win.SHCreateItemFromParsingName(strptr(opts.filename), nil, win.IID_IShellItem, &item)
|
||||||
if item != nil {
|
if item != nil {
|
||||||
|
defer item.Release()
|
||||||
dialog.SetFolder(item)
|
dialog.SetFolder(item)
|
||||||
item.Release()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,15 +251,6 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
shellItemPath := func(item *win.IShellItem) error {
|
|
||||||
defer item.Release()
|
|
||||||
str, err := item.GetDisplayName(_SIGDN_FILESYSPATH)
|
|
||||||
if err == nil {
|
|
||||||
lst = append(lst, str)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if multi {
|
if multi {
|
||||||
items, err := dialog.GetResults()
|
items, err := dialog.GetResults()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -281,25 +262,31 @@ func pickFolders(opts options, multi bool) (str string, lst []string, err error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
for i := uint32(0); i < count; i++ {
|
|
||||||
item, err := items.GetItemAt(i)
|
var lst []string
|
||||||
if err == nil {
|
for i := uint32(0); i < count && err == nil; i++ {
|
||||||
err = shellItemPath(item)
|
str, err := shellItemPath(items.GetItemAt(i))
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
lst = append(lst, str)
|
||||||
}
|
}
|
||||||
|
return "", lst, nil
|
||||||
} else {
|
} else {
|
||||||
item, err := dialog.GetResult()
|
str, err := shellItemPath(dialog.GetResult())
|
||||||
if err == nil {
|
|
||||||
err = shellItemPath(item)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
return str, nil, nil
|
||||||
}
|
}
|
||||||
return
|
}
|
||||||
|
|
||||||
|
func shellItemPath(item *win.IShellItem, err error) (string, error) {
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer item.Release()
|
||||||
|
return item.GetDisplayName(win.SIGDN_FILESYSPATH)
|
||||||
}
|
}
|
||||||
|
|
||||||
func browseForFolder(opts options) (string, []string, error) {
|
func browseForFolder(opts options) (string, []string, error) {
|
||||||
|
@ -327,10 +314,10 @@ 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 == nullptr {
|
if ptr == nil {
|
||||||
return "", nil, ErrCanceled
|
return "", nil, ErrCanceled
|
||||||
}
|
}
|
||||||
defer win.CoTaskMemFree(ptr)
|
defer win.CoTaskMemFree(unsafe.Pointer(ptr))
|
||||||
|
|
||||||
var res [32768]uint16
|
var res [32768]uint16
|
||||||
win.SHGetPathFromIDListEx(ptr, &res[0], len(res), 0)
|
win.SHGetPathFromIDListEx(ptr, &res[0], len(res), 0)
|
||||||
|
|
|
@ -2,6 +2,26 @@
|
||||||
|
|
||||||
package win
|
package win
|
||||||
|
|
||||||
|
const (
|
||||||
|
ICC_LISTVIEW_CLASSES = 0x00000001
|
||||||
|
ICC_TREEVIEW_CLASSES = 0x00000002
|
||||||
|
ICC_BAR_CLASSES = 0x00000004
|
||||||
|
ICC_TAB_CLASSES = 0x00000008
|
||||||
|
ICC_UPDOWN_CLASS = 0x00000010
|
||||||
|
ICC_PROGRESS_CLASS = 0x00000020
|
||||||
|
ICC_HOTKEY_CLASS = 0x00000040
|
||||||
|
ICC_ANIMATE_CLASS = 0x00000080
|
||||||
|
ICC_WIN95_CLASSES = 0x000000FF
|
||||||
|
ICC_DATE_CLASSES = 0x00000100
|
||||||
|
ICC_USEREX_CLASSES = 0x00000200
|
||||||
|
ICC_COOL_CLASSES = 0x00000400
|
||||||
|
ICC_INTERNET_CLASSES = 0x00000800
|
||||||
|
ICC_PAGESCROLLER_CLASS = 0x00001000
|
||||||
|
ICC_NATIVEFNTCTL_CLASS = 0x00002000
|
||||||
|
ICC_STANDARD_CLASSES = 0x00004000
|
||||||
|
ICC_LINK_CLASS = 0x00008000
|
||||||
|
)
|
||||||
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-initcommoncontrolsex
|
// https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-initcommoncontrolsex
|
||||||
type INITCOMMONCONTROLSEX struct {
|
type INITCOMMONCONTROLSEX struct {
|
||||||
Size uint32
|
Size uint32
|
||||||
|
|
|
@ -32,38 +32,41 @@ 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 _IUnknownBase struct{ COMObject }
|
type IUnknown struct{}
|
||||||
type _IUnknownVtbl struct {
|
type iUnknownVtbl struct {
|
||||||
QueryInterface uintptr
|
QueryInterface uintptr
|
||||||
AddRef uintptr
|
AddRef uintptr
|
||||||
Release uintptr
|
Release uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IUnknownBase) Release() {
|
func (u *IUnknown) Release() {
|
||||||
vtbl := (*(**_IUnknownVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iUnknownVtbl)(unsafe.Pointer(u))
|
||||||
c.Call(vtbl.Release)
|
u.call(vtbl.Release)
|
||||||
}
|
}
|
||||||
|
|
||||||
type COMObject struct{}
|
|
||||||
|
|
||||||
//go:uintptrescapes
|
//go:uintptrescapes
|
||||||
func (o *COMObject) Call(trap uintptr, a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
func (u *IUnknown) call(trap uintptr, a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||||
switch nargs := uintptr(len(a)); nargs {
|
switch nargs := uintptr(len(a)); nargs {
|
||||||
case 0:
|
case 0:
|
||||||
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(o)), 0, 0)
|
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(u)), 0, 0)
|
||||||
case 1:
|
case 1:
|
||||||
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(o)), a[0], 0)
|
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(u)), a[0], 0)
|
||||||
case 2:
|
case 2:
|
||||||
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(o)), a[0], a[1])
|
return syscall.Syscall(trap, nargs+1, uintptr(unsafe.Pointer(u)), a[0], a[1])
|
||||||
default:
|
default:
|
||||||
panic("COM call with too many arguments.")
|
panic("COM call with too many arguments.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys CoCreateInstance(clsid uintptr, unkOuter *COMObject, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) = ole32.CoCreateInstance
|
// https://github.com/wine-mirror/wine/blob/master/include/objidl.idl
|
||||||
//sys CoTaskMemFree(address Pointer) = ole32.CoTaskMemFree
|
|
||||||
|
type IBindCtx struct{ IUnknown }
|
||||||
|
|
||||||
|
//sys CoCreateInstance(clsid uintptr, unkOuter *IUnknown, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) = ole32.CoCreateInstance
|
||||||
|
|
||||||
func uuid(s string) uintptr {
|
func uuid(s string) uintptr {
|
||||||
return (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
|
return (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
|
||||||
|
|
|
@ -14,8 +14,73 @@ const (
|
||||||
BFFM_INITIALIZED = 1
|
BFFM_INITIALIZED = 1
|
||||||
BFFM_SETSELECTION = WM_USER + 103
|
BFFM_SETSELECTION = WM_USER + 103
|
||||||
|
|
||||||
NIM_ADD = 0
|
// ShellNotifyIcon messages
|
||||||
NIM_DELETE = 2
|
NIM_ADD = 0
|
||||||
|
NIM_MODIFY = 1
|
||||||
|
NIM_DELETE = 2
|
||||||
|
NIM_SETFOCUS = 3
|
||||||
|
NIM_SETVERSION = 4
|
||||||
|
|
||||||
|
// NOTIFYICONDATA flags
|
||||||
|
NIF_MESSAGE = 0x01
|
||||||
|
NIF_ICON = 0x02
|
||||||
|
NIF_TIP = 0x04
|
||||||
|
NIF_STATE = 0x08
|
||||||
|
NIF_INFO = 0x10
|
||||||
|
NIF_GUID = 0x20
|
||||||
|
NIF_REALTIME = 0x40
|
||||||
|
NIF_SHOWTIP = 0x80
|
||||||
|
|
||||||
|
// NOTIFYICONDATA info flags
|
||||||
|
NIIF_NONE = 0x00
|
||||||
|
NIIF_INFO = 0x01
|
||||||
|
NIIF_WARNING = 0x02
|
||||||
|
NIIF_ERROR = 0x03
|
||||||
|
NIIF_USER = 0x04
|
||||||
|
NIIF_NOSOUND = 0x10
|
||||||
|
NIIF_LARGE_ICON = 0x20
|
||||||
|
NIIF_RESPECT_QUIET_TIME = 0x80
|
||||||
|
NIIF_ICON_MASK = 0x0F
|
||||||
|
|
||||||
|
// NOTIFYICONDATA state
|
||||||
|
NIS_HIDDEN = 0x1
|
||||||
|
NIS_SHAREDICON = 0x2
|
||||||
|
|
||||||
|
// IFileOpenDialog options
|
||||||
|
FOS_OVERWRITEPROMPT = 0x2
|
||||||
|
FOS_STRICTFILETYPES = 0x4
|
||||||
|
FOS_NOCHANGEDIR = 0x8
|
||||||
|
FOS_PICKFOLDERS = 0x20
|
||||||
|
FOS_FORCEFILESYSTEM = 0x40
|
||||||
|
FOS_ALLNONSTORAGEITEMS = 0x80
|
||||||
|
FOS_NOVALIDATE = 0x100
|
||||||
|
FOS_ALLOWMULTISELECT = 0x200
|
||||||
|
FOS_PATHMUSTEXIST = 0x800
|
||||||
|
FOS_FILEMUSTEXIST = 0x1000
|
||||||
|
FOS_CREATEPROMPT = 0x2000
|
||||||
|
FOS_SHAREAWARE = 0x4000
|
||||||
|
FOS_NOREADONLYRETURN = 0x8000
|
||||||
|
FOS_NOTESTFILECREATE = 0x10000
|
||||||
|
FOS_HIDEMRUPLACES = 0x20000
|
||||||
|
FOS_HIDEPINNEDPLACES = 0x40000
|
||||||
|
FOS_NODEREFERENCELINKS = 0x100000
|
||||||
|
FOS_OKBUTTONNEEDSINTERACTION = 0x200000
|
||||||
|
FOS_DONTADDTORECENT = 0x2000000
|
||||||
|
FOS_FORCESHOWHIDDEN = 0x10000000
|
||||||
|
FOS_DEFAULTNOMINIMODE = 0x20000000
|
||||||
|
FOS_FORCEPREVIEWPANEON = 0x40000000
|
||||||
|
FOS_SUPPORTSTREAMABLEITEMS = 0x80000000
|
||||||
|
|
||||||
|
SIGDN_NORMALDISPLAY = 0x00000000
|
||||||
|
SIGDN_PARENTRELATIVEPARSING = ^(^0x18001 + 0x80000000)
|
||||||
|
SIGDN_DESKTOPABSOLUTEPARSING = ^(^0x28000 + 0x80000000)
|
||||||
|
SIGDN_PARENTRELATIVEEDITING = ^(^0x31001 + 0x80000000)
|
||||||
|
SIGDN_DESKTOPABSOLUTEEDITING = ^(^0x4c000 + 0x80000000)
|
||||||
|
SIGDN_FILESYSPATH = ^(^0x58000 + 0x80000000)
|
||||||
|
SIGDN_URL = ^(^0x68000 + 0x80000000)
|
||||||
|
SIGDN_PARENTRELATIVEFORADDRESSBAR = ^(^0x7c001 + 0x80000000)
|
||||||
|
SIGDN_PARENTRELATIVE = ^(^0x80001 + 0x80000000)
|
||||||
|
SIGDN_PARENTRELATIVEFORUI = ^(^0x94001 + 0x80000000)
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -49,6 +114,8 @@ type NOTIFYICONDATA struct {
|
||||||
// BalloonIcon Handle // NOTIFYICONDATAA_V3_SIZE
|
// BalloonIcon Handle // NOTIFYICONDATAA_V3_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IDLIST struct{}
|
||||||
|
|
||||||
// https://github.com/wine-mirror/wine/blob/master/include/shobjidl.idl
|
// https://github.com/wine-mirror/wine/blob/master/include/shobjidl.idl
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -57,30 +124,25 @@ var (
|
||||||
CLSID_FileOpenDialog = uuid("\x9c\x5a\x1c\xdc\x8a\xe8\xde\x4d\xa5\xa1\x60\xf8\x2a\x20\xae\xf7")
|
CLSID_FileOpenDialog = uuid("\x9c\x5a\x1c\xdc\x8a\xe8\xde\x4d\xa5\xa1\x60\xf8\x2a\x20\xae\xf7")
|
||||||
)
|
)
|
||||||
|
|
||||||
type IFileOpenDialog struct {
|
type IFileOpenDialog struct{ IFileDialog }
|
||||||
_IFileOpenDialogBase
|
type iFileOpenDialogVtbl struct {
|
||||||
_ *_IFileOpenDialogVtbl
|
iFileDialogVtbl
|
||||||
}
|
|
||||||
|
|
||||||
type _IFileOpenDialogBase struct{ _IFileDialogBase }
|
|
||||||
type _IFileOpenDialogVtbl struct {
|
|
||||||
_IFileDialogVtbl
|
|
||||||
GetResults uintptr
|
GetResults uintptr
|
||||||
GetSelectedItems uintptr
|
GetSelectedItems uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IFileOpenDialogBase) GetResults() (res *IShellItemArray, err error) {
|
func (u *IFileOpenDialog) GetResults() (res *IShellItemArray, err error) {
|
||||||
vtbl := (*(**_IFileOpenDialogVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iFileOpenDialogVtbl)(unsafe.Pointer(u))
|
||||||
hr, _, _ := c.Call(vtbl.GetResults, uintptr(unsafe.Pointer(&res)))
|
hr, _, _ := u.call(vtbl.GetResults, uintptr(unsafe.Pointer(&res)))
|
||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
err = syscall.Errno(hr)
|
err = syscall.Errno(hr)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type _IFileDialogBase struct{ _IModalWindowBase }
|
type IFileDialog struct{ IModalWindow }
|
||||||
type _IFileDialogVtbl struct {
|
type iFileDialogVtbl struct {
|
||||||
_IModalWindowVtbl
|
iModalWindowVtbl
|
||||||
SetFileTypes uintptr
|
SetFileTypes uintptr
|
||||||
SetFileTypeIndex uintptr
|
SetFileTypeIndex uintptr
|
||||||
GetFileTypeIndex uintptr
|
GetFileTypeIndex uintptr
|
||||||
|
@ -106,74 +168,69 @@ type _IFileDialogVtbl struct {
|
||||||
SetFilter uintptr
|
SetFilter uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IFileDialogBase) SetOptions(fos int) (err error) {
|
func (u *IFileDialog) SetOptions(fos int) (err error) {
|
||||||
vtbl := (*(**_IFileDialogVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iFileDialogVtbl)(unsafe.Pointer(u))
|
||||||
hr, _, _ := c.Call(vtbl.SetOptions, uintptr(fos))
|
hr, _, _ := u.call(vtbl.SetOptions, uintptr(fos))
|
||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
err = syscall.Errno(hr)
|
err = syscall.Errno(hr)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IFileDialogBase) GetOptions() (fos int, err error) {
|
func (u *IFileDialog) GetOptions() (fos int, err error) {
|
||||||
vtbl := (*(**_IFileDialogVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iFileDialogVtbl)(unsafe.Pointer(u))
|
||||||
hr, _, _ := c.Call(vtbl.GetOptions, uintptr(unsafe.Pointer(&fos)))
|
hr, _, _ := u.call(vtbl.GetOptions, uintptr(unsafe.Pointer(&fos)))
|
||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
err = syscall.Errno(hr)
|
err = syscall.Errno(hr)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IFileDialogBase) SetFolder(item *IShellItem) (err error) {
|
func (u *IFileDialog) SetFolder(item *IShellItem) (err error) {
|
||||||
vtbl := (*(**_IFileDialogVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iFileDialogVtbl)(unsafe.Pointer(u))
|
||||||
hr, _, _ := c.Call(vtbl.SetFolder, uintptr(unsafe.Pointer(item)))
|
hr, _, _ := u.call(vtbl.SetFolder, uintptr(unsafe.Pointer(item)))
|
||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
err = syscall.Errno(hr)
|
err = syscall.Errno(hr)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IFileDialogBase) SetTitle(title *uint16) (err error) {
|
func (u *IFileDialog) SetTitle(title *uint16) (err error) {
|
||||||
vtbl := (*(**_IFileDialogVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iFileDialogVtbl)(unsafe.Pointer(u))
|
||||||
hr, _, _ := c.Call(vtbl.SetTitle, uintptr(unsafe.Pointer(title)))
|
hr, _, _ := u.call(vtbl.SetTitle, uintptr(unsafe.Pointer(title)))
|
||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
err = syscall.Errno(hr)
|
err = syscall.Errno(hr)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IFileDialogBase) GetResult() (item *IShellItem, err error) {
|
func (u *IFileDialog) GetResult() (item *IShellItem, err error) {
|
||||||
vtbl := (*(**_IFileDialogVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iFileDialogVtbl)(unsafe.Pointer(u))
|
||||||
hr, _, _ := c.Call(vtbl.GetResult, uintptr(unsafe.Pointer(&item)))
|
hr, _, _ := u.call(vtbl.GetResult, uintptr(unsafe.Pointer(&item)))
|
||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
err = syscall.Errno(hr)
|
err = syscall.Errno(hr)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type _IModalWindowBase struct{ _IUnknownBase }
|
type IModalWindow struct{ IUnknown }
|
||||||
type _IModalWindowVtbl struct {
|
type iModalWindowVtbl struct {
|
||||||
_IUnknownVtbl
|
iUnknownVtbl
|
||||||
Show uintptr
|
Show uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IModalWindowBase) Show(wnd HWND) (err error) {
|
func (u *IModalWindow) Show(wnd HWND) (err error) {
|
||||||
vtbl := (*(**_IModalWindowVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iModalWindowVtbl)(unsafe.Pointer(u))
|
||||||
hr, _, _ := c.Call(vtbl.Show, uintptr(wnd))
|
hr, _, _ := u.call(vtbl.Show, uintptr(wnd))
|
||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
err = syscall.Errno(hr)
|
err = syscall.Errno(hr)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type IShellItem struct {
|
type IShellItem struct{ IUnknown }
|
||||||
_IShellItemBase
|
type iShellItemVtbl struct {
|
||||||
_ *_IShellItemVtbl
|
iUnknownVtbl
|
||||||
}
|
|
||||||
|
|
||||||
type _IShellItemBase struct{ _IUnknownBase }
|
|
||||||
type _IShellItemVtbl struct {
|
|
||||||
_IUnknownVtbl
|
|
||||||
BindToHandler uintptr
|
BindToHandler uintptr
|
||||||
GetParent uintptr
|
GetParent uintptr
|
||||||
GetDisplayName uintptr
|
GetDisplayName uintptr
|
||||||
|
@ -181,10 +238,10 @@ type _IShellItemVtbl struct {
|
||||||
Compare uintptr
|
Compare uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IShellItemBase) GetDisplayName(name int) (res string, err error) {
|
func (u *IShellItem) GetDisplayName(name int) (res string, err error) {
|
||||||
var ptr uintptr
|
var ptr uintptr
|
||||||
vtbl := (*(**_IShellItemVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iShellItemVtbl)(unsafe.Pointer(u))
|
||||||
hr, _, _ := c.Call(vtbl.GetDisplayName, uintptr(name), uintptr(unsafe.Pointer(&ptr)))
|
hr, _, _ := u.call(vtbl.GetDisplayName, uintptr(name), uintptr(unsafe.Pointer(&ptr)))
|
||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
err = syscall.Errno(hr)
|
err = syscall.Errno(hr)
|
||||||
} else {
|
} else {
|
||||||
|
@ -196,14 +253,9 @@ func (c *_IShellItemBase) GetDisplayName(name int) (res string, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type IShellItemArray struct {
|
type IShellItemArray struct{ IUnknown }
|
||||||
_IShellItemArrayBase
|
type iShellItemArrayVtbl struct {
|
||||||
_ *_IShellItemArrayVtbl
|
iUnknownVtbl
|
||||||
}
|
|
||||||
|
|
||||||
type _IShellItemArrayBase struct{ _IUnknownBase }
|
|
||||||
type _IShellItemArrayVtbl struct {
|
|
||||||
_IUnknownVtbl
|
|
||||||
BindToHandler uintptr
|
BindToHandler uintptr
|
||||||
GetPropertyStore uintptr
|
GetPropertyStore uintptr
|
||||||
GetPropertyDescriptionList uintptr
|
GetPropertyDescriptionList uintptr
|
||||||
|
@ -213,25 +265,25 @@ type _IShellItemArrayVtbl struct {
|
||||||
EnumItems uintptr
|
EnumItems uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IShellItemArrayBase) GetCount() (numItems uint32, err error) {
|
func (u *IShellItemArray) GetCount() (numItems uint32, err error) {
|
||||||
vtbl := (*(**_IShellItemArrayVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iShellItemArrayVtbl)(unsafe.Pointer(u))
|
||||||
hr, _, _ := c.Call(vtbl.GetCount, uintptr(unsafe.Pointer(&numItems)))
|
hr, _, _ := u.call(vtbl.GetCount, uintptr(unsafe.Pointer(&numItems)))
|
||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
err = syscall.Errno(hr)
|
err = syscall.Errno(hr)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *_IShellItemArrayBase) GetItemAt(index uint32) (item *IShellItem, err error) {
|
func (u *IShellItemArray) GetItemAt(index uint32) (item *IShellItem, err error) {
|
||||||
vtbl := (*(**_IShellItemArrayVtbl)(unsafe.Pointer(c)))
|
vtbl := *(**iShellItemArrayVtbl)(unsafe.Pointer(u))
|
||||||
hr, _, _ := c.Call(vtbl.GetItemAt, uintptr(index), uintptr(unsafe.Pointer(&item)))
|
hr, _, _ := u.call(vtbl.GetItemAt, uintptr(index), uintptr(unsafe.Pointer(&item)))
|
||||||
if hr != 0 {
|
if hr != 0 {
|
||||||
err = syscall.Errno(hr)
|
err = syscall.Errno(hr)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys SHBrowseForFolder(bi *BROWSEINFO) (ret Pointer) = shell32.SHBrowseForFolder
|
//sys SHBrowseForFolder(bi *BROWSEINFO) (ret *IDLIST) = shell32.SHBrowseForFolder
|
||||||
//sys SHCreateItemFromParsingName(path *uint16, bc *COMObject, iid uintptr, item **IShellItem) (res error) = shell32.SHCreateItemFromParsingName
|
//sys SHCreateItemFromParsingName(path *uint16, bc *IBindCtx, iid uintptr, item **IShellItem) (res error) = shell32.SHCreateItemFromParsingName
|
||||||
//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
|
||||||
//sys SHGetPathFromIDListEx(ptr Pointer, path *uint16, pathLen int, opts int) (ok bool) = shell32.SHGetPathFromIDListEx
|
//sys SHGetPathFromIDListEx(ptr *IDLIST, path *uint16, pathLen int, opts int) (ok bool) = shell32.SHGetPathFromIDListEx
|
||||||
|
|
|
@ -19,6 +19,9 @@ const (
|
||||||
IDYES = 6
|
IDYES = 6
|
||||||
IDNO = 7
|
IDNO = 7
|
||||||
|
|
||||||
|
// Control IDs
|
||||||
|
IDC_STATIC_OK = 20
|
||||||
|
|
||||||
// MessageBox types
|
// MessageBox types
|
||||||
MB_OK = windows.MB_OK
|
MB_OK = windows.MB_OK
|
||||||
MB_OKCANCEL = windows.MB_OKCANCEL
|
MB_OKCANCEL = windows.MB_OKCANCEL
|
||||||
|
@ -60,7 +63,7 @@ const (
|
||||||
STM_SETICON = 0x0170
|
STM_SETICON = 0x0170
|
||||||
|
|
||||||
// CreateWindow
|
// CreateWindow
|
||||||
CW_USEDEFAULT = 0x80000000
|
CW_USEDEFAULT = -0x80000000
|
||||||
|
|
||||||
// Window classes
|
// Window classes
|
||||||
PROGRESS_CLASS = "msctls_progress32"
|
PROGRESS_CLASS = "msctls_progress32"
|
||||||
|
@ -217,18 +220,34 @@ const (
|
||||||
// SetWindowsHookEx types
|
// SetWindowsHookEx types
|
||||||
WH_CALLWNDPROCRET = 12
|
WH_CALLWNDPROCRET = 12
|
||||||
|
|
||||||
USER_DEFAULT_SCREEN_DPI = 96
|
// System colors
|
||||||
|
COLOR_WINDOW = 5
|
||||||
|
|
||||||
|
// DPI awareness
|
||||||
|
USER_DEFAULT_SCREEN_DPI = 96
|
||||||
DPI_AWARENESS_CONTEXT_UNAWARE = ^uintptr(1) + 1
|
DPI_AWARENESS_CONTEXT_UNAWARE = ^uintptr(1) + 1
|
||||||
DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = ^uintptr(2) + 1
|
DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = ^uintptr(2) + 1
|
||||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ^uintptr(3) + 1
|
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = ^uintptr(3) + 1
|
||||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = ^uintptr(4) + 1
|
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = ^uintptr(4) + 1
|
||||||
DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED = ^uintptr(5) + 1
|
DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED = ^uintptr(5) + 1
|
||||||
|
|
||||||
|
// LoadImage type
|
||||||
IMAGE_BITMAP = 0
|
IMAGE_BITMAP = 0
|
||||||
IMAGE_ICON = 1
|
IMAGE_ICON = 1
|
||||||
IMAGE_CURSOR = 2
|
IMAGE_CURSOR = 2
|
||||||
|
|
||||||
|
// LoadIcon resources
|
||||||
|
IDI_APPLICATION = 32512
|
||||||
|
IDI_ERROR = 32513
|
||||||
|
IDI_HAND = 32513
|
||||||
|
IDI_QUESTION = 32514
|
||||||
|
IDI_WARNING = 32515
|
||||||
|
IDI_EXCLAMATION = 32515
|
||||||
|
IDI_ASTERISK = 32516
|
||||||
|
IDI_INFORMATION = 32516
|
||||||
|
IDI_WINLOGO = 32517
|
||||||
|
IDI_SHIELD = 32518
|
||||||
|
|
||||||
// LoadResource (image/icon) flags
|
// LoadResource (image/icon) flags
|
||||||
LR_DEFAULTCOLOR = 0x00000000
|
LR_DEFAULTCOLOR = 0x00000000
|
||||||
LR_MONOCHROME = 0x00000001
|
LR_MONOCHROME = 0x00000001
|
||||||
|
|
|
@ -7,7 +7,7 @@ import "golang.org/x/sys/windows"
|
||||||
|
|
||||||
type Handle = windows.Handle
|
type Handle = windows.Handle
|
||||||
type HWND = windows.HWND
|
type HWND = windows.HWND
|
||||||
type Pointer uintptr
|
type Pointer = windows.Pointer
|
||||||
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime
|
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime
|
||||||
type SYSTEMTIME struct {
|
type SYSTEMTIME struct {
|
||||||
|
|
|
@ -62,7 +62,6 @@ var (
|
||||||
procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW")
|
procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW")
|
||||||
procReleaseActCtx = modkernel32.NewProc("ReleaseActCtx")
|
procReleaseActCtx = modkernel32.NewProc("ReleaseActCtx")
|
||||||
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")
|
||||||
|
@ -199,7 +198,7 @@ func ReleaseActCtx(actCtx Handle) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func CoCreateInstance(clsid uintptr, unkOuter *COMObject, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) {
|
func CoCreateInstance(clsid uintptr, unkOuter *IUnknown, clsContext int32, iid uintptr, address unsafe.Pointer) (res error) {
|
||||||
r0, _, _ := syscall.Syscall6(procCoCreateInstance.Addr(), 5, uintptr(clsid), uintptr(unsafe.Pointer(unkOuter)), uintptr(clsContext), uintptr(iid), uintptr(address), 0)
|
r0, _, _ := syscall.Syscall6(procCoCreateInstance.Addr(), 5, uintptr(clsid), uintptr(unsafe.Pointer(unkOuter)), uintptr(clsContext), uintptr(iid), uintptr(address), 0)
|
||||||
if r0 != 0 {
|
if r0 != 0 {
|
||||||
res = syscall.Errno(r0)
|
res = syscall.Errno(r0)
|
||||||
|
@ -207,18 +206,13 @@ func CoCreateInstance(clsid uintptr, unkOuter *COMObject, clsContext int32, iid
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func CoTaskMemFree(address Pointer) {
|
func SHBrowseForFolder(bi *BROWSEINFO) (ret *IDLIST) {
|
||||||
syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(address), 0, 0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func SHBrowseForFolder(bi *BROWSEINFO) (ret Pointer) {
|
|
||||||
r0, _, _ := syscall.Syscall(procSHBrowseForFolder.Addr(), 1, uintptr(unsafe.Pointer(bi)), 0, 0)
|
r0, _, _ := syscall.Syscall(procSHBrowseForFolder.Addr(), 1, uintptr(unsafe.Pointer(bi)), 0, 0)
|
||||||
ret = Pointer(r0)
|
ret = (*IDLIST)(unsafe.Pointer(r0))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SHCreateItemFromParsingName(path *uint16, bc *COMObject, iid uintptr, item **IShellItem) (res error) {
|
func SHCreateItemFromParsingName(path *uint16, bc *IBindCtx, iid uintptr, item **IShellItem) (res error) {
|
||||||
r0, _, _ := syscall.Syscall6(procSHCreateItemFromParsingName.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(bc)), uintptr(iid), uintptr(unsafe.Pointer(item)), 0, 0)
|
r0, _, _ := syscall.Syscall6(procSHCreateItemFromParsingName.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(bc)), uintptr(iid), uintptr(unsafe.Pointer(item)), 0, 0)
|
||||||
if r0 != 0 {
|
if r0 != 0 {
|
||||||
res = syscall.Errno(r0)
|
res = syscall.Errno(r0)
|
||||||
|
@ -226,8 +220,8 @@ func SHCreateItemFromParsingName(path *uint16, bc *COMObject, iid uintptr, item
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SHGetPathFromIDListEx(ptr Pointer, path *uint16, pathLen int, opts int) (ok bool) {
|
func SHGetPathFromIDListEx(ptr *IDLIST, 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(unsafe.Pointer(ptr)), uintptr(unsafe.Pointer(path)), uintptr(pathLen), uintptr(opts), 0, 0)
|
||||||
ok = r0 != 0
|
ok = r0 != 0
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,7 +187,7 @@ func listProc(wnd win.HWND, msg uint32, wparam uintptr, lparam *unsafe.Pointer)
|
||||||
dlg.out = make([]string, len)
|
dlg.out = make([]string, len)
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
indices := make([]int32, len)
|
indices := make([]int32, len)
|
||||||
win.SendMessage(dlg.listCtl, win.LB_GETSELITEMS, len, uintptr(unsafe.Pointer(&indices[0])))
|
win.SendMessagePointer(dlg.listCtl, win.LB_GETSELITEMS, len, unsafe.Pointer(&indices[0]))
|
||||||
for i, idx := range indices {
|
for i, idx := range indices {
|
||||||
dlg.out[i] = dlg.items[idx]
|
dlg.out[i] = dlg.items[idx]
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,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) {
|
||||||
|
// TODO: use GetDlgItem, SetDlgItemText instead of EnumChildWindows.
|
||||||
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),
|
||||||
unsafe.Pointer(&opts))
|
unsafe.Pointer(&opts))
|
||||||
|
@ -110,7 +111,7 @@ func hookMessageDialogCallback(wnd win.HWND, lparam *options) uintptr {
|
||||||
win.SetWindowText(wnd, strptr(*text))
|
win.SetWindowText(wnd, strptr(*text))
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctl == 20 /*IDC_STATIC_OK*/ {
|
if ctl == win.IDC_STATIC_OK {
|
||||||
icon := getIcon(lparam.icon)
|
icon := getIcon(lparam.icon)
|
||||||
if icon.handle != 0 {
|
if icon.handle != 0 {
|
||||||
defer icon.delete()
|
defer icon.delete()
|
||||||
|
|
|
@ -19,8 +19,8 @@ func notify(text string, opts options) error {
|
||||||
var args win.NOTIFYICONDATA
|
var args win.NOTIFYICONDATA
|
||||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||||
args.ID = rand.Uint32()
|
args.ID = rand.Uint32()
|
||||||
args.Flags = 0x00000010 // NIF_INFO
|
args.Flags = win.NIF_INFO
|
||||||
args.State = 0x00000001 // NIS_HIDDEN
|
args.State = win.NIS_HIDDEN
|
||||||
|
|
||||||
info := syscall.StringToUTF16(text)
|
info := syscall.StringToUTF16(text)
|
||||||
copy(args.Info[:len(args.Info)-1], info)
|
copy(args.Info[:len(args.Info)-1], info)
|
||||||
|
@ -32,18 +32,18 @@ func notify(text string, opts options) error {
|
||||||
|
|
||||||
switch opts.icon {
|
switch opts.icon {
|
||||||
case InfoIcon, QuestionIcon:
|
case InfoIcon, QuestionIcon:
|
||||||
args.InfoFlags |= 0x1 // NIIF_INFO
|
args.InfoFlags |= win.NIIF_INFO
|
||||||
case WarningIcon:
|
case WarningIcon:
|
||||||
args.InfoFlags |= 0x2 // NIIF_WARNING
|
args.InfoFlags |= win.NIIF_WARNING
|
||||||
case ErrorIcon:
|
case ErrorIcon:
|
||||||
args.InfoFlags |= 0x3 // NIIF_ERROR
|
args.InfoFlags |= win.NIIF_ERROR
|
||||||
default:
|
default:
|
||||||
icon := getIcon(opts.icon)
|
icon := getIcon(opts.icon)
|
||||||
if icon.handle != 0 {
|
if icon.handle != 0 {
|
||||||
defer icon.delete()
|
defer icon.delete()
|
||||||
args.Icon = win.Handle(icon.handle)
|
args.Icon = win.Handle(icon.handle)
|
||||||
args.Flags |= 0x00000002 // NIF_ICON
|
args.Flags |= win.NIF_ICON
|
||||||
args.InfoFlags |= 0x4 // NIIF_USER
|
args.InfoFlags |= win.NIIF_USER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,6 @@ const (
|
||||||
_WS_ZEN_BUTTON = _WS_ZEN_CONTROL
|
_WS_ZEN_BUTTON = _WS_ZEN_CONTROL
|
||||||
)
|
)
|
||||||
|
|
||||||
const nullptr win.Pointer = 0
|
|
||||||
|
|
||||||
func intptr(i int64) uintptr { return uintptr(i) }
|
func intptr(i int64) uintptr { return uintptr(i) }
|
||||||
func strptr(s string) *uint16 { return syscall.StringToUTF16Ptr(s) }
|
func strptr(s string) *uint16 { return syscall.StringToUTF16Ptr(s) }
|
||||||
|
|
||||||
|
@ -56,7 +54,7 @@ func setup() context.CancelFunc {
|
||||||
|
|
||||||
var icc win.INITCOMMONCONTROLSEX
|
var icc win.INITCOMMONCONTROLSEX
|
||||||
icc.Size = uint32(unsafe.Sizeof(icc))
|
icc.Size = uint32(unsafe.Sizeof(icc))
|
||||||
icc.ICC = 0x00004020 // ICC_STANDARD_CLASSES|ICC_PROGRESS_CLASS
|
icc.ICC = win.ICC_STANDARD_CLASSES | win.ICC_DATE_CLASSES | win.ICC_PROGRESS_CLASS
|
||||||
win.InitCommonControlsEx(&icc)
|
win.InitCommonControlsEx(&icc)
|
||||||
|
|
||||||
return func() {
|
return func() {
|
||||||
|
@ -264,13 +262,13 @@ func getIcon(i any) icon {
|
||||||
var resource uintptr
|
var resource uintptr
|
||||||
switch i {
|
switch i {
|
||||||
case ErrorIcon:
|
case ErrorIcon:
|
||||||
resource = 32513 // IDI_ERROR
|
resource = win.IDI_ERROR
|
||||||
case QuestionIcon:
|
case QuestionIcon:
|
||||||
resource = 32514 // IDI_QUESTION
|
resource = win.IDI_QUESTION
|
||||||
case WarningIcon:
|
case WarningIcon:
|
||||||
resource = 32515 // IDI_WARNING
|
resource = win.IDI_WARNING
|
||||||
case InfoIcon:
|
case InfoIcon:
|
||||||
resource = 32516 // IDI_INFORMATION
|
resource = win.IDI_INFORMATION
|
||||||
}
|
}
|
||||||
if resource != 0 {
|
if resource != 0 {
|
||||||
res.handle, _ = win.LoadIcon(0, resource)
|
res.handle, _ = win.LoadIcon(0, resource)
|
||||||
|
@ -331,7 +329,7 @@ func registerClass(instance, icon win.Handle, proc uintptr) (*uint16, error) {
|
||||||
wcx.WndProc = proc
|
wcx.WndProc = proc
|
||||||
wcx.Icon = icon
|
wcx.Icon = icon
|
||||||
wcx.Instance = instance
|
wcx.Instance = instance
|
||||||
wcx.Background = 5 // COLOR_WINDOW
|
wcx.Background = win.COLOR_WINDOW
|
||||||
wcx.ClassName = strptr(name)
|
wcx.ClassName = strptr(name)
|
||||||
|
|
||||||
if err := win.RegisterClassEx(&wcx); err != nil {
|
if err := win.RegisterClassEx(&wcx); err != nil {
|
||||||
|
|
Loading…
Reference in a new issue