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[:]) }