init uniWindowController 0.9.8
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
using AOT;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Kirurobo
|
||||
{
|
||||
/// <summary>
|
||||
/// 提供打开原生文件对话框的静态方法
|
||||
/// </summary>
|
||||
public class FilePanel
|
||||
{
|
||||
protected class LibUniWinC
|
||||
{
|
||||
[DllImport("LibUniWinC", CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool OpenFilePanel(in PanelSettings settings, [MarshalAs(UnmanagedType.LPWStr), Out] StringBuilder buffer, UInt32 bufferSize);
|
||||
|
||||
[DllImport("LibUniWinC", CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool OpenSavePanel(in PanelSettings settings, [MarshalAs(UnmanagedType.LPWStr), Out] StringBuilder buffer, UInt32 bufferSize);
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct PanelSettings : IDisposable {
|
||||
public Int32 structSize;
|
||||
public Int32 flags;
|
||||
public IntPtr lpszTitle;
|
||||
public IntPtr lpszFilter;
|
||||
public IntPtr lpszInitialFile;
|
||||
public IntPtr lpszInitialDir;
|
||||
public IntPtr lpszDefaultExt;
|
||||
|
||||
public PanelSettings(Settings settings)
|
||||
{
|
||||
this.structSize = 0;
|
||||
//this.structSize = 4 * 2 + Marshal.SizeOf<IntPtr>() * 3;
|
||||
this.flags = (Int32)settings.flags;
|
||||
|
||||
//this.lpTitleText = IntPtr.Zero;
|
||||
//this.lpFilterText = IntPtr.Zero;
|
||||
//this.lpDefaultPath = IntPtr.Zero;
|
||||
this.lpszTitle = Marshal.StringToHGlobalUni(settings.title);
|
||||
this.lpszFilter = Marshal.StringToHGlobalUni(Filter.Join(settings.filters));
|
||||
this.lpszInitialFile = Marshal.StringToHGlobalUni(settings.initialFile);
|
||||
this.lpszInitialDir = Marshal.StringToHGlobalUni(settings.initialDirectory);
|
||||
//this.lpszDefaultExt = Marshal.StringToHGlobalUni(settings.defaultExtension);
|
||||
this.lpszDefaultExt = IntPtr.Zero;
|
||||
|
||||
//this.structSize = Marshal.SizeOf(this);
|
||||
this.structSize = Marshal.SizeOf(this);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.lpszTitle != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(lpszTitle);
|
||||
this.lpszTitle = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (this.lpszFilter!= IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(lpszFilter);
|
||||
this.lpszFilter= IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (this.lpszInitialFile!= IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(lpszInitialFile);
|
||||
this.lpszInitialFile= IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (this.lpszInitialDir != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(lpszInitialDir);
|
||||
this.lpszInitialDir = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (this.lpszDefaultExt != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(lpszDefaultExt);
|
||||
this.lpszDefaultExt = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对话框的设置标志
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum Flag
|
||||
{
|
||||
None = 0,
|
||||
FileMustExist = 1, // 仅 Windows
|
||||
FolderMustExist = 2, // 仅 Windows
|
||||
AllowMultipleSelection = 4,
|
||||
CanCreateDirectories = 16,
|
||||
OverwritePrompt = 256, // macOS 上始终启用
|
||||
CreatePrompt = 512, // macOS 上始终启用
|
||||
ShowHiddenFiles = 4096,
|
||||
RetrieveLink = 8192,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件对话框的参数
|
||||
/// </summary>
|
||||
public struct Settings
|
||||
{
|
||||
public string title;
|
||||
public Filter[] filters;
|
||||
public string initialDirectory;
|
||||
public string initialFile;
|
||||
public string defaultExtension; // 未实现
|
||||
public Flag flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件过滤器
|
||||
/// </summary>
|
||||
public class Filter
|
||||
{
|
||||
protected string title;
|
||||
protected string[] extensions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="title">过滤器标题(macOS 上暂不可用)</param>
|
||||
/// <param name="extensions">扩展名数组,如 ["png", "jpg", "txt"]</param>
|
||||
public Filter(string title, params string[] extensions)
|
||||
{
|
||||
this.title = title;
|
||||
this.extensions = extensions;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return title + "\t" + String.Join("\t", extensions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回由 Filter 数组转换后的字符串
|
||||
/// </summary>
|
||||
/// <param name="filters"></param>
|
||||
/// <returns></returns>
|
||||
public static string Join(Filter[] filters)
|
||||
{
|
||||
if (filters == null) return "";
|
||||
|
||||
string result = "";
|
||||
bool isFirstItem = true;
|
||||
foreach (var filter in filters) {
|
||||
if (!isFirstItem) result += "\n";
|
||||
result += filter.ToString();
|
||||
isFirstItem = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于传递文件或文件夹路径的 UTF-16 缓冲区字符数
|
||||
/// 因为多个路径以换行符分隔,260 字符不够用。
|
||||
/// </summary>
|
||||
private const int pathBufferSize = 2560;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 打开文件选择对话框
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="action"></param>
|
||||
public static void OpenFilePanel(Settings settings, Action<string[]> action)
|
||||
{
|
||||
LibUniWinC.PanelSettings ps = new LibUniWinC.PanelSettings(settings);
|
||||
StringBuilder sb = new StringBuilder(pathBufferSize);
|
||||
|
||||
if (LibUniWinC.OpenFilePanel(in ps, sb, (uint)sb.Capacity))
|
||||
{
|
||||
string[] files = UniWinCore.parsePaths(sb.ToString());
|
||||
action.Invoke(files);
|
||||
}
|
||||
|
||||
ps.Dispose(); // 通过传入 Settings 的构造函数分配了内存,因此需要释放
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开保存文件选择对话框
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="action"></param>
|
||||
public static void SaveFilePanel(Settings settings, Action<string[]> action)
|
||||
{
|
||||
LibUniWinC.PanelSettings ps = new LibUniWinC.PanelSettings(settings);
|
||||
StringBuilder sb = new StringBuilder(pathBufferSize);
|
||||
|
||||
if (LibUniWinC.OpenSavePanel(in ps, sb, (uint)sb.Capacity))
|
||||
{
|
||||
string[] files = UniWinCore.parsePaths(sb.ToString());
|
||||
action.Invoke(files);
|
||||
}
|
||||
|
||||
ps.Dispose(); // 通过传入 Settings 的构造函数分配了内存,因此需要释放
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user