7 changed files with 224 additions and 0 deletions
@ -0,0 +1,34 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Perspex.Controls.Platform; |
|||
using Splat; |
|||
|
|||
namespace Perspex.Controls |
|||
{ |
|||
public class CommonDialog |
|||
{ |
|||
public string Title { get; set; } |
|||
public List<CommonDialogFilter> Filters { get; set; } = new List<CommonDialogFilter>(); |
|||
public string InitialFileName { get; set; } |
|||
public string InitialDirectory { get; set; } |
|||
public bool AllowMultiple { get; set; } |
|||
public string DefaultExtension { get; set; } |
|||
public CommonDialogAction Action { get; set; } |
|||
|
|||
|
|||
public Task<string[]> ShowAsync(Window window = null) |
|||
=> Locator.Current.GetService<ICommonDialogImpl>().ShowAsync(this, window?.PlatformImpl); |
|||
} |
|||
|
|||
public enum CommonDialogAction |
|||
{ |
|||
OpenFile, |
|||
SaveFile |
|||
} |
|||
|
|||
public class CommonDialogFilter |
|||
{ |
|||
public string Name { get; set; } |
|||
public List<string> Extensions { get; set; } = new List<string>(); |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Perspex.Platform; |
|||
|
|||
namespace Perspex.Controls.Platform |
|||
{ |
|||
public interface ICommonDialogImpl |
|||
{ |
|||
Task<string[]> ShowAsync(CommonDialog dialog, IWindowImpl parent); |
|||
} |
|||
} |
|||
@ -0,0 +1,117 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Runtime.InteropServices; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Perspex.Controls; |
|||
using Perspex.Controls.Platform; |
|||
using Perspex.Platform; |
|||
using Perspex.Win32.Interop; |
|||
|
|||
namespace Perspex.Win32 |
|||
{ |
|||
class CommonDialogImpl : ICommonDialogImpl |
|||
{ |
|||
public unsafe Task<string[]> ShowAsync(CommonDialog dialog, IWindowImpl parent) |
|||
{ |
|||
var hWnd = parent?.Handle?.Handle ?? IntPtr.Zero; |
|||
return Task.Factory.StartNew(() => |
|||
{ |
|||
var filters = new StringBuilder(); |
|||
foreach (var filter in dialog.Filters) |
|||
{ |
|||
var extMask = string.Join(";", filter.Extensions.Select(e => "*." + e)); |
|||
filters.Append(filter.Name); |
|||
filters.Append(" ("); |
|||
filters.Append(extMask); |
|||
filters.Append(")"); |
|||
filters.Append('\0'); |
|||
filters.Append(extMask); |
|||
filters.Append('\0'); |
|||
} |
|||
if (filters.Length == 0) |
|||
filters.Append("All files\0*.*\0"); |
|||
filters.Append('\0'); |
|||
|
|||
var filterBuffer = new char[filters.Length]; |
|||
filters.CopyTo(0, filterBuffer, 0, filterBuffer.Length); |
|||
|
|||
|
|||
var buffer = new char[256]; |
|||
fixed (char* pBuffer = buffer) |
|||
fixed (char* pFilterBuffer = filterBuffer) |
|||
fixed (char* pDefExt = dialog.DefaultExtension) |
|||
fixed (char* pInitDir = dialog.InitialDirectory) |
|||
fixed (char* pTitle = dialog.Title) |
|||
{ |
|||
|
|||
var ofn = new UnmanagedMethods.OpenFileName() |
|||
{ |
|||
hwndOwner = hWnd, |
|||
hInstance = IntPtr.Zero, |
|||
lCustData = IntPtr.Zero, |
|||
nFilterIndex = 0, |
|||
Flags = |
|||
UnmanagedMethods.OpenFileNameFlags.OFN_EXPLORER | |
|||
UnmanagedMethods.OpenFileNameFlags.OFN_HIDEREADONLY, |
|||
nMaxCustFilter = 0, |
|||
nMaxFile = buffer.Length - 1, |
|||
nMaxFileTitle = 0, |
|||
lpTemplateName = IntPtr.Zero, |
|||
lpfnHook = IntPtr.Zero, |
|||
lpstrCustomFilter = IntPtr.Zero, |
|||
lpstrDefExt = new IntPtr(pDefExt), |
|||
lpstrFile = new IntPtr(pBuffer), |
|||
lpstrFileTitle = IntPtr.Zero, |
|||
lpstrFilter = new IntPtr(pFilterBuffer), |
|||
lpstrInitialDir = new IntPtr(pInitDir), |
|||
lpstrTitle = new IntPtr(pTitle), |
|||
|
|||
}; |
|||
ofn.lStructSize = Marshal.SizeOf(ofn); |
|||
if (dialog.AllowMultiple && dialog.Action == CommonDialogAction.OpenFile) |
|||
ofn.Flags |= UnmanagedMethods.OpenFileNameFlags.OFN_ALLOWMULTISELECT; |
|||
|
|||
if (dialog.Action == CommonDialogAction.SaveFile) |
|||
ofn.Flags |= UnmanagedMethods.OpenFileNameFlags.OFN_NOREADONLYRETURN | |
|||
UnmanagedMethods.OpenFileNameFlags.OFN_OVERWRITEPROMPT; |
|||
|
|||
var pofn = &ofn; |
|||
|
|||
var res = dialog.Action == CommonDialogAction.OpenFile |
|||
? UnmanagedMethods.GetOpenFileName(new IntPtr(pofn)) |
|||
: UnmanagedMethods.GetSaveFileName(new IntPtr(pofn)); |
|||
if (!res) |
|||
return null; |
|||
|
|||
} |
|||
var cStart = 0; |
|||
string dir = null; |
|||
var files = new List<string>(); |
|||
for (var c = 0; c < buffer.Length; c++) |
|||
{ |
|||
if (buffer[c] == 0) |
|||
{ |
|||
//Encountered double zero char
|
|||
if (cStart == c) |
|||
break; |
|||
|
|||
var s = new string(buffer, cStart, c - cStart); |
|||
if (dir == null) |
|||
dir = s; |
|||
else |
|||
files.Add(s); |
|||
cStart = c + 1; |
|||
} |
|||
} |
|||
if (files.Count == 0) |
|||
return new[] {dir}; |
|||
|
|||
return files.Select(f => Path.Combine(dir, f)).ToArray(); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue