Use IFileSaveDialog where available.
This commit is contained in:
parent
c56588920f
commit
77da6e29f3
2 changed files with 96 additions and 0 deletions
|
@ -130,6 +130,10 @@ func selectFileMultiple(opts options) ([]string, error) {
|
|||
}
|
||||
|
||||
func selectFileSave(opts options) (string, error) {
|
||||
name, shown, err := fileSaveDialog(opts)
|
||||
if shown || opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return name, err
|
||||
}
|
||||
if opts.directory {
|
||||
return selectFile(opts)
|
||||
}
|
||||
|
@ -280,6 +284,86 @@ func fileOpenDialog(opts options, multi bool) (string, []string, bool, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func fileSaveDialog(opts options) (string, bool, error) {
|
||||
uninit, err := coInitialize()
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
defer uninit()
|
||||
|
||||
owner, _ := opts.attach.(win.HWND)
|
||||
defer setup(owner)()
|
||||
|
||||
var dialog *win.IFileSaveDialog
|
||||
err = win.CoCreateInstance(
|
||||
win.CLSID_FileSaveDialog, nil, win.CLSCTX_ALL,
|
||||
win.IID_IFileSaveDialog, unsafe.Pointer(&dialog))
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
defer dialog.Release()
|
||||
|
||||
flgs, err := dialog.GetOptions()
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
flgs |= win.FOS_NOCHANGEDIR | win.FOS_PATHMUSTEXIST | win.FOS_NOREADONLYRETURN | win.FOS_FORCEFILESYSTEM
|
||||
if opts.confirmOverwrite {
|
||||
flgs |= win.FOS_OVERWRITEPROMPT
|
||||
}
|
||||
if opts.confirmCreate {
|
||||
flgs |= win.FOS_CREATEPROMPT
|
||||
}
|
||||
if opts.showHidden {
|
||||
flgs |= win.FOS_FORCESHOWHIDDEN
|
||||
}
|
||||
err = dialog.SetOptions(flgs)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
if opts.title != nil {
|
||||
dialog.SetTitle(strptr(*opts.title))
|
||||
}
|
||||
|
||||
if opts.filename != "" {
|
||||
var item *win.IShellItem
|
||||
dir, name, _ := splitDirAndName(opts.filename)
|
||||
dialog.SetFileName(strptr(name))
|
||||
if ext := filepath.Ext(name); len(ext) > 1 {
|
||||
dialog.SetDefaultExtension(strptr(ext[1:]))
|
||||
}
|
||||
win.SHCreateItemFromParsingName(strptr(dir), nil, win.IID_IShellItem, &item)
|
||||
if item != nil {
|
||||
defer item.Release()
|
||||
dialog.SetFolder(item)
|
||||
}
|
||||
}
|
||||
|
||||
unhook, err := hookDialog(opts.ctx, opts.windowIcon, nil, nil)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
defer unhook()
|
||||
|
||||
err = dialog.Show(owner)
|
||||
if opts.ctx != nil && opts.ctx.Err() != nil {
|
||||
return "", true, opts.ctx.Err()
|
||||
}
|
||||
if err == win.E_CANCELED {
|
||||
return "", true, ErrCanceled
|
||||
}
|
||||
if err != nil {
|
||||
return "", true, err
|
||||
}
|
||||
|
||||
str, err := shellItemPath(dialog.GetResult())
|
||||
if err != nil {
|
||||
return "", true, err
|
||||
}
|
||||
return str, true, nil
|
||||
}
|
||||
|
||||
func shellItemPath(item *win.IShellItem, err error) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
|
@ -123,7 +123,9 @@ type IDLIST struct{}
|
|||
var (
|
||||
IID_IShellItem = guid("\x1e\x6d\x82\x43\x18\xe7\xee\x42\xbc\x55\xa1\xe2\x61\xc3\x7b\xfe")
|
||||
IID_IFileOpenDialog = guid("\x88\x72\x7c\xd5\xad\xd4\x68\x47\xbe\x02\x9d\x96\x95\x32\xd9\x60")
|
||||
IID_IFileSaveDialog = guid("\x23\xcd\xbc\x84\xde\x5f\xdb\x4c\xae\xa4\xaf\x64\xb8\x3d\x78\xab")
|
||||
CLSID_FileOpenDialog = guid("\x9c\x5a\x1c\xdc\x8a\xe8\xde\x4d\xa5\xa1\x60\xf8\x2a\x20\xae\xf7")
|
||||
CLSID_FileSaveDialog = guid("\xf3\xe2\xb4\xc0\x21\xba\x73\x47\x8d\xba\x33\x5e\xc9\x46\xeb\x8b")
|
||||
)
|
||||
|
||||
type IFileOpenDialog struct{ IFileDialog }
|
||||
|
@ -142,6 +144,16 @@ func (u *IFileOpenDialog) GetResults() (res *IShellItemArray, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
type IFileSaveDialog struct{ IFileDialog }
|
||||
type IFileSaveDialogVtbl struct {
|
||||
iFileDialogVtbl
|
||||
SetSaveAsItem uintptr
|
||||
SetProperties uintptr
|
||||
SetCollectedProperties uintptr
|
||||
GetProperties uintptr
|
||||
ApplyProperties uintptr
|
||||
}
|
||||
|
||||
type IFileDialog struct{ IModalWindow }
|
||||
type iFileDialogVtbl struct {
|
||||
iModalWindowVtbl
|
||||
|
|
Loading…
Reference in a new issue