diff --git a/App.config "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/App.config"
similarity index 100%
rename from App.config
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/App.config"
diff --git a/AppConfig.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/AppConfig.cs"
similarity index 100%
rename from AppConfig.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/AppConfig.cs"
diff --git a/File.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/File.cs"
similarity index 100%
rename from File.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/File.cs"
diff --git a/FileDropAdmin.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/FileDropAdmin.cs"
similarity index 100%
rename from FileDropAdmin.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/FileDropAdmin.cs"
diff --git a/Form.Designer.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.Designer.cs"
similarity index 100%
rename from Form.Designer.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.Designer.cs"
diff --git a/Form.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.cs"
similarity index 100%
rename from Form.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.cs"
diff --git a/Form.resx "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.resx"
similarity index 100%
rename from Form.resx
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Form.resx"
diff --git a/Icon.ico "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Icon.ico"
similarity index 100%
rename from Icon.ico
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Icon.ico"
diff --git a/LICENSE "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/LICENSE"
similarity index 100%
rename from LICENSE
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/LICENSE"
diff --git a/Other.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Other.cs"
similarity index 100%
rename from Other.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Other.cs"
diff --git a/Program.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Program.cs"
similarity index 100%
rename from Program.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Program.cs"
diff --git a/Properties/Resources.Designer.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Resources.Designer.cs"
similarity index 100%
rename from Properties/Resources.Designer.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Resources.Designer.cs"
diff --git a/Properties/Resources.resx "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Resources.resx"
similarity index 100%
rename from Properties/Resources.resx
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Resources.resx"
diff --git a/Properties/Settings.Designer.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Settings.Designer.cs"
similarity index 100%
rename from Properties/Settings.Designer.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Settings.Designer.cs"
diff --git a/Properties/Settings.settings "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Settings.settings"
similarity index 100%
rename from Properties/Settings.settings
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Properties/Settings.settings"
diff --git a/Registry.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Registry.cs"
similarity index 100%
rename from Registry.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/Registry.cs"
diff --git a/WebClient.cs "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/WebClient.cs"
similarity index 100%
rename from WebClient.cs
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/WebClient.cs"
diff --git a/app.manifest "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/app.manifest"
similarity index 100%
rename from app.manifest
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/app.manifest"
diff --git a/syspin.dll "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/syspin.dll"
similarity index 100%
rename from syspin.dll
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/syspin.dll"
diff --git "a/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.csproj" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.csproj"
similarity index 100%
rename from "\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.csproj"
rename to "src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.WindowsForms/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.csproj"
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.config" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.config"
new file mode 100644
index 0000000..10b1fb1
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.config"
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.manifest" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.manifest"
new file mode 100644
index 0000000..75fadaf
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.manifest"
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+ true
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml"
new file mode 100644
index 0000000..23a88b1
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml"
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml.cs"
new file mode 100644
index 0000000..05dd157
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/App.xaml.cs"
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+using Xiu2.TileTool.Core;
+
+namespace Xiu2.TileTool
+{
+ public partial class App : Application
+ {
+ protected override void OnStartup(StartupEventArgs e)
+ {
+ base.OnStartup(e);
+
+ // 判断系统版本
+ if (Environment.OSVersion.Version.Major != 10)
+ {
+ _ = MessageBox.Show($"{AppInfo.Main.AppName}仅支持 Windows10 系统!", "错误", MessageBoxButton.OK);
+ Shutdown();
+ }
+ }
+ }
+}
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Core/AppInfo.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Core/AppInfo.cs"
new file mode 100644
index 0000000..84ef534
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Core/AppInfo.cs"
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+
+namespace Xiu2.TileTool.Core
+{
+ ///
+ /// 包含应用程序的一般信息。
+ ///
+ internal class AppInfo
+ {
+ ///
+ /// 获取当前应用程序的一般信息。
+ ///
+ public static AppInfo Main { get; } = new AppInfo(Assembly.GetEntryAssembly()!);
+
+ public AppInfo(Assembly assembly)
+ {
+ AppName = assembly.GetCustomAttribute()?.Product
+ ?? assembly.GetCustomAttribute()!.Title;
+ Version = assembly.GetCustomAttribute()!.InformationalVersion;
+ Author = assembly.GetCustomAttribute()!.Company;
+ }
+
+ ///
+ /// 获取应用名称。
+ ///
+ public string AppName { get; }
+
+ ///
+ /// 获取版本号(可能带预览标签)。
+ ///
+ public string Version { get; }
+
+ ///
+ /// 获取作者名。
+ ///
+ public string Author { get; }
+ }
+}
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Program.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Program.cs"
new file mode 100644
index 0000000..09c32be
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Program.cs"
@@ -0,0 +1,86 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Threading;
+using Xiu2.TileTool.Core;
+
+namespace Xiu2.TileTool
+{
+ internal static class Program
+ {
+ [STAThread]
+ static void Main(string[] args)
+ {
+ // 启动前一个进程实例。
+ Mutex? newMutex = null;
+ try
+ {
+#pragma warning disable IDE0067 // 丢失范围之前释放对象
+ newMutex = new Mutex(true, "a8851f5e-cbb5-4466-bd72-d95c9bea4dea", out bool createdNew);
+#pragma warning restore IDE0067 // 丢失范围之前释放对象
+ if (!createdNew)
+ {
+ if (args.Length > 0 && args[0] != "")
+ {
+ // 右键菜单启动:杀掉已存在的进程。
+ KillSameNameProcess();
+ }
+ else
+ {
+ // 用户双击启动,打开之前已打开的窗口。
+ var current = Process.GetCurrentProcess();
+ var process = Process.GetProcessesByName(current.ProcessName).FirstOrDefault(x => x.Id != current.Id);
+ if (process != null)
+ {
+ var hwnd = process.MainWindowHandle;
+ ShowWindow(hwnd, 9);
+ SetForegroundWindow(hwnd);
+ return;
+ }
+ }
+ }
+ }
+ catch (Exception)
+ {
+ // 忽略任何多实例处理相关的异常。
+ }
+
+ // 启动自己。
+ var app = new App();
+ app.InitializeComponent();
+ app.Run();
+ }
+
+ ///
+ /// 结束同名进程。
+ ///
+ private static void KillSameNameProcess()
+ {
+ var name = AppInfo.Main.AppName;
+ // 获取当前进程信息。
+ Process currentProcess = Process.GetCurrentProcess();
+ // 获取同名进程信息。
+ Process[] processes = Process.GetProcesses();
+ foreach (Process process in processes)
+ {
+ // 判断该进程主窗口标题是否含有 XXX 字符串。
+ if (process.MainWindowTitle.Contains(name))
+ {
+ // 如果不是当前进程,就结束它。
+ if (process.Id != currentProcess.Id)
+ {
+ process.Kill();
+ }
+ }
+ }
+ }
+
+ [DllImport("user32.dll")]
+ private static extern int ShowWindow(IntPtr hwnd, uint nCmdShow);
+
+ [DllImport("USER32.DLL")]
+ public static extern bool SetForegroundWindow(IntPtr hWnd);
+ }
+}
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Properties/AssemblyInfo.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Properties/AssemblyInfo.cs"
new file mode 100644
index 0000000..8b5504e
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Properties/AssemblyInfo.cs"
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Core.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Core.xaml"
new file mode 100644
index 0000000..e95ae8a
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Core.xaml"
@@ -0,0 +1,43 @@
+
+
+ #0B6AB4
+ #2286CC
+ #014696
+ White
+ #999999
+ #2B2B2B
+ White
+ #999999
+ #2B2B2B
+ #353536
+ #353536
+ #353536
+ #353536
+ #353536
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/Button.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/Button.xaml"
new file mode 100644
index 0000000..7957486
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/Button.xaml"
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/ListBox.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/ListBox.xaml"
new file mode 100644
index 0000000..5bc4ab9
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/ListBox.xaml"
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/Window.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/Window.xaml"
new file mode 100644
index 0000000..fe5e94b
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/FDS/Window.xaml"
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Generic.xaml" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Generic.xaml"
new file mode 100644
index 0000000..4ccd3a9
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/Themes/Generic.xaml"
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/BindableObject.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/BindableObject.cs"
new file mode 100644
index 0000000..06fbbc6
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/BindableObject.cs"
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+// 来源:https://github.com/walterlv/Walterlv.Packages/blob/master/src/Frameworks/Walterlv.Windows.Framework/ComponentModel/BindableObject.cs
+
+namespace Xiu2.TileTool.UIFramework
+{
+ ///
+ /// 表示可绑定的对象,在此类型的派生类中按约定定义的属性支持绑定。
+ ///
+ public abstract class BindableObject : INotifyPropertyChanged
+ {
+ ///
+ /// 当此实例中的任何一个具有更改通知的属性值改变时发生。
+ /// 派生类可以通过调用 或 来引发此事件。
+ ///
+ public event PropertyChangedEventHandler? PropertyChanged;
+
+ ///
+ /// 当具有更改通知的属性值改变时发生。
+ ///
+ /// 属性名称。不需要手动传入,会自动根据所在属性的方法名设置此参数值。
+ protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ ///
+ /// 修改一个具有更改通知的属性值,并对外报告值的改变。
+ ///
+ /// 值的类型。
+ /// 要修改的字段引用。
+ /// 要修改的字段的新值。
+ /// 属性名称。不需要手动传入,会自动根据所在属性的方法名设置此参数值。
+ /// 如果值发生了更改,则返回 true;否则返回 false。
+ protected bool SetValue(ref T field, T value, [CallerMemberName] string? propertyName = null)
+ {
+ if (!Equals(field, value))
+ {
+ field = value;
+ OnPropertyChanged(propertyName);
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git "a/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/NavigationItem.cs" "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/NavigationItem.cs"
new file mode 100644
index 0000000..7f49782
--- /dev/null
+++ "b/src/\347\243\201\350\264\264\347\276\216\345\214\226\345\260\217\345\267\245\345\205\267.Wpf/UIFramework/NavigationItem.cs"
@@ -0,0 +1,121 @@
+using System;
+using System.Diagnostics.Contracts;
+using System.Windows;
+
+// 来源:https://github.com/walterlv/Walterlv.Packages/blob/master/src/Frameworks/Walterlv.Windows.Framework/Windows/Navigating/NavigationItem.cs
+
+namespace Xiu2.TileTool.UIFramework
+{
+ ///
+ /// 为 Master-Detail 布局型导航提供通用的 ViewModel。
+ ///
+ public class NavigationItem : BindableObject
+ {
+ private readonly Func _viewCreator;
+ private readonly Func