github.com/AlpineAIO/wails/v2@v2.0.0-beta.32.0.20240505041856-1047a8fa5fef/internal/go-common-file-dialog/cfd/vtblCommonFunc.go (about) 1 //go:build windows 2 // +build windows 3 4 package cfd 5 6 import ( 7 "fmt" 8 "github.com/go-ole/go-ole" 9 "strings" 10 "syscall" 11 "unsafe" 12 ) 13 14 func hresultToError(hr uintptr) error { 15 if hr < 0 { 16 return ole.NewError(hr) 17 } 18 return nil 19 } 20 21 func (vtbl *iUnknownVtbl) release(objPtr unsafe.Pointer) error { 22 ret, _, _ := syscall.Syscall(vtbl.Release, 23 0, 24 uintptr(objPtr), 25 0, 26 0) 27 return hresultToError(ret) 28 } 29 30 func (vtbl *iModalWindowVtbl) show(objPtr unsafe.Pointer, hwnd uintptr) error { 31 ret, _, _ := syscall.Syscall(vtbl.Show, 32 1, 33 uintptr(objPtr), 34 hwnd, 35 0) 36 return hresultToError(ret) 37 } 38 39 func (vtbl *iFileDialogVtbl) setFileTypes(objPtr unsafe.Pointer, filters []FileFilter) error { 40 cFileTypes := len(filters) 41 if cFileTypes < 0 { 42 return fmt.Errorf("must specify at least one filter") 43 } 44 comDlgFilterSpecs := make([]comDlgFilterSpec, cFileTypes) 45 for i := 0; i < cFileTypes; i++ { 46 filter := &filters[i] 47 comDlgFilterSpecs[i] = comDlgFilterSpec{ 48 pszName: ole.SysAllocString(filter.DisplayName), 49 pszSpec: ole.SysAllocString(filter.Pattern), 50 } 51 } 52 ret, _, _ := syscall.Syscall(vtbl.SetFileTypes, 53 2, 54 uintptr(objPtr), 55 uintptr(cFileTypes), 56 uintptr(unsafe.Pointer(&comDlgFilterSpecs[0]))) 57 return hresultToError(ret) 58 } 59 60 // Options are: 61 // FOS_OVERWRITEPROMPT = 0x2, 62 // FOS_STRICTFILETYPES = 0x4, 63 // FOS_NOCHANGEDIR = 0x8, 64 // FOS_PICKFOLDERS = 0x20, 65 // FOS_FORCEFILESYSTEM = 0x40, 66 // FOS_ALLNONSTORAGEITEMS = 0x80, 67 // FOS_NOVALIDATE = 0x100, 68 // FOS_ALLOWMULTISELECT = 0x200, 69 // FOS_PATHMUSTEXIST = 0x800, 70 // FOS_FILEMUSTEXIST = 0x1000, 71 // FOS_CREATEPROMPT = 0x2000, 72 // FOS_SHAREAWARE = 0x4000, 73 // FOS_NOREADONLYRETURN = 0x8000, 74 // FOS_NOTESTFILECREATE = 0x10000, 75 // FOS_HIDEMRUPLACES = 0x20000, 76 // FOS_HIDEPINNEDPLACES = 0x40000, 77 // FOS_NODEREFERENCELINKS = 0x100000, 78 // FOS_OKBUTTONNEEDSINTERACTION = 0x200000, 79 // FOS_DONTADDTORECENT = 0x2000000, 80 // FOS_FORCESHOWHIDDEN = 0x10000000, 81 // FOS_DEFAULTNOMINIMODE = 0x20000000, 82 // FOS_FORCEPREVIEWPANEON = 0x40000000, 83 // FOS_SUPPORTSTREAMABLEITEMS = 0x80000000 84 func (vtbl *iFileDialogVtbl) setOptions(objPtr unsafe.Pointer, options uint32) error { 85 ret, _, _ := syscall.Syscall(vtbl.SetOptions, 86 1, 87 uintptr(objPtr), 88 uintptr(options), 89 0) 90 return hresultToError(ret) 91 } 92 93 func (vtbl *iFileDialogVtbl) getOptions(objPtr unsafe.Pointer) (uint32, error) { 94 var options uint32 95 ret, _, _ := syscall.Syscall(vtbl.GetOptions, 96 1, 97 uintptr(objPtr), 98 uintptr(unsafe.Pointer(&options)), 99 0) 100 return options, hresultToError(ret) 101 } 102 103 func (vtbl *iFileDialogVtbl) addOption(objPtr unsafe.Pointer, option uint32) error { 104 if options, err := vtbl.getOptions(objPtr); err == nil { 105 return vtbl.setOptions(objPtr, options|option) 106 } else { 107 return err 108 } 109 } 110 111 func (vtbl *iFileDialogVtbl) removeOption(objPtr unsafe.Pointer, option uint32) error { 112 if options, err := vtbl.getOptions(objPtr); err == nil { 113 return vtbl.setOptions(objPtr, options&^option) 114 } else { 115 return err 116 } 117 } 118 119 func (vtbl *iFileDialogVtbl) setDefaultFolder(objPtr unsafe.Pointer, path string) error { 120 shellItem, err := newIShellItem(path) 121 if err != nil { 122 return err 123 } 124 defer shellItem.vtbl.release(unsafe.Pointer(shellItem)) 125 ret, _, _ := syscall.Syscall(vtbl.SetDefaultFolder, 126 1, 127 uintptr(objPtr), 128 uintptr(unsafe.Pointer(shellItem)), 129 0) 130 return hresultToError(ret) 131 } 132 133 func (vtbl *iFileDialogVtbl) setFolder(objPtr unsafe.Pointer, path string) error { 134 shellItem, err := newIShellItem(path) 135 if err != nil { 136 return err 137 } 138 defer shellItem.vtbl.release(unsafe.Pointer(shellItem)) 139 ret, _, _ := syscall.Syscall(vtbl.SetFolder, 140 1, 141 uintptr(objPtr), 142 uintptr(unsafe.Pointer(shellItem)), 143 0) 144 return hresultToError(ret) 145 } 146 147 func (vtbl *iFileDialogVtbl) setTitle(objPtr unsafe.Pointer, title string) error { 148 titlePtr := ole.SysAllocString(title) 149 ret, _, _ := syscall.Syscall(vtbl.SetTitle, 150 1, 151 uintptr(objPtr), 152 uintptr(unsafe.Pointer(titlePtr)), 153 0) 154 return hresultToError(ret) 155 } 156 157 func (vtbl *iFileDialogVtbl) close(objPtr unsafe.Pointer) error { 158 ret, _, _ := syscall.Syscall(vtbl.Close, 159 1, 160 uintptr(objPtr), 161 0, 162 0) 163 return hresultToError(ret) 164 } 165 166 func (vtbl *iFileDialogVtbl) getResult(objPtr unsafe.Pointer) (*iShellItem, error) { 167 var shellItem *iShellItem 168 ret, _, _ := syscall.Syscall(vtbl.GetResult, 169 1, 170 uintptr(objPtr), 171 uintptr(unsafe.Pointer(&shellItem)), 172 0) 173 return shellItem, hresultToError(ret) 174 } 175 176 func (vtbl *iFileDialogVtbl) getResultString(objPtr unsafe.Pointer) (string, error) { 177 shellItem, err := vtbl.getResult(objPtr) 178 if err != nil { 179 return "", err 180 } 181 if shellItem == nil { 182 return "", ErrCancelled 183 } 184 defer shellItem.vtbl.release(unsafe.Pointer(shellItem)) 185 return shellItem.vtbl.getDisplayName(unsafe.Pointer(shellItem)) 186 } 187 188 func (vtbl *iFileDialogVtbl) setClientGuid(objPtr unsafe.Pointer, guid *ole.GUID) error { 189 ret, _, _ := syscall.Syscall(vtbl.SetClientGuid, 190 1, 191 uintptr(objPtr), 192 uintptr(unsafe.Pointer(guid)), 193 0) 194 return hresultToError(ret) 195 } 196 197 func (vtbl *iFileDialogVtbl) setDefaultExtension(objPtr unsafe.Pointer, defaultExtension string) error { 198 if defaultExtension[0] == '.' { 199 defaultExtension = strings.TrimPrefix(defaultExtension, ".") 200 } 201 defaultExtensionPtr := ole.SysAllocString(defaultExtension) 202 ret, _, _ := syscall.Syscall(vtbl.SetDefaultExtension, 203 1, 204 uintptr(objPtr), 205 uintptr(unsafe.Pointer(defaultExtensionPtr)), 206 0) 207 return hresultToError(ret) 208 } 209 210 func (vtbl *iFileDialogVtbl) setFileName(objPtr unsafe.Pointer, fileName string) error { 211 fileNamePtr := ole.SysAllocString(fileName) 212 ret, _, _ := syscall.Syscall(vtbl.SetFileName, 213 1, 214 uintptr(objPtr), 215 uintptr(unsafe.Pointer(fileNamePtr)), 216 0) 217 return hresultToError(ret) 218 } 219 220 func (vtbl *iFileDialogVtbl) setSelectedFileFilterIndex(objPtr unsafe.Pointer, index uint) error { 221 ret, _, _ := syscall.Syscall(vtbl.SetFileTypeIndex, 222 1, 223 uintptr(objPtr), 224 uintptr(index+1), // SetFileTypeIndex counts from 1 225 0) 226 return hresultToError(ret) 227 }