Files
u-desktop/dialog.go

162 lines
4.0 KiB
Go

package main
import (
"fmt"
"unicode/utf16"
"unsafe"
"golang.org/x/sys/windows"
)
var (
comdlg32 = windows.NewLazySystemDLL("comdlg32.dll")
procGetOpenFileNameW = comdlg32.NewProc("GetOpenFileNameW")
procChooseColorW = comdlg32.NewProc("ChooseColorW")
shell32 = windows.NewLazySystemDLL("shell32.dll")
procSHBrowseForFolderW = shell32.NewProc("SHBrowseForFolderW")
procSHGetPathFromIDListW = shell32.NewProc("SHGetPathFromIDListW")
ole32dll = windows.NewLazySystemDLL("ole32.dll")
procCoTaskMemFree = ole32dll.NewProc("CoTaskMemFree")
)
func slicePtr(s interface{}) uintptr {
switch v := s.(type) {
case []uint16:
if len(v) == 0 {
return 0
}
return uintptr(unsafe.Pointer(&v[0]))
case []uint32:
if len(v) == 0 {
return 0
}
return uintptr(unsafe.Pointer(&v[0]))
}
return 0
}
func openFileDialog(owner uintptr) string {
type openFileName struct {
lStructSize uint32
hwndOwner uintptr
hInstance uintptr
lpstrFilter uintptr
lpstrCustomFilter uintptr
nMaxCustFilter uint32
nFilterIndex uint32
lpstrFile uintptr
nMaxFile uint32
lpstrFileTitle uintptr
nMaxFileTitle uint32
lpstrInitialDir uintptr
lpstrTitle uintptr
Flags uint32
nFileOffset uint16
nFileExtension uint16
lpstrDefExt uintptr
lCustData uintptr
lpfnHook uintptr
lpTemplateName uintptr
pvReserved uintptr
dwReserved uint32
FlagsEx uint32
}
// Filter: "Images\0*.jpg;*.png\0All\0*.*\0\0"
filterStr := "图片文件\x00*.jpg;*.jpeg;*.png;*.bmp;*.webp;*.gif\x00所有文件\x00*.*\x00\x00"
filterUTF16 := utf16.Encode([]rune(filterStr))
titleUTF16 := utf16.Encode([]rune("选择壁纸图片"))
fileBuf := make([]uint16, 260)
ofn := openFileName{
lStructSize: uint32(unsafe.Sizeof(openFileName{})),
hwndOwner: owner,
lpstrFilter: slicePtr(filterUTF16),
lpstrFile: slicePtr(fileBuf),
nMaxFile: 260,
lpstrTitle: slicePtr(titleUTF16),
Flags: 0x00001000 | 0x00000800 | 0x00000004,
}
ret, _, _ := procGetOpenFileNameW.Call(uintptr(unsafe.Pointer(&ofn)))
if ret == 0 {
return ""
}
return windows.UTF16ToString(fileBuf)
}
func colorPickerDialog(owner uintptr, initialColor string) string {
type chooseColor struct {
lStructSize uint32
hwndOwner uintptr
hInstance uintptr
rgbResult uint32
lpCustColors uintptr
Flags uint32
lCustData uintptr
lpfnHook uintptr
lpTemplateName uintptr
}
custColors := make([]uint32, 16)
var initRGB uint32
if len(initialColor) > 4 && initialColor[0] == '#' {
var r, g, b uint32
fmt.Sscanf(initialColor[1:], "%02x%02x%02x", &r, &g, &b)
initRGB = r | (g << 8) | (b << 16)
}
cc := chooseColor{
lStructSize: uint32(unsafe.Sizeof(chooseColor{})),
hwndOwner: owner,
rgbResult: initRGB,
lpCustColors: slicePtr(custColors),
Flags: 0x00000002,
}
ret, _, _ := procChooseColorW.Call(uintptr(unsafe.Pointer(&cc)))
if ret == 0 {
return ""
}
r := cc.rgbResult & 0xFF
g := (cc.rgbResult >> 8) & 0xFF
b := (cc.rgbResult >> 16) & 0xFF
return fmt.Sprintf("#%02x%02x%02x", r, g, b)
}
func browseForFolderDialog(owner uintptr) string {
title, _ := windows.UTF16PtrFromString("选择图片目录")
var displayName [260]uint16
bi := struct {
HwndOwner uintptr
PidlRoot uintptr
PszDisplayName uintptr
LpszTitle uintptr
UlFlags uint32
LpFn uintptr
LParam uintptr
IImage int32
}{
HwndOwner: owner,
PszDisplayName: uintptr(unsafe.Pointer(&displayName[0])),
LpszTitle: uintptr(unsafe.Pointer(title)),
UlFlags: 0x00000001 | 0x00000040,
}
pidl, _, _ := procSHBrowseForFolderW.Call(uintptr(unsafe.Pointer(&bi)))
if pidl == 0 {
return ""
}
defer procCoTaskMemFree.Call(pidl)
var path [260]uint16
procSHGetPathFromIDListW.Call(pidl, uintptr(unsafe.Pointer(&path[0])))
return windows.UTF16ToString(path[:])
}