File dialogs for windows.
This commit is contained in:
parent
69e5f7ad01
commit
72f0fafe46
1 changed files with 155 additions and 0 deletions
155
dialog/dialog_windows.go
Normal file
155
dialog/dialog_windows.go
Normal file
|
@ -0,0 +1,155 @@
|
|||
package dialog
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func OpenFile(title, defaultPath string, filters []FileFilter) (string, error) {
|
||||
comdlg32 := syscall.NewLazyDLL("comdlg32.dll")
|
||||
getOpenFileName := comdlg32.NewProc("GetOpenFileNameW")
|
||||
|
||||
var args _OPENFILENAME
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
|
||||
if title != "" {
|
||||
args.Title = syscall.StringToUTF16Ptr(title)
|
||||
}
|
||||
if defaultPath != "" {
|
||||
args.InitialDir = syscall.StringToUTF16Ptr(defaultPath)
|
||||
}
|
||||
args.Filter = &windowsFilters(filters)[0]
|
||||
|
||||
res := [1024]uint16{}
|
||||
args.File = &res[0]
|
||||
args.MaxFile = uint32(len(res))
|
||||
|
||||
_, _, _ = getOpenFileName.Call(uintptr(unsafe.Pointer(&args)))
|
||||
return syscall.UTF16ToString(res[:]), nil
|
||||
}
|
||||
|
||||
func OpenFiles(title, defaultPath string, filters []FileFilter) ([]string, error) {
|
||||
comdlg32 := syscall.NewLazyDLL("comdlg32.dll")
|
||||
getOpenFileName := comdlg32.NewProc("GetOpenFileNameW")
|
||||
|
||||
var args _OPENFILENAME
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
args.Flags = 0x00080200 // OFN_ALLOWMULTISELECT|OFN_EXPLORER
|
||||
|
||||
if title != "" {
|
||||
args.Title = syscall.StringToUTF16Ptr(title)
|
||||
}
|
||||
if defaultPath != "" {
|
||||
args.InitialDir = syscall.StringToUTF16Ptr(defaultPath)
|
||||
}
|
||||
args.Filter = &windowsFilters(filters)[0]
|
||||
|
||||
res := [65536]uint16{}
|
||||
args.File = &res[0]
|
||||
args.MaxFile = uint32(len(res))
|
||||
|
||||
_, _, _ = getOpenFileName.Call(uintptr(unsafe.Pointer(&args)))
|
||||
|
||||
var i int
|
||||
var nul bool
|
||||
var split []string
|
||||
for j, p := range res {
|
||||
if p == 0 {
|
||||
if nul {
|
||||
break
|
||||
}
|
||||
if i < j {
|
||||
split = append(split, string(utf16.Decode(res[i:j])))
|
||||
}
|
||||
i = j + 1
|
||||
nul = true
|
||||
} else {
|
||||
nul = false
|
||||
}
|
||||
}
|
||||
if len := len(split) - 1; len > 0 {
|
||||
base := split[0]
|
||||
for i := 0; i < len; i++ {
|
||||
split[i] = filepath.Join(base, string(split[i+1]))
|
||||
}
|
||||
split = split[:len]
|
||||
}
|
||||
return split, nil
|
||||
}
|
||||
|
||||
func SaveFile(title, defaultPath string, confirmOverwrite bool, filters []FileFilter) (string, error) {
|
||||
comdlg32 := syscall.NewLazyDLL("comdlg32.dll")
|
||||
getSaveFileName := comdlg32.NewProc("GetSaveFileNameW")
|
||||
|
||||
var args _OPENFILENAME
|
||||
args.StructSize = uint32(unsafe.Sizeof(args))
|
||||
|
||||
if title != "" {
|
||||
args.Title = syscall.StringToUTF16Ptr(title)
|
||||
}
|
||||
if defaultPath != "" {
|
||||
args.InitialDir = syscall.StringToUTF16Ptr(defaultPath)
|
||||
}
|
||||
if confirmOverwrite {
|
||||
args.Flags |= 0x00000002 // OFN_OVERWRITEPROMPT
|
||||
}
|
||||
args.Filter = &windowsFilters(filters)[0]
|
||||
|
||||
res := [1024]uint16{}
|
||||
args.File = &res[0]
|
||||
args.MaxFile = uint32(len(res))
|
||||
|
||||
_, _, _ = getSaveFileName.Call(uintptr(unsafe.Pointer(&args)))
|
||||
return syscall.UTF16ToString(res[:]), nil
|
||||
}
|
||||
|
||||
func PickFolder(title, defaultPath string) (string, error) {
|
||||
// TODO
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func windowsFilters(filters []FileFilter) []uint16 {
|
||||
var res []uint16
|
||||
for _, f := range filters {
|
||||
res = append(res, utf16.Encode([]rune(f.Name))...)
|
||||
res = append(res, 0)
|
||||
for _, e := range f.Exts {
|
||||
res = append(res, uint16('*'))
|
||||
res = append(res, utf16.Encode([]rune(e))...)
|
||||
res = append(res, uint16(';'))
|
||||
}
|
||||
res = append(res, 0)
|
||||
}
|
||||
if res != nil {
|
||||
res = append(res, 0)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
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 unsafe.Pointer
|
||||
DwReserved uint32
|
||||
FlagsEx uint32
|
||||
}
|
Loading…
Reference in a new issue