1
1
using System ;
2
- using System . Linq ;
3
2
using System . Collections . Generic ;
4
3
using System . IO ;
5
4
using System . ComponentModel ;
@@ -15,10 +14,12 @@ namespace Avalonia.Win32
15
14
{
16
15
internal class Win32StorageProvider : BclStorageProvider
17
16
{
18
- private const uint SIGDN_FILESYSPATH = 0x80058000 ;
17
+ private const uint SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000 ;
19
18
20
- private const FILEOPENDIALOGOPTIONS DefaultDialogOptions = FILEOPENDIALOGOPTIONS . FOS_FORCEFILESYSTEM | FILEOPENDIALOGOPTIONS . FOS_NOVALIDATE |
21
- FILEOPENDIALOGOPTIONS . FOS_NOTESTFILECREATE | FILEOPENDIALOGOPTIONS . FOS_DONTADDTORECENT ;
19
+ private const FILEOPENDIALOGOPTIONS DefaultDialogOptions =
20
+ FILEOPENDIALOGOPTIONS . FOS_PATHMUSTEXIST | FILEOPENDIALOGOPTIONS . FOS_FORCEFILESYSTEM |
21
+ FILEOPENDIALOGOPTIONS . FOS_NOVALIDATE | FILEOPENDIALOGOPTIONS . FOS_NOTESTFILECREATE |
22
+ FILEOPENDIALOGOPTIONS . FOS_DONTADDTORECENT ;
22
23
23
24
private readonly WindowImpl _windowImpl ;
24
25
@@ -35,21 +36,23 @@ public Win32StorageProvider(WindowImpl windowImpl)
35
36
36
37
public override async Task < IReadOnlyList < IStorageFolder > > OpenFolderPickerAsync ( FolderPickerOpenOptions options )
37
38
{
38
- var files = await ShowFilePicker (
39
+ return await ShowFilePicker (
39
40
true , true ,
40
41
options . AllowMultiple , false ,
41
- options . Title , null , options . SuggestedStartLocation , null , null ) ;
42
- return files . Select ( f => new BclStorageFolder ( new DirectoryInfo ( f ) ) ) . ToArray ( ) ;
42
+ options . Title , null , options . SuggestedStartLocation , null , null ,
43
+ f => new BclStorageFolder ( new DirectoryInfo ( f ) ) )
44
+ . ConfigureAwait ( false ) ;
43
45
}
44
46
45
47
public override async Task < IReadOnlyList < IStorageFile > > OpenFilePickerAsync ( FilePickerOpenOptions options )
46
48
{
47
- var files = await ShowFilePicker (
49
+ return await ShowFilePicker (
48
50
true , false ,
49
51
options . AllowMultiple , false ,
50
52
options . Title , null , options . SuggestedStartLocation ,
51
- null , options . FileTypeFilter ) ;
52
- return files . Select ( f => new BclStorageFile ( new FileInfo ( f ) ) ) . ToArray ( ) ;
53
+ null , options . FileTypeFilter ,
54
+ f => new BclStorageFile ( new FileInfo ( f ) ) )
55
+ . ConfigureAwait ( false ) ;
53
56
}
54
57
55
58
public override async Task < IStorageFile ? > SaveFilePickerAsync ( FilePickerSaveOptions options )
@@ -58,11 +61,13 @@ public override async Task<IReadOnlyList<IStorageFile>> OpenFilePickerAsync(File
58
61
false , false ,
59
62
false , options . ShowOverwritePrompt ,
60
63
options . Title , options . SuggestedFileName , options . SuggestedStartLocation ,
61
- options . DefaultExtension , options . FileTypeChoices ) ;
62
- return files . Select ( f => new BclStorageFile ( new FileInfo ( f ) ) ) . FirstOrDefault ( ) ;
64
+ options . DefaultExtension , options . FileTypeChoices ,
65
+ f => new BclStorageFile ( new FileInfo ( f ) ) )
66
+ . ConfigureAwait ( false ) ;
67
+ return files . Count > 0 ? files [ 0 ] : null ;
63
68
}
64
69
65
- private unsafe Task < IEnumerable < string > > ShowFilePicker (
70
+ private unsafe Task < IReadOnlyList < TStorageItem > > ShowFilePicker < TStorageItem > (
66
71
bool isOpenFile ,
67
72
bool openFolder ,
68
73
bool allowMultiple ,
@@ -71,11 +76,13 @@ private unsafe Task<IEnumerable<string>> ShowFilePicker(
71
76
string ? suggestedFileName ,
72
77
IStorageFolder ? folder ,
73
78
string ? defaultExtension ,
74
- IReadOnlyList < FilePickerFileType > ? filters )
79
+ IReadOnlyList < FilePickerFileType > ? filters ,
80
+ Func < string , TStorageItem > convert )
81
+ where TStorageItem : IStorageItem
75
82
{
76
83
return Task . Run ( ( ) =>
77
84
{
78
- IEnumerable < string > result = Array . Empty < string > ( ) ;
85
+ IReadOnlyList < TStorageItem > result = Array . Empty < TStorageItem > ( ) ;
79
86
try
80
87
{
81
88
var clsid = isOpenFile ? UnmanagedMethods . ShellIds . OpenFileDialog : UnmanagedMethods . ShellIds . SaveFileDialog ;
@@ -101,7 +108,7 @@ private unsafe Task<IEnumerable<string>> ShowFilePicker(
101
108
102
109
if ( defaultExtension is null )
103
110
{
104
- defaultExtension = String . Empty ;
111
+ defaultExtension = string . Empty ;
105
112
}
106
113
107
114
fixed ( char * pExt = defaultExtension )
@@ -162,22 +169,22 @@ private unsafe Task<IEnumerable<string>> ShowFilePicker(
162
169
var shellItemArray = fileOpenDialog . Results ;
163
170
var count = shellItemArray . Count ;
164
171
165
- var results = new List < string > ( ) ;
172
+ var results = new List < TStorageItem > ( ) ;
166
173
for ( int i = 0 ; i < count ; i ++ )
167
174
{
168
175
var shellItem = shellItemArray . GetItemAt ( i ) ;
169
- if ( GetAbsoluteFilePath ( shellItem ) is { } selected )
176
+ if ( GetParsingName ( shellItem ) is { } selected )
170
177
{
171
- results . Add ( selected ) ;
178
+ results . Add ( convert ( selected ) ) ;
172
179
}
173
180
}
174
181
175
182
result = results ;
176
183
}
177
184
else if ( frm . Result is { } shellItem
178
- && GetAbsoluteFilePath ( shellItem ) is { } singleResult )
185
+ && GetParsingName ( shellItem ) is { } singleResult )
179
186
{
180
- result = new [ ] { singleResult } ;
187
+ result = new [ ] { convert ( singleResult ) } ;
181
188
}
182
189
183
190
return result ;
@@ -191,18 +198,23 @@ private unsafe Task<IEnumerable<string>> ShowFilePicker(
191
198
}
192
199
193
200
194
- private static unsafe string ? GetAbsoluteFilePath ( IShellItem shellItem )
201
+ private static string ? GetParsingName ( IShellItem shellItem )
202
+ {
203
+ return GetDisplayName ( shellItem , SIGDN_DESKTOPABSOLUTEPARSING ) ;
204
+ }
205
+
206
+ private static unsafe string ? GetDisplayName ( IShellItem shellItem , uint sigdnName )
195
207
{
196
- var pszString = new IntPtr ( shellItem . GetDisplayName ( SIGDN_FILESYSPATH ) ) ;
197
- if ( pszString != IntPtr . Zero )
208
+ char * pszString = null ;
209
+ if ( shellItem . GetDisplayName ( sigdnName , & pszString ) == 0 )
198
210
{
199
211
try
200
212
{
201
- return Marshal . PtrToStringUni ( pszString ) ;
213
+ return Marshal . PtrToStringUni ( ( IntPtr ) pszString ) ;
202
214
}
203
215
finally
204
216
{
205
- Marshal . FreeCoTaskMem ( pszString ) ;
217
+ Marshal . FreeCoTaskMem ( ( IntPtr ) pszString ) ;
206
218
}
207
219
}
208
220
return default ;
@@ -224,7 +236,7 @@ private static byte[] FiltersToPointer(IReadOnlyList<FilePickerFileType>? filter
224
236
for ( int i = 0 ; i < filters . Count ; i ++ )
225
237
{
226
238
var filter = filters [ i ] ;
227
- if ( filter . Patterns is null || ! filter . Patterns . Any ( ) )
239
+ if ( filter . Patterns is null || filter . Patterns . Count == 0 )
228
240
{
229
241
continue ;
230
242
}
0 commit comments