Skip to content

Commit 3fca0b7

Browse files
committed
add windows support
1 parent 941ef6f commit 3fca0b7

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

image_picker/file_unsupported.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build !darwin,!linux
1+
// +build !darwin,!linux,!windows
22

33
package image_picker
44

image_picker/file_windows.go

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package image_picker
2+
3+
import (
4+
"strings"
5+
"syscall"
6+
"unicode/utf16"
7+
"unsafe"
8+
9+
"github.com/pkg/errors"
10+
)
11+
12+
var (
13+
comdlg32 = syscall.NewLazyDLL("comdlg32.dll")
14+
getOpenFileNameW = comdlg32.NewProc("GetOpenFileNameW")
15+
)
16+
17+
const (
18+
maxPath = 260
19+
ofnExplorer = 0x00080000
20+
ofnFileMustExist = 0x00001000
21+
ofnHideReadOnly = 0x00000004
22+
)
23+
24+
type openfilenameW struct {
25+
lStructSize uint32
26+
hwndOwner syscall.Handle
27+
hInstance syscall.Handle
28+
lpstrFilter *uint16
29+
lpstrCustomFilter *uint16
30+
nMaxCustFilter uint32
31+
nFilterIndex uint32
32+
lpstrFile *uint16
33+
nMaxFile uint32
34+
lpstrFileTitle *uint16
35+
nMaxFileTitle uint32
36+
lpstrInitialDir *uint16
37+
lpstrTitle *uint16
38+
flags uint32
39+
nFileOffset uint16
40+
nFileExtension uint16
41+
lpstrDefExt *uint16
42+
lCustData uintptr
43+
lpfnHook syscall.Handle
44+
lpTemplateName *uint16
45+
pvReserved unsafe.Pointer
46+
dwReserved uint32
47+
flagsEx uint32
48+
}
49+
50+
func utf16PtrFromString(s string) *uint16 {
51+
b := utf16.Encode([]rune(s))
52+
return &b[0]
53+
}
54+
55+
func stringFromUtf16Ptr(p *uint16) string {
56+
b := *(*[maxPath]uint16)(unsafe.Pointer(p))
57+
r := utf16.Decode(b[:])
58+
return strings.Trim(string(r), "\x00")
59+
}
60+
61+
func getOpenFileName(lpofn *openfilenameW) bool {
62+
ret, _, _ := getOpenFileNameW.Call(uintptr(unsafe.Pointer(lpofn)), 0, 0)
63+
return ret != 0
64+
}
65+
66+
func fileDialog(title string, fileType string) (string, error) {
67+
var ofn openfilenameW
68+
buf := make([]uint16, maxPath)
69+
70+
t, _ := syscall.UTF16PtrFromString(title)
71+
72+
ofn.lStructSize = uint32(unsafe.Sizeof(ofn))
73+
ofn.lpstrTitle = t
74+
ofn.lpstrFile = &buf[0]
75+
ofn.nMaxFile = uint32(len(buf))
76+
77+
var filters string
78+
switch fileType {
79+
case "image":
80+
filters = "Images (*.jpeg,*.png,*.gif)\x00*.jpg;*.jpeg;*.png;*.gif\x00All Files (*.*)\x00*.*\x00\x00"
81+
case "video":
82+
filters = "Videos (*.webm,*.wmv,*.mpeg,*.mkv,*.mp4,*.avi,*.mov,*.flv)\x00*.webm;*.wmv;*.mpeg;*.mkv;*mp4;*.avi;*.mov;*.flv\x00All Files (*.*)\x00*.*\x00\x00"
83+
default:
84+
return "", errors.New("unsupported fileType")
85+
}
86+
87+
if filters != "" {
88+
ofn.lpstrFilter = utf16PtrFromString(filters)
89+
}
90+
91+
flags := ofnExplorer | ofnFileMustExist | ofnHideReadOnly
92+
93+
ofn.flags = uint32(flags)
94+
95+
if getOpenFileName(&ofn) {
96+
return stringFromUtf16Ptr(ofn.lpstrFile), nil
97+
}
98+
99+
return "", nil
100+
101+
}

0 commit comments

Comments
 (0)