This repository has been archived by the owner on Jun 3, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 44
/
file_windows.go
99 lines (78 loc) · 2.58 KB
/
file_windows.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// +build windows,!linux,!darwin,!js
package dlgs
import (
"path/filepath"
"strings"
"syscall"
"unsafe"
)
// File displays a file dialog, returning the selected file or directory, a bool for success, and an
// error if it was unable to display the dialog. Filter is a string that determines
// which extensions should be displayed for the dialog. Separate multiple file
// extensions by spaces and use "*.extension" format for cross-platform compatibility, e.g. "*.png *.jpg".
// A blank string for the filter will display all file types.
func File(title, filter string, directory bool) (string, bool, error) {
if directory {
out, ok := dirDialog(title)
return out, ok, nil
}
out, ok := fileDialog(title, filter, false)
return out, ok, nil
}
// FileMulti displays a file dialog that allows for selecting multiple files. It returns the selected
// files, a bool for success, and an error if it was unable to display the dialog. Filter is a string
// that determines which files should be available for selection in the dialog. Separate multiple file
// extensions by spaces and use "*.extension" format for cross-platform compatibility, e.g. "*.png *.jpg".
// A blank string for the filter will display all file types.
func FileMulti(title, filter string) ([]string, bool, error) {
out, ok := fileDialog(title, filter, true)
files := make([]string, 0)
if !ok {
return files, ok, nil
}
l := strings.Split(out, "\x00")
if len(l) > 1 {
for _, p := range l[1:] {
files = append(files, filepath.Join(l[0], p))
}
} else {
files = append(files, out)
}
return files, ok, nil
}
// fileDialog displays file dialog.
func fileDialog(title, filter string, multi bool) (string, bool) {
var ofn openfilenameW
buf := make([]uint16, maxPath)
t, _ := syscall.UTF16PtrFromString(title)
ofn.lStructSize = uint32(unsafe.Sizeof(ofn))
ofn.lpstrTitle = t
ofn.lpstrFile = &buf[0]
ofn.nMaxFile = uint32(len(buf))
if filter != "" {
ofn.lpstrFilter = utf16PtrFromString(filter)
}
flags := ofnExplorer | ofnFileMustExist | ofnHideReadOnly
if multi {
flags |= ofnAllowMultiSelect
}
ofn.flags = uint32(flags)
if getOpenFileName(&ofn) {
return stringFromUtf16Ptr(ofn.lpstrFile), true
}
return "", false
}
// dirDialog displays directory dialog.
func dirDialog(title string) (string, bool) {
var bi browseinfoW
buf := make([]uint16, maxPath)
t, _ := syscall.UTF16PtrFromString(title)
bi.title = t
bi.flags = bifEditBox | bifNewDialogStyle
lpItem := shBrowseForFolder(&bi)
ok := shGetPathFromIDList(lpItem, &buf[0])
if ok {
return stringFromUtf16Ptr(&buf[0]), true
}
return "", false
}