2324 lines
72 KiB
C#
2324 lines
72 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Diagnostics;
|
||
using System.Drawing;
|
||
using System.IO;
|
||
using System.Text;
|
||
using System.Windows.Forms;
|
||
using System.Windows.Forms.Layout;
|
||
using Microsoft.Win32;
|
||
|
||
namespace FontPreview;
|
||
|
||
public class MainForm : Form
|
||
{
|
||
private const string TAG_PREFIX = "TAG:";
|
||
|
||
private TextBox txtPath;
|
||
|
||
private Button btnChoose;
|
||
|
||
private Button btnApply;
|
||
|
||
private Label lblStat;
|
||
|
||
private TreeView catBox;
|
||
private TextBox txtSearch;
|
||
private Dictionary<string, TreeNode> nodeIndex = new Dictionary<string, TreeNode>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
private TextBox txtInput;
|
||
|
||
private NumericUpDown numSize;
|
||
|
||
private NumericUpDown numLimit;
|
||
|
||
private Label lblFg;
|
||
|
||
private Label lblBg;
|
||
|
||
private Button btnRender;
|
||
|
||
private Button btnStop;
|
||
|
||
private Button btnMore;
|
||
|
||
private Button btnTag;
|
||
|
||
private Button btnExport;
|
||
|
||
private Button btnRename;
|
||
|
||
private Button btnMove;
|
||
|
||
private TextBox txtMoveDir;
|
||
|
||
private string moveDir = "";
|
||
|
||
private ProgressBar prog;
|
||
|
||
private Label lblProg;
|
||
|
||
private Panel rightPanel;
|
||
|
||
private FlowLayoutPanel flow;
|
||
|
||
private Color fgColor = Color.FromArgb(34, 34, 34);
|
||
|
||
private Color bgColor = Color.White;
|
||
|
||
private Dictionary<string, List<FontItem>> categories = new Dictionary<string, List<FontItem>>();
|
||
|
||
private string rootDir = "";
|
||
|
||
private Worker worker;
|
||
|
||
private string renderHash = "";
|
||
|
||
private Dictionary<string, Bitmap> cache = new Dictionary<string, Bitmap>();
|
||
|
||
private List<FontItem> allItems = new List<FontItem>();
|
||
|
||
private Dictionary<string, FontItem> pathIndex = new Dictionary<string, FontItem>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
private List<FontItem> compareList = new List<FontItem>();
|
||
|
||
private Dictionary<string, List<string>> tags = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
private bool isScanning;
|
||
|
||
private FontItem curPreviewItem;
|
||
private PictureBox curPreviewPic;
|
||
private List<KeyValuePair<FontItem, PictureBox>> renderedPics = new List<KeyValuePair<FontItem, PictureBox>>();
|
||
|
||
private string CfgFile => Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "config.txt");
|
||
|
||
private string TagFile => Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "tags.txt");
|
||
|
||
public ProgressBar Prog => prog;
|
||
|
||
public Label ProgText => lblProg;
|
||
|
||
public MainForm()
|
||
{
|
||
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00c9: Expected O, but got Unknown
|
||
((Control)this).Text = AppInfo.FullTitle;
|
||
// 启动时检测并确保允许快捷方式安装字体
|
||
EnsureInstallAsLinkEnabled();
|
||
try
|
||
{
|
||
System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
|
||
string resName = null;
|
||
foreach (string n in asm.GetManifestResourceNames())
|
||
{
|
||
if (n.EndsWith("app.ico", StringComparison.OrdinalIgnoreCase)) { resName = n; break; }
|
||
}
|
||
if (resName != null)
|
||
{
|
||
using (System.IO.Stream s = asm.GetManifestResourceStream(resName))
|
||
{
|
||
((Form)this).Icon = new Icon(s);
|
||
}
|
||
}
|
||
}
|
||
catch { }
|
||
((Control)this).Width = 1180;
|
||
((Control)this).Height = 780;
|
||
((Form)this).StartPosition = (FormStartPosition)1;
|
||
((Control)this).Font = new Font("Microsoft YaHei UI", 9f);
|
||
LoadTags();
|
||
BuildUI();
|
||
EventHandler eventHandler = delegate
|
||
{
|
||
RestoreLastDir();
|
||
};
|
||
((Form)this).Load += eventHandler;
|
||
}
|
||
|
||
// 确保系统允许用快捷方式安装字体(HKCU,无需管理员)
|
||
private void EnsureInstallAsLinkEnabled()
|
||
{
|
||
try
|
||
{
|
||
using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\Font Management", true))
|
||
{
|
||
if (key == null)
|
||
{
|
||
using (Microsoft.Win32.RegistryKey created = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\Font Management"))
|
||
{
|
||
created.SetValue("InstallAsLink", 1, Microsoft.Win32.RegistryValueKind.DWord);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
object val = key.GetValue("InstallAsLink");
|
||
if (val == null || val.ToString() != "1")
|
||
{
|
||
key.SetValue("InstallAsLink", 1, Microsoft.Win32.RegistryValueKind.DWord);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private void BuildUI()
|
||
{
|
||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0007: Expected O, but got Unknown
|
||
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_002d: Expected O, but got Unknown
|
||
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0044: Expected O, but got Unknown
|
||
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0063: Expected O, but got Unknown
|
||
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0077: Expected O, but got Unknown
|
||
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00a2: Expected O, but got Unknown
|
||
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00d7: Expected O, but got Unknown
|
||
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0116: Expected O, but got Unknown
|
||
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0134: Expected O, but got Unknown
|
||
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0191: Expected O, but got Unknown
|
||
//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_01f1: Expected O, but got Unknown
|
||
//IL_023c: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0242: Expected O, but got Unknown
|
||
//IL_026a: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0271: Expected O, but got Unknown
|
||
//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_02ba: Expected O, but got Unknown
|
||
//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0307: Expected O, but got Unknown
|
||
//IL_0358: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0362: Expected O, but got Unknown
|
||
//IL_0375: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_037c: Expected O, but got Unknown
|
||
//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_03b8: Expected O, but got Unknown
|
||
//IL_040f: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0416: Expected O, but got Unknown
|
||
//IL_043a: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0441: Expected O, but got Unknown
|
||
//IL_046c: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0476: Expected O, but got Unknown
|
||
//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_04dc: Expected O, but got Unknown
|
||
//IL_0508: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0512: Expected O, but got Unknown
|
||
//IL_0590: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0597: Expected O, but got Unknown
|
||
//IL_05cf: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_05d9: Expected O, but got Unknown
|
||
//IL_05e9: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_05f0: Expected O, but got Unknown
|
||
//IL_061c: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0626: Expected O, but got Unknown
|
||
//IL_0695: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_069c: Expected O, but got Unknown
|
||
//IL_06c9: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_06d3: Expected O, but got Unknown
|
||
//IL_0746: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0750: Expected O, but got Unknown
|
||
//IL_07db: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_07e5: Expected O, but got Unknown
|
||
//IL_0848: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0852: Expected O, but got Unknown
|
||
//IL_08b5: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_08bf: Expected O, but got Unknown
|
||
//IL_0907: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0911: Expected O, but got Unknown
|
||
//IL_095d: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0967: Expected O, but got Unknown
|
||
//IL_097b: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0985: Expected O, but got Unknown
|
||
//IL_09d8: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_09e2: Expected O, but got Unknown
|
||
//IL_0a35: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0a3f: Expected O, but got Unknown
|
||
//IL_0a94: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0a9b: Expected O, but got Unknown
|
||
//IL_0add: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0ae7: Expected O, but got Unknown
|
||
//IL_0b20: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0b2a: Expected O, but got Unknown
|
||
//IL_0b3d: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0b44: Expected O, but got Unknown
|
||
//IL_0b8a: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0b94: Expected O, but got Unknown
|
||
//IL_0bea: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0bf4: Expected O, but got Unknown
|
||
//IL_0c28: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0c32: Expected O, but got Unknown
|
||
//IL_0c87: Unknown result type (might be due to invalid IL or missing references)
|
||
TableLayoutPanel val = new TableLayoutPanel();
|
||
((Control)val).Dock = (DockStyle)5;
|
||
val.ColumnCount = 2;
|
||
val.ColumnStyles.Add(new ColumnStyle((SizeType)1, 320f));
|
||
val.ColumnStyles.Add(new ColumnStyle((SizeType)2, 100f));
|
||
val.RowCount = 1;
|
||
val.RowStyles.Add(new RowStyle((SizeType)2, 100f));
|
||
((Control)this).Controls.Add((Control)(object)val);
|
||
Panel val2 = new Panel();
|
||
((Control)val2).Dock = (DockStyle)5;
|
||
((Control)val2).Padding = new Padding(10);
|
||
val.Controls.Add((Control)(object)val2, 0, 0);
|
||
((Control)val2).BackColor = UiTheme.PanelBg;
|
||
Label val3 = new Label();
|
||
((Control)val3).Text = "字体目录路径(网络盘直接粘贴:\\\\server\\share 或 Z:\\)";
|
||
((Control)val3).SetBounds(10, 8, 300, 18);
|
||
((Control)val3).Font = new Font("Microsoft YaHei UI", 9.5f, FontStyle.Bold);
|
||
((Control)val3).ForeColor = UiTheme.Primary;
|
||
((Control)val2).Controls.Add((Control)(object)val3);
|
||
txtPath = new TextBox();
|
||
((Control)txtPath).Text = "";
|
||
((Control)txtPath).SetBounds(10, 28, 300, 26);
|
||
((Control)txtPath).KeyDown += (KeyEventHandler)delegate(object s, KeyEventArgs e)
|
||
{
|
||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0009: Invalid comparison between Unknown and I4
|
||
if ((int)e.KeyCode == 13)
|
||
{
|
||
ApplyPath();
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)txtPath);
|
||
btnChoose = new Button();
|
||
((Control)btnChoose).Text = "浏览…";
|
||
((Control)btnChoose).SetBounds(10, 58, 145, 28);
|
||
((Control)btnChoose).Click += delegate
|
||
{
|
||
ChooseDir();
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)btnChoose);
|
||
btnApply = new Button();
|
||
((Control)btnApply).Text = "应用路径";
|
||
((Control)btnApply).SetBounds(160, 58, 150, 28);
|
||
((Control)btnApply).Click += delegate
|
||
{
|
||
ApplyPath();
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)btnApply);
|
||
lblStat = new Label();
|
||
((Control)lblStat).Text = "尚未选择目录";
|
||
((Control)lblStat).SetBounds(10, 90, 300, 20);
|
||
((Control)lblStat).ForeColor = UiTheme.SubText;
|
||
((Control)val2).Controls.Add((Control)(object)lblStat);
|
||
Label val4 = new Label();
|
||
((Control)val4).Text = "选择分类";
|
||
((Control)val4).SetBounds(10, 114, 120, 20);
|
||
((Control)val4).Font = new Font("Microsoft YaHei UI", 9.5f, FontStyle.Bold);
|
||
((Control)val4).ForeColor = UiTheme.Primary;
|
||
((Control)val2).Controls.Add((Control)(object)val4);
|
||
Button val5 = new Button();
|
||
((Control)val5).Text = "全选";
|
||
((Control)val5).SetBounds(170, 112, 60, 24);
|
||
((Control)val5).Click += delegate
|
||
{
|
||
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0021: Expected O, but got Unknown
|
||
foreach (TreeNode node in catBox.Nodes)
|
||
{
|
||
TreeNode n2 = node;
|
||
SetNodeChecked(n2, check: true);
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)val5);
|
||
Button val6 = new Button();
|
||
((Control)val6).Text = "全不选";
|
||
((Control)val6).SetBounds(238, 112, 72, 24);
|
||
((Control)val6).Click += delegate
|
||
{
|
||
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0021: Expected O, but got Unknown
|
||
foreach (TreeNode node2 in catBox.Nodes)
|
||
{
|
||
TreeNode n = node2;
|
||
SetNodeChecked(n, check: false);
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)val6);
|
||
catBox = new TreeView();
|
||
((Control)catBox).SetBounds(10, 138, 300, 180);
|
||
catBox.CheckBoxes = true;
|
||
catBox.HideSelection = false;
|
||
catBox.FullRowSelect = true;
|
||
catBox.AfterCheck += (TreeViewEventHandler)delegate(object s, TreeViewEventArgs e)
|
||
{
|
||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0008: Invalid comparison between Unknown and I4
|
||
if ((int)e.Action == 2)
|
||
{
|
||
SetNodeChecked(e.Node, e.Node.Checked);
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)catBox);
|
||
// 新增:字体搜索框
|
||
Label valSearchLabel = new Label();
|
||
((Control)valSearchLabel).Text = "搜索字体(按名称/文件名过滤预览)";
|
||
((Control)valSearchLabel).SetBounds(10, 322, 300, 20);
|
||
((Control)valSearchLabel).Font = new Font("Microsoft YaHei UI", 9.5f, FontStyle.Bold);
|
||
((Control)valSearchLabel).ForeColor = UiTheme.Primary;
|
||
((Control)val2).Controls.Add((Control)(object)valSearchLabel);
|
||
txtSearch = new TextBox();
|
||
((Control)txtSearch).SetBounds(10, 344, 300, 26);
|
||
// 回车直接触发预览
|
||
txtSearch.KeyDown += delegate(object s, KeyEventArgs e)
|
||
{
|
||
if (e.KeyCode == Keys.Enter && !e.Shift)
|
||
{
|
||
e.SuppressKeyPress = true;
|
||
btnRender.PerformClick();
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)txtSearch);
|
||
Label val7 = new Label();
|
||
((Control)val7).Text = "预览文字";
|
||
((Control)val7).SetBounds(10, 376, 300, 20);
|
||
((Control)val7).Font = new Font("Microsoft YaHei UI", 9.5f, FontStyle.Bold);
|
||
((Control)val7).ForeColor = UiTheme.Primary;
|
||
((Control)val2).Controls.Add((Control)(object)val7);
|
||
txtInput = new TextBox();
|
||
((TextBoxBase)txtInput).Multiline = true;
|
||
((Control)txtInput).Text = "你好,世界 Welcome to Font Preview 0123456789";
|
||
((Control)txtInput).SetBounds(10, 398, 300, 60);
|
||
txtInput.ScrollBars = (ScrollBars)2;
|
||
((Control)val2).Controls.Add((Control)(object)txtInput);
|
||
// 新增:右键“预览文字”框 → 一键填入中文样例
|
||
ContextMenuStrip sampleMenu = new ContextMenuStrip();
|
||
foreach (KeyValuePair<string, string> kv in SampleTexts.GetItems())
|
||
{
|
||
string cap = kv.Key;
|
||
string content = kv.Value;
|
||
ToolStripMenuItem mi = new ToolStripMenuItem("填入样例:" + cap);
|
||
mi.Click += delegate
|
||
{
|
||
((Control)txtInput).Text = content;
|
||
};
|
||
sampleMenu.Items.Add(mi);
|
||
}
|
||
((Control)txtInput).ContextMenuStrip = sampleMenu;
|
||
Panel val8 = new Panel();
|
||
((Control)val8).SetBounds(10, 484, 300, 60);
|
||
((Control)val2).Controls.Add((Control)(object)val8);
|
||
Label val9 = new Label();
|
||
((Control)val9).Text = "字号";
|
||
((Control)val9).SetBounds(0, 2, 34, 22);
|
||
((Control)val8).Controls.Add((Control)(object)val9);
|
||
numSize = new NumericUpDown();
|
||
numSize.Minimum = 12m;
|
||
numSize.Maximum = 120m;
|
||
numSize.Value = 40m;
|
||
((Control)numSize).SetBounds(36, 0, 56, 24);
|
||
numSize.ValueChanged += delegate { RerenderCurrent(); };
|
||
((Control)val8).Controls.Add((Control)(object)numSize);
|
||
Label val10 = new Label();
|
||
((Control)val10).Text = "上限";
|
||
((Control)val10).SetBounds(100, 2, 34, 22);
|
||
((Control)val8).Controls.Add((Control)(object)val10);
|
||
numLimit = new NumericUpDown();
|
||
numLimit.Minimum = 50m;
|
||
numLimit.Maximum = 100000m;
|
||
numLimit.Value = 1000m;
|
||
numLimit.Increment = 500m;
|
||
((Control)numLimit).SetBounds(134, 0, 80, 24);
|
||
((Control)val8).Controls.Add((Control)(object)numLimit);
|
||
Label val11 = new Label();
|
||
((Control)val11).Text = "个(0=全部, 逐次累加续载)";
|
||
((Control)val11).SetBounds(218, 2, 82, 22);
|
||
((Control)val11).ForeColor = Color.Gray;
|
||
((Control)val11).Font = new Font("Microsoft YaHei UI", 7.5f);
|
||
((Control)val8).Controls.Add((Control)(object)val11);
|
||
Label val12 = new Label();
|
||
((Control)val12).Text = "字色";
|
||
((Control)val12).SetBounds(0, 30, 34, 22);
|
||
((Control)val8).Controls.Add((Control)(object)val12);
|
||
lblFg = new Label();
|
||
((Control)lblFg).BackColor = fgColor;
|
||
lblFg.BorderStyle = (BorderStyle)1;
|
||
((Control)lblFg).SetBounds(36, 30, 56, 22);
|
||
((Control)lblFg).Cursor = Cursors.Hand;
|
||
((Control)lblFg).Click += delegate
|
||
{
|
||
PickColor(fg: true);
|
||
};
|
||
((Control)val8).Controls.Add((Control)(object)lblFg);
|
||
Label val13 = new Label();
|
||
((Control)val13).Text = "底色";
|
||
((Control)val13).SetBounds(100, 30, 34, 22);
|
||
((Control)val8).Controls.Add((Control)(object)val13);
|
||
lblBg = new Label();
|
||
((Control)lblBg).BackColor = bgColor;
|
||
lblBg.BorderStyle = (BorderStyle)1;
|
||
((Control)lblBg).SetBounds(134, 30, 56, 22);
|
||
((Control)lblBg).Cursor = Cursors.Hand;
|
||
((Control)lblBg).Click += delegate
|
||
{
|
||
PickColor(fg: false);
|
||
};
|
||
((Control)val8).Controls.Add((Control)(object)lblBg);
|
||
btnRender = new Button();
|
||
((Control)btnRender).Text = "开始预览";
|
||
((Control)btnRender).BackColor = UiTheme.Primary;
|
||
((Control)btnRender).ForeColor = Color.White;
|
||
((ButtonBase)btnRender).FlatStyle = (FlatStyle)3;
|
||
((Control)btnRender).SetBounds(10, 544, 110, 32);
|
||
((Control)btnRender).Click += delegate
|
||
{
|
||
StartRender(append: false);
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)btnRender);
|
||
btnStop = new Button();
|
||
((Control)btnStop).Text = "停止";
|
||
((Control)btnStop).Enabled = false;
|
||
((Control)btnStop).SetBounds(126, 544, 60, 32);
|
||
((ButtonBase)btnStop).FlatStyle = (FlatStyle)3;
|
||
((Control)btnStop).Click += delegate
|
||
{
|
||
if (worker != null)
|
||
{
|
||
worker.Stop();
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)btnStop);
|
||
btnMore = new Button();
|
||
((Control)btnMore).Text = "加载更多";
|
||
((Control)btnMore).Enabled = false;
|
||
((Control)btnMore).SetBounds(192, 544, 118, 32);
|
||
((ButtonBase)btnMore).FlatStyle = (FlatStyle)3;
|
||
((Control)btnMore).Click += delegate
|
||
{
|
||
StartRender(append: true);
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)btnMore);
|
||
prog = new ProgressBar();
|
||
prog.Minimum = 0;
|
||
prog.Maximum = 100;
|
||
((Control)prog).SetBounds(10, 582, 300, 16);
|
||
((Control)val2).Controls.Add((Control)(object)prog);
|
||
lblProg = new Label();
|
||
((Control)lblProg).Text = "";
|
||
((Control)lblProg).SetBounds(10, 608, 300, 34);
|
||
((Control)lblProg).ForeColor = UiTheme.SubText;
|
||
((Control)lblProg).Font = new Font("Microsoft YaHei UI", 8f);
|
||
((Control)val2).Controls.Add((Control)(object)lblProg);
|
||
Label val14 = new Label();
|
||
((Control)val14).Text = "复制目录";
|
||
((Control)val14).SetBounds(10, 647, 60, 26);
|
||
((Control)val14).ForeColor = Color.FromArgb(90, 90, 90);
|
||
((Control)val2).Controls.Add((Control)(object)val14);
|
||
txtMoveDir = new TextBox();
|
||
((Control)txtMoveDir).Text = moveDir;
|
||
((Control)txtMoveDir).SetBounds(72, 647, 150, 26);
|
||
((Control)txtMoveDir).KeyDown += (KeyEventHandler)delegate(object s, KeyEventArgs e)
|
||
{
|
||
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0009: Invalid comparison between Unknown and I4
|
||
if ((int)e.KeyCode == 13)
|
||
{
|
||
MoveInstallBatch();
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)txtMoveDir);
|
||
Button val15 = new Button();
|
||
((Control)val15).Text = "浏览…";
|
||
((Control)val15).SetBounds(226, 646, 84, 28);
|
||
((Control)val15).Click += delegate
|
||
{
|
||
string text = NativeFolderDialog.PickFolder(((Control)this).Handle, "选择复制目标目录", (moveDir.Length > 0) ? moveDir : ((Control)txtPath).Text);
|
||
if (text != null)
|
||
{
|
||
moveDir = text;
|
||
((Control)txtMoveDir).Text = text;
|
||
SaveConfig();
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)val15);
|
||
// 新增:关于按钮
|
||
Button btnAbout = new Button();
|
||
((Control)btnAbout).Text = "关于";
|
||
((Control)btnAbout).SetBounds(10, 688, 96, 28);
|
||
((Control)btnAbout).Click += delegate
|
||
{
|
||
using (AboutDialog dlg = new AboutDialog())
|
||
{
|
||
dlg.ShowDialog(this);
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)btnAbout);
|
||
// 新增:缺字检测
|
||
Button btnGlyph = new Button();
|
||
((Control)btnGlyph).Text = "缺字检测";
|
||
((Control)btnGlyph).SetBounds(110, 688, 96, 28);
|
||
((Control)btnGlyph).Click += delegate
|
||
{
|
||
if (allItems.Count == 0)
|
||
{
|
||
MessageBox.Show("请先加载字体目录,再进行缺字检测。");
|
||
return;
|
||
}
|
||
using (GlyphCoverageDialog dlg = new GlyphCoverageDialog(allItems))
|
||
{
|
||
dlg.ShowDialog(this);
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)btnGlyph);
|
||
// 新增:字体并排对比
|
||
Button btnCompare = new Button();
|
||
((Control)btnCompare).Text = "字体对比";
|
||
((Control)btnCompare).SetBounds(210, 688, 100, 28);
|
||
((Control)btnCompare).Click += delegate
|
||
{
|
||
if (compareList.Count < 2)
|
||
{
|
||
MessageBox.Show("请先在预览卡片上右键 →「加入对比列表」选好至少两个字体,再点「字体对比」。", "字体对比");
|
||
return;
|
||
}
|
||
using (CompareDialog dlg = new CompareDialog(new List<FontItem>(compareList), true, MoveInstallOne))
|
||
{
|
||
dlg.ShowDialog(this);
|
||
}
|
||
};
|
||
((Control)val2).Controls.Add((Control)(object)btnCompare);
|
||
rightPanel = new Panel();
|
||
((Control)rightPanel).Dock = (DockStyle)5;
|
||
((Control)rightPanel).SetBounds(0, 0, 100, 100);
|
||
val.Controls.Add((Control)(object)rightPanel, 1, 0);
|
||
flow = new FlowLayoutPanel();
|
||
((Control)flow).Dock = (DockStyle)5;
|
||
((ScrollableControl)flow).AutoScroll = true;
|
||
flow.WrapContents = true;
|
||
((Control)flow).BackColor = Color.FromArgb(242, 244, 247);
|
||
((Control)flow).Padding = new Padding(16, 14, 16, 18);
|
||
((Control)flow).Resize += delegate
|
||
{
|
||
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0064: Expected O, but got Unknown
|
||
int width = ((Control)flow).ClientSize.Width;
|
||
Padding padding = ((Control)flow).Padding;
|
||
int num = width - padding.Horizontal - 8;
|
||
if (num < 300)
|
||
{
|
||
num = 300;
|
||
}
|
||
foreach (Control item in (ArrangedElementCollection)((Control)flow).Controls)
|
||
{
|
||
Control val16 = item;
|
||
val16.Width = num;
|
||
}
|
||
};
|
||
((Control)rightPanel).Controls.Add((Control)(object)flow);
|
||
}
|
||
|
||
private void PickColor(bool fg)
|
||
{
|
||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0007: Expected O, but got Unknown
|
||
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0028: Invalid comparison between Unknown and I4
|
||
ColorDialog val = new ColorDialog();
|
||
val.Color = (fg ? fgColor : bgColor);
|
||
if ((int)((CommonDialog)val).ShowDialog((IWin32Window)(object)this) == 1)
|
||
{
|
||
if (fg)
|
||
{
|
||
fgColor = val.Color;
|
||
((Control)lblFg).BackColor = fgColor;
|
||
}
|
||
else
|
||
{
|
||
bgColor = val.Color;
|
||
((Control)lblBg).BackColor = bgColor;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void ChooseDir()
|
||
{
|
||
string text = NativeFolderDialog.PickFolder(((Control)this).Handle, "选择字体所在目录(会按子目录作为分类)", rootDir);
|
||
if (text != null)
|
||
{
|
||
rootDir = text;
|
||
((Control)txtPath).Text = rootDir;
|
||
ScanDir();
|
||
}
|
||
}
|
||
|
||
private void ApplyPath()
|
||
{
|
||
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
|
||
string text = ((Control)txtPath).Text.Trim().Trim(new char[1] { '"' });
|
||
if (text.Length == 0)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "请输入路径", "提示");
|
||
return;
|
||
}
|
||
if (text.Length == 2 && text[1] == ':')
|
||
{
|
||
text += "\\";
|
||
}
|
||
string text2 = DiagnosePath(text);
|
||
if (text2 != null)
|
||
{
|
||
string text3 = DriveToUnc(text);
|
||
if (text3 != null && text3 != text && DiagnosePath(text3) == null)
|
||
{
|
||
rootDir = text3;
|
||
((Control)txtPath).Text = text3;
|
||
ScanDir();
|
||
return;
|
||
}
|
||
if (TryReconnect(text))
|
||
{
|
||
text2 = DiagnosePath(text);
|
||
if (text2 == null)
|
||
{
|
||
rootDir = text;
|
||
ScanDir();
|
||
return;
|
||
}
|
||
}
|
||
if (text3 != null && DiagnosePath(text3) == null)
|
||
{
|
||
rootDir = text3;
|
||
((Control)txtPath).Text = text3;
|
||
ScanDir();
|
||
return;
|
||
}
|
||
if (ConnectWithAuth(text))
|
||
{
|
||
text2 = DiagnosePath(text);
|
||
if (text2 == null)
|
||
{
|
||
rootDir = text;
|
||
ScanDir();
|
||
return;
|
||
}
|
||
}
|
||
MessageBox.Show((IWin32Window)(object)this, "路径无法访问:" + text + "\r\n\r\n诊断结果:\r\n" + text2 + "\r\n\r\n排查建议:\r\n- 若提示“驱动器未映射/离线”:在资源管理器中双击 Z 盘确认能否打开;\r\n- 若 NAS 不可达:确认服务器在线、网络已连接;\r\n- 也可尝试手动执行:net use " + (GetShareTarget(text) ?? text) + " /user:用户名 密码", "提示", (MessageBoxButtons)0, (MessageBoxIcon)48);
|
||
}
|
||
else
|
||
{
|
||
rootDir = text;
|
||
ScanDir();
|
||
}
|
||
}
|
||
|
||
internal static string DriveToUnc(string path)
|
||
{
|
||
if (path.Length < 2 || path[1] != ':')
|
||
{
|
||
return null;
|
||
}
|
||
string shareTarget = GetShareTarget(path);
|
||
if (string.IsNullOrEmpty(shareTarget))
|
||
{
|
||
return null;
|
||
}
|
||
string text = path.Substring(2);
|
||
return shareTarget + text;
|
||
}
|
||
|
||
private bool ConnectWithAuth(string path)
|
||
{
|
||
//IL_0318: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_002a: Expected O, but got Unknown
|
||
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0072: Expected O, but got Unknown
|
||
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00a8: Expected O, but got Unknown
|
||
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00cf: Expected O, but got Unknown
|
||
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0102: Expected O, but got Unknown
|
||
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_010a: Expected O, but got Unknown
|
||
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_012e: Expected O, but got Unknown
|
||
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0157: Expected O, but got Unknown
|
||
//IL_0161: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0168: Expected O, but got Unknown
|
||
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0198: Expected O, but got Unknown
|
||
//IL_0325: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_032b: Invalid comparison between Unknown and I4
|
||
//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
|
||
string shareTarget = GetShareTarget(path);
|
||
if (shareTarget == null)
|
||
{
|
||
return false;
|
||
}
|
||
Form val = new Form();
|
||
((Control)val).Text = "连接网络共享";
|
||
val.FormBorderStyle = (FormBorderStyle)3;
|
||
val.MaximizeBox = false;
|
||
val.MinimizeBox = false;
|
||
val.StartPosition = (FormStartPosition)4;
|
||
val.ClientSize = new Size(360, 168);
|
||
Label val2 = new Label();
|
||
((Control)val2).Text = "共享:" + shareTarget;
|
||
((Control)val2).ForeColor = Color.DimGray;
|
||
((Control)val2).SetBounds(14, 12, 332, 22);
|
||
Label val3 = new Label();
|
||
((Control)val3).Text = "用户名:";
|
||
((Control)val3).SetBounds(14, 42, 64, 24);
|
||
TextBox tUser = new TextBox();
|
||
((Control)tUser).SetBounds(82, 40, 262, 24);
|
||
((Control)tUser).Font = new Font("Microsoft YaHei UI", 9f);
|
||
Label val4 = new Label();
|
||
((Control)val4).Text = "密码:";
|
||
((Control)val4).SetBounds(14, 72, 64, 24);
|
||
TextBox val5 = new TextBox();
|
||
((Control)val5).SetBounds(82, 70, 262, 24);
|
||
((Control)val5).Font = new Font("Microsoft YaHei UI", 9f);
|
||
val5.UseSystemPasswordChar = true;
|
||
Button val6 = new Button();
|
||
((Control)val6).Text = "连接";
|
||
val6.DialogResult = (DialogResult)1;
|
||
((Control)val6).SetBounds(196, 108, 70, 30);
|
||
Button val7 = new Button();
|
||
((Control)val7).Text = "取消";
|
||
val7.DialogResult = (DialogResult)2;
|
||
((Control)val7).SetBounds(274, 108, 70, 30);
|
||
((Control)val).Controls.AddRange((Control[])(object)new Control[7]
|
||
{
|
||
(Control)val2,
|
||
(Control)val3,
|
||
(Control)tUser,
|
||
(Control)val4,
|
||
(Control)val5,
|
||
(Control)val6,
|
||
(Control)val7
|
||
});
|
||
val.AcceptButton = (IButtonControl)(object)val6;
|
||
val.CancelButton = (IButtonControl)(object)val7;
|
||
val.Shown += delegate
|
||
{
|
||
((Control)tUser).Focus();
|
||
};
|
||
while ((int)val.ShowDialog((IWin32Window)(object)this) == 1)
|
||
{
|
||
string text = ((Control)tUser).Text.Trim();
|
||
string text2 = ((Control)val5).Text;
|
||
try
|
||
{
|
||
NETRESOURCE netResource = default(NETRESOURCE);
|
||
netResource.dwType = 1;
|
||
netResource.lpRemoteName = shareTarget;
|
||
int num = NetApi.WNetAddConnection2(ref netResource, text2, (text.Length == 0) ? null : text, 1);
|
||
if (num == 1219)
|
||
{
|
||
NetApi.WNetCancelConnection2(shareTarget, 0, force: true);
|
||
num = NetApi.WNetAddConnection2(ref netResource, text2, (text.Length == 0) ? null : text, 1);
|
||
}
|
||
if (num == 0)
|
||
{
|
||
((Component)(object)val).Dispose();
|
||
return true;
|
||
}
|
||
MessageBox.Show((IWin32Window)(object)this, "连接失败,错误码 " + num + "。\r\n请检查 NAS 用户名/密码是否正确。", "提示", (MessageBoxButtons)0, (MessageBoxIcon)48);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "连接出错:" + ex.Message, "提示", (MessageBoxButtons)0, (MessageBoxIcon)48);
|
||
}
|
||
}
|
||
((Component)(object)val).Dispose();
|
||
return false;
|
||
}
|
||
|
||
internal static string GetShareTarget(string path)
|
||
{
|
||
if (path.StartsWith("\\\\", StringComparison.Ordinal))
|
||
{
|
||
string[] array = path.TrimStart(new char[1] { '\\' }).Split(new char[1] { '\\' });
|
||
if (array.Length >= 2)
|
||
{
|
||
return "\\\\" + array[0] + "\\" + array[1];
|
||
}
|
||
return null;
|
||
}
|
||
if (path.Length >= 2 && path[1] == ':')
|
||
{
|
||
string text = path.Substring(0, 1);
|
||
try
|
||
{
|
||
using RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("Network\\" + text);
|
||
if (registryKey != null)
|
||
{
|
||
object value = registryKey.GetValue("RemotePath");
|
||
if (value != null)
|
||
{
|
||
return value.ToString();
|
||
}
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
internal static bool TryReconnect(string path)
|
||
{
|
||
string shareTarget = GetShareTarget(path);
|
||
if (shareTarget == null)
|
||
{
|
||
return false;
|
||
}
|
||
try
|
||
{
|
||
NETRESOURCE netResource = default(NETRESOURCE);
|
||
netResource.dwType = 1;
|
||
netResource.lpRemoteName = shareTarget;
|
||
int num = NetApi.WNetAddConnection2(ref netResource, null, null, 1);
|
||
return num == 0;
|
||
}
|
||
catch
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
internal static string DiagnosePath(string path)
|
||
{
|
||
string text = ((path.Length >= 2 && path[1] == ':') ? path.Substring(0, 2) : null);
|
||
if (text != null)
|
||
{
|
||
bool flag = false;
|
||
string[] logicalDrives = Environment.GetLogicalDrives();
|
||
foreach (string a in logicalDrives)
|
||
{
|
||
if (string.Equals(a, text + "\\", StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
flag = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!flag)
|
||
{
|
||
return "当前进程无法看到驱动器 " + text + "。\r\n映射盘是“按用户会话”生效的,若本工具由后台/提权进程启动,可能看不到图形界面里已映射的盘。\r\n此时请改用 UNC 路径(见下方建议)。";
|
||
}
|
||
}
|
||
try
|
||
{
|
||
DirectoryInfo directoryInfo = new DirectoryInfo(path);
|
||
directoryInfo.GetDirectories();
|
||
return null;
|
||
}
|
||
catch (DirectoryNotFoundException)
|
||
{
|
||
return "目录不存在:" + path;
|
||
}
|
||
catch (UnauthorizedAccessException)
|
||
{
|
||
return "拒绝访问(当前身份无权限,或网络共享要求重新登录凭据)";
|
||
}
|
||
catch (IOException ex3)
|
||
{
|
||
return "IO/网络错误:" + ex3.Message + "\r\n——通常是网络路径不可达(NAS 离线/断网)导致。";
|
||
}
|
||
catch (Exception ex4)
|
||
{
|
||
return ex4.Message;
|
||
}
|
||
}
|
||
|
||
private void ScanDir()
|
||
{
|
||
if (isScanning)
|
||
{
|
||
return;
|
||
}
|
||
isScanning = true;
|
||
categories.Clear();
|
||
allItems.Clear();
|
||
pathIndex.Clear();
|
||
catBox.Nodes.Clear();
|
||
nodeIndex.Clear();
|
||
((Control)flow).Controls.Clear();
|
||
renderedPics.Clear();
|
||
cache.Clear();
|
||
|
||
string scanRoot = rootDir;
|
||
HashSet<string> exts = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".ttf", ".otf", ".ttc", ".ote" };
|
||
|
||
// 1) 先尝试读缓存,立即填充界面(秒显)
|
||
FontCache cached;
|
||
bool hasCache = FontCache.TryLoad(scanRoot, out cached);
|
||
if (hasCache)
|
||
{
|
||
foreach (FontItem it in cached.Items)
|
||
{
|
||
allItems.Add(it);
|
||
pathIndex[it.Path] = it;
|
||
string key = string.IsNullOrEmpty(it.Cat) ? "(未分类)" : it.Cat;
|
||
List<FontItem> lst;
|
||
if (!categories.TryGetValue(key, out lst)) { lst = new List<FontItem>(); categories[key] = lst; }
|
||
lst.Add(it);
|
||
}
|
||
FillTreeFromCategories();
|
||
((Control)lblStat).Text = cached.Items.Count + " 个字体(缓存),后台校验中…";
|
||
((Control)lblProg).Text = "";
|
||
}
|
||
else
|
||
{
|
||
((Control)lblStat).Text = "正在扫描字体目录…";
|
||
((Control)lblProg).Text = "";
|
||
}
|
||
|
||
// 2) 后台递归遍历:每扫完一个目录就回 UI 更新该节点计数,进度可见
|
||
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(delegate
|
||
{
|
||
string fail = null;
|
||
Dictionary<string, FontItem> cachedByPath = null;
|
||
if (hasCache)
|
||
{
|
||
cachedByPath = new Dictionary<string, FontItem>(StringComparer.OrdinalIgnoreCase);
|
||
foreach (FontItem it in cached.Items) { cachedByPath[it.Path] = it; }
|
||
}
|
||
Dictionary<string, FontCache.Stamp> bgStamps = new Dictionary<string, FontCache.Stamp>(StringComparer.OrdinalIgnoreCase);
|
||
bool[] firstBatch = new bool[1] { true };
|
||
|
||
// 生产者-消费者:一个线程快速遍历目录把文件路径入队,N 个线程同时取文件解析,I/O 等待重叠
|
||
Queue<object[]> q = new Queue<object[]>();
|
||
object qlock = new object();
|
||
bool[] producerDone = new bool[1] { false };
|
||
object stampsLock = new object();
|
||
int progressTotal = 0;
|
||
|
||
Action<string, string> walk = null;
|
||
walk = delegate (string dir, string rel)
|
||
{
|
||
try
|
||
{
|
||
string[] files = Directory.GetFiles(dir);
|
||
// 批量入队,减少锁竞争;文件信息延迟到消费线程并行读取
|
||
lock (qlock)
|
||
{
|
||
foreach (string f in files)
|
||
{
|
||
if (!exts.Contains(Path.GetExtension(f))) continue;
|
||
q.Enqueue(new object[] { f, rel });
|
||
}
|
||
}
|
||
}
|
||
catch { }
|
||
try
|
||
{
|
||
string[] dirs = Directory.GetDirectories(dir);
|
||
foreach (string d in dirs)
|
||
{
|
||
string sub = (rel.Length == 0) ? Path.GetFileName(d) : (rel + "\\" + Path.GetFileName(d));
|
||
walk(d, sub);
|
||
}
|
||
}
|
||
catch { }
|
||
};
|
||
|
||
Action consume = delegate
|
||
{
|
||
List<FontItem> localBatch = new List<FontItem>();
|
||
while (true)
|
||
{
|
||
object[] job = null;
|
||
lock (qlock)
|
||
{
|
||
if (q.Count > 0) job = q.Dequeue();
|
||
else if (producerDone[0]) { FlushBatch(localBatch, ref progressTotal, firstBatch); return; }
|
||
else { System.Threading.Thread.Sleep(1); continue; }
|
||
}
|
||
string f = (string)job[0];
|
||
string rel = (string)job[1];
|
||
// 文件信息并行读取(NAS 上并行 stat 比串行快)
|
||
long size = 0;
|
||
long mtime = 0;
|
||
try { FileInfo fi = new FileInfo(f); size = fi.Length; mtime = fi.LastWriteTime.Ticks; } catch { }
|
||
FontItem reuse = null;
|
||
if (cachedByPath != null)
|
||
{
|
||
FontItem ci;
|
||
FontCache.Stamp cs;
|
||
if (cachedByPath.TryGetValue(f, out ci) &&
|
||
cached.Stamps.TryGetValue(f, out cs) &&
|
||
cs.Size == size && cs.Mtime == mtime)
|
||
{
|
||
reuse = ci;
|
||
}
|
||
}
|
||
FontItem it = reuse ?? new FontItem
|
||
{
|
||
Path = f,
|
||
Name = Path.GetFileName(f),
|
||
DisplayName = FontNameParser.GetDisplayName(f, Path.GetFileName(f)),
|
||
Cat = rel
|
||
};
|
||
lock (stampsLock)
|
||
{
|
||
bgStamps[f] = new FontCache.Stamp { Size = size, Mtime = mtime };
|
||
}
|
||
localBatch.Add(it);
|
||
if (localBatch.Count >= 8)
|
||
{
|
||
List<FontItem> flush = localBatch;
|
||
localBatch = new List<FontItem>();
|
||
FlushBatch(flush, ref progressTotal, firstBatch);
|
||
}
|
||
}
|
||
};
|
||
|
||
|
||
int nw = Math.Max(2, Environment.ProcessorCount);
|
||
List<System.Threading.Thread> workers = new List<System.Threading.Thread>();
|
||
for (int w = 0; w < nw; w++)
|
||
{
|
||
System.Threading.Thread pt = new System.Threading.Thread(new System.Threading.ThreadStart(consume));
|
||
pt.IsBackground = true;
|
||
pt.Start();
|
||
workers.Add(pt);
|
||
}
|
||
try { walk(scanRoot, ""); }
|
||
catch (Exception ex2) { fail = ex2.Message; }
|
||
producerDone[0] = true;
|
||
foreach (System.Threading.Thread pt in workers) pt.Join();
|
||
|
||
BeginInvoke(new MethodInvoker(delegate
|
||
{
|
||
isScanning = false;
|
||
if (fail != null)
|
||
{
|
||
((Control)lblStat).Text = "读取目录失败";
|
||
MessageBox.Show((IWin32Window)(object)this, "读取目录失败:" + fail, "提示", (MessageBoxButtons)0, (MessageBoxIcon)48);
|
||
return;
|
||
}
|
||
FillTreeFromCategories();
|
||
((Control)lblStat).Text = allItems.Count + " 个字体 / " + categories.Count + " 个分类";
|
||
((Control)lblProg).Text = "目录已加载,可开始预览";
|
||
SaveConfig();
|
||
FontCache.Save(new FontCache { RootDir = scanRoot, Items = allItems, Stamps = bgStamps });
|
||
}));
|
||
}));
|
||
t.IsBackground = true;
|
||
t.SetApartmentState(System.Threading.ApartmentState.STA);
|
||
t.Start();
|
||
}
|
||
|
||
private class DiskEntry
|
||
{
|
||
public string Path;
|
||
public string Rel;
|
||
public long Size;
|
||
public long Mtime;
|
||
}
|
||
|
||
private List<DiskEntry> WalkDisk(string dir, string rel, HashSet<string> exts)
|
||
{
|
||
List<DiskEntry> result = new List<DiskEntry>();
|
||
try
|
||
{
|
||
string[] files = Directory.GetFiles(dir);
|
||
foreach (string f in files)
|
||
{
|
||
if (exts.Contains(Path.GetExtension(f)))
|
||
{
|
||
FileInfo fi = new FileInfo(f);
|
||
result.Add(new DiskEntry { Path = f, Rel = rel, Size = fi.Length, Mtime = fi.LastWriteTime.Ticks });
|
||
}
|
||
}
|
||
string[] dirs = Directory.GetDirectories(dir);
|
||
foreach (string d in dirs)
|
||
{
|
||
string sub = (rel.Length == 0) ? Path.GetFileName(d) : (rel + "\\" + Path.GetFileName(d));
|
||
result.AddRange(WalkDisk(d, sub, exts));
|
||
}
|
||
}
|
||
catch { }
|
||
return result;
|
||
}
|
||
|
||
private void FlushBatch(List<FontItem> flush, ref int progressTotal, bool[] firstBatch)
|
||
{
|
||
int total = System.Threading.Interlocked.Add(ref progressTotal, flush.Count);
|
||
BeginInvoke(new MethodInvoker(delegate
|
||
{
|
||
if (firstBatch[0])
|
||
{
|
||
categories.Clear();
|
||
allItems.Clear();
|
||
pathIndex.Clear();
|
||
catBox.Nodes.Clear();
|
||
nodeIndex.Clear();
|
||
firstBatch[0] = false;
|
||
}
|
||
HashSet<string> touched = new HashSet<string>(StringComparer.Ordinal);
|
||
foreach (FontItem fi in flush)
|
||
{
|
||
string key = string.IsNullOrEmpty(fi.Cat) ? "(未分类)" : fi.Cat;
|
||
List<FontItem> lst;
|
||
if (!categories.TryGetValue(key, out lst)) { lst = new List<FontItem>(); categories[key] = lst; }
|
||
lst.Add(fi);
|
||
allItems.Add(fi);
|
||
pathIndex[fi.Path] = fi;
|
||
touched.Add(key);
|
||
}
|
||
foreach (string key in touched)
|
||
{
|
||
List<FontItem> lst;
|
||
if (categories.TryGetValue(key, out lst))
|
||
{
|
||
InsertCatNode(key, lst.Count);
|
||
}
|
||
}
|
||
((Control)lblStat).Text = "正在扫描… 已 " + total + " 个字体";
|
||
}));
|
||
}
|
||
|
||
private void FillTreeFromCategories()
|
||
{
|
||
int num = 0;
|
||
List<string> list = new List<string>(categories.Keys);
|
||
list.Sort((string a, string b) => categories[b].Count.CompareTo(categories[a].Count));
|
||
catBox.Nodes.Clear();
|
||
nodeIndex.Clear();
|
||
foreach (string item in list)
|
||
{
|
||
int count = categories[item].Count;
|
||
num += count;
|
||
InsertCatNode(item, count);
|
||
}
|
||
InsertTagNodes();
|
||
catBox.CollapseAll();
|
||
}
|
||
|
||
private void AddDirCategory(string dir, string rel, HashSet<string> exts)
|
||
{
|
||
try
|
||
{
|
||
List<FontItem> list = null;
|
||
string[] files = Directory.GetFiles(dir);
|
||
foreach (string text in files)
|
||
{
|
||
if (exts.Contains(Path.GetExtension(text)))
|
||
{
|
||
if (list == null)
|
||
{
|
||
list = new List<FontItem>();
|
||
}
|
||
string displayName = FontNameParser.GetDisplayName(text, Path.GetFileName(text));
|
||
list.Add(new FontItem
|
||
{
|
||
Path = text,
|
||
Name = Path.GetFileName(text),
|
||
DisplayName = displayName,
|
||
Cat = rel
|
||
});
|
||
}
|
||
}
|
||
if (list != null)
|
||
{
|
||
string key = ((rel.Length == 0) ? "(未分类)" : rel);
|
||
categories[key] = list;
|
||
foreach (FontItem item in list)
|
||
{
|
||
allItems.Add(item);
|
||
pathIndex[item.Path] = item;
|
||
}
|
||
}
|
||
files = Directory.GetDirectories(dir);
|
||
foreach (string text2 in files)
|
||
{
|
||
string rel2 = ((rel.Length == 0) ? Path.GetFileName(text2) : (rel + "\\" + Path.GetFileName(text2)));
|
||
AddDirCategory(text2, rel2, exts);
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
}
|
||
|
||
private void InsertCatNode(string key, int count)
|
||
{
|
||
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0076: Expected O, but got Unknown
|
||
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00ed: Expected O, but got Unknown
|
||
string[] array = key.Split(new char[1] { '\\' });
|
||
TreeNode val = null;
|
||
string text = "";
|
||
for (int i = 0; i < array.Length; i++)
|
||
{
|
||
text = ((i == 0) ? array[i] : (text + "\\" + array[i]));
|
||
TreeNodeCollection val2 = ((val == null) ? catBox.Nodes : val.Nodes);
|
||
TreeNode val3 = null;
|
||
// 用字典 O(1) 查找节点,避免遍历子节点集合
|
||
if (!nodeIndex.TryGetValue(text, out val3))
|
||
{
|
||
val3 = new TreeNode(array[i]);
|
||
val3.Tag = text;
|
||
val2.Add(val3);
|
||
nodeIndex[text] = val3;
|
||
}
|
||
if (i == array.Length - 1)
|
||
{
|
||
val3.Text = array[i] + " (" + count + ")";
|
||
}
|
||
val = val3;
|
||
}
|
||
}
|
||
|
||
private void SetNodeChecked(TreeNode n, bool check)
|
||
{
|
||
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0024: Expected O, but got Unknown
|
||
n.Checked = check;
|
||
foreach (TreeNode node in n.Nodes)
|
||
{
|
||
TreeNode n2 = node;
|
||
SetNodeChecked(n2, check);
|
||
}
|
||
}
|
||
|
||
private void CollectChecked(TreeNodeCollection coll, List<FontItem> items)
|
||
{
|
||
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_001c: Expected O, but got Unknown
|
||
foreach (TreeNode item in coll)
|
||
{
|
||
TreeNode val = item;
|
||
if (val.Checked && val.Tag != null)
|
||
{
|
||
string text = (string)val.Tag;
|
||
FontItem value2;
|
||
List<FontItem> value3;
|
||
if (text.StartsWith("TAG:", StringComparison.Ordinal))
|
||
{
|
||
string key = text.Substring("TAG:".Length);
|
||
if (tags.TryGetValue(key, out var value))
|
||
{
|
||
foreach (string item2 in value)
|
||
{
|
||
if (pathIndex.TryGetValue(item2, out value2) && !items.Contains(value2))
|
||
{
|
||
items.Add(value2);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (categories.TryGetValue(text, out value3))
|
||
{
|
||
foreach (FontItem item3 in value3)
|
||
{
|
||
value2 = item3;
|
||
if (!items.Contains(value2))
|
||
{
|
||
items.Add(value2);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
CollectChecked(val.Nodes, items);
|
||
}
|
||
}
|
||
|
||
private void StartRender(bool append)
|
||
{
|
||
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
|
||
if (!append && worker != null && worker.IsRunning())
|
||
{
|
||
return;
|
||
}
|
||
if (rootDir.Length == 0)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "请先选择字体目录", "提示");
|
||
return;
|
||
}
|
||
string kw = ((Control)txtSearch).Text.Trim();
|
||
List<FontItem> list = new List<FontItem>();
|
||
// 搜索框非空时跳过分类勾选检查
|
||
if (kw.Length == 0)
|
||
{
|
||
CollectChecked(catBox.Nodes, list);
|
||
if (list.Count == 0)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "请至少选择一个分类", "提示");
|
||
return;
|
||
}
|
||
}
|
||
string text = ((Control)txtInput).Text;
|
||
if (text.Trim().Length == 0)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "请先输入预览文字", "提示");
|
||
return;
|
||
}
|
||
List<FontItem> list2 = new List<FontItem>();
|
||
if (kw.Length > 0)
|
||
{
|
||
foreach (FontItem it in allItems)
|
||
{
|
||
if ((it.DisplayName != null && it.DisplayName.IndexOf(kw, StringComparison.OrdinalIgnoreCase) >= 0)
|
||
|| it.Name.IndexOf(kw, StringComparison.OrdinalIgnoreCase) >= 0)
|
||
{
|
||
list2.Add(it);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
CollectChecked(catBox.Nodes, list2);
|
||
}
|
||
if (list2.Count == 0)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "所选分类没有字体" + ((kw.Length > 0) ? "(搜索「" + kw + "」无匹配)" : ""), "提示");
|
||
return;
|
||
}
|
||
int num = (int)numLimit.Value;
|
||
int num2 = ((num <= 0) ? list2.Count : Math.Min(num, list2.Count));
|
||
if (append)
|
||
{
|
||
num2 = list2.Count;
|
||
}
|
||
int num3 = fgColor.ToArgb();
|
||
int num4 = bgColor.ToArgb();
|
||
string text2 = text + "|" + numSize.Value + "|" + num3 + "|" + num4;
|
||
if (text2 != renderHash)
|
||
{
|
||
cache.Clear();
|
||
renderHash = text2;
|
||
}
|
||
if (worker == null || !worker.IsRunning())
|
||
{
|
||
if (!append)
|
||
{
|
||
((Control)flow).Controls.Clear();
|
||
renderedPics.Clear();
|
||
}
|
||
worker = new Worker(this, list2, num2, text, (int)numSize.Value, fgColor, bgColor, cache);
|
||
((Control)btnRender).Enabled = false;
|
||
((Control)btnStop).Enabled = true;
|
||
((Control)btnMore).Enabled = false;
|
||
prog.Value = 0;
|
||
((Control)lblProg).Text = "正在渲染 0 / " + num2 + " ...";
|
||
worker.Completed += OnWorkerCompleted;
|
||
worker.Start();
|
||
}
|
||
}
|
||
|
||
private void OnWorkerCompleted(bool cancelled, int done, int failed, int remain, List<Worker.CardData> cards)
|
||
{
|
||
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0121: Expected O, but got Unknown
|
||
((Control)btnRender).Enabled = true;
|
||
((Control)btnStop).Enabled = false;
|
||
if (remain > 0)
|
||
{
|
||
((Control)btnMore).Enabled = true;
|
||
((Control)lblProg).Text = "已渲染 " + done + ",失败 " + failed + ",还有 " + remain + " 个未渲染。点「继续加载更多」接着渲染剩余。";
|
||
}
|
||
else
|
||
{
|
||
((Control)btnMore).Enabled = false;
|
||
((Control)lblProg).Text = "渲染完成:" + done + "(失败 " + failed + ")";
|
||
}
|
||
if (cards == null)
|
||
{
|
||
return;
|
||
}
|
||
int idx = 0;
|
||
Timer t = new Timer();
|
||
t.Interval = 20;
|
||
t.Tick += delegate
|
||
{
|
||
int num = Math.Min(60, cards.Count - idx);
|
||
for (int i = 0; i < num; i++)
|
||
{
|
||
AddCard(cards[idx + i]);
|
||
}
|
||
idx += num;
|
||
if (idx >= cards.Count)
|
||
{
|
||
t.Stop();
|
||
((Component)(object)t).Dispose();
|
||
}
|
||
};
|
||
t.Start();
|
||
}
|
||
|
||
private void AddCard(Worker.CardData data)
|
||
{
|
||
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00fa: Expected O, but got Unknown
|
||
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_010b: Expected O, but got Unknown
|
||
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0145: Expected O, but got Unknown
|
||
//IL_016e: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0175: Expected O, but got Unknown
|
||
//IL_01db: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_01e2: Expected O, but got Unknown
|
||
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0216: Expected O, but got Unknown
|
||
//IL_027e: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0288: Expected O, but got Unknown
|
||
//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_03b3: Expected O, but got Unknown
|
||
//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_02ff: Expected O, but got Unknown
|
||
int width = ((Control)flow).ClientSize.Width;
|
||
Padding padding = ((Control)flow).Padding;
|
||
int num = Math.Max(300, width - padding.Horizontal - 8);
|
||
int num2 = 0;
|
||
int num3 = 0;
|
||
if (data.Bitmap != null)
|
||
{
|
||
num3 = ((Image)data.Bitmap).Width;
|
||
num2 = ((Image)data.Bitmap).Height;
|
||
num = Math.Max(num, num3 + 36);
|
||
}
|
||
RoundPanel roundPanel = UiTheme.CreateCard(num, Math.Max(50, 44 + num2 + 6));
|
||
((Control)roundPanel).Margin = new Padding(16, 0, 16, 12);
|
||
num = ((Control)roundPanel).Width;
|
||
string curPath = data.Path ?? "";
|
||
ContextMenuStrip val = new ContextMenuStrip();
|
||
ToolStripMenuItem miCmp = new ToolStripMenuItem("加入对比列表");
|
||
((ToolStripItem)miCmp).Click += delegate
|
||
{
|
||
FontItem fi;
|
||
if (string.IsNullOrEmpty(curPath) || !pathIndex.TryGetValue(curPath, out fi))
|
||
{
|
||
((Control)lblProg).Text = "找不到该字体。";
|
||
return;
|
||
}
|
||
bool exists = false;
|
||
foreach (FontItem ex in compareList) { if (string.Equals(ex.Path, curPath, StringComparison.OrdinalIgnoreCase)) { exists = true; break; } }
|
||
if (exists)
|
||
{
|
||
((Control)lblProg).Text = "已在对比列表中(当前 " + compareList.Count + " 个)";
|
||
}
|
||
else
|
||
{
|
||
compareList.Add(fi);
|
||
((Control)lblProg).Text = "已加入对比列表(当前 " + compareList.Count + " 个)";
|
||
}
|
||
};
|
||
((ToolStrip)val).Items.Add((ToolStripItem)(object)miCmp);
|
||
val.Opening += delegate { miCmp.Text = "加入对比列表(当前 " + compareList.Count + " 个)"; };
|
||
|
||
ToolStripMenuItem val3 = new ToolStripMenuItem("以快捷方式安装(复制到左侧目录)");
|
||
((ToolStripItem)val3).Click += delegate
|
||
{
|
||
MoveInstallOne(curPath);
|
||
};
|
||
if (string.IsNullOrEmpty(curPath) || !File.Exists(DriveToUnc(curPath) ?? curPath))
|
||
{
|
||
((ToolStripItem)val3).Enabled = false;
|
||
}
|
||
((ToolStrip)val).Items.Add((ToolStripItem)(object)val3);
|
||
|
||
ToolStripMenuItem miCmpClear = new ToolStripMenuItem("清空对比列表");
|
||
((ToolStripItem)miCmpClear).Click += delegate
|
||
{
|
||
compareList.Clear();
|
||
((Control)lblProg).Text = "对比列表已清空。";
|
||
};
|
||
((ToolStrip)val).Items.Add((ToolStripItem)(object)miCmpClear);
|
||
((Control)roundPanel).ContextMenuStrip = val;
|
||
// 左侧强调色竖条 + 字体名标签 + 预览图,统一走 UiTheme 工厂
|
||
((Control)roundPanel).Controls.Add(UiTheme.CreateAccentBar(14, 16));
|
||
string text = (string.IsNullOrEmpty(data.DisplayName) ? data.Name : data.DisplayName);
|
||
Label val5 = UiTheme.CreateCardTitle(text, 26, 12, ((Control)roundPanel).Width - 44);
|
||
((Control)val5).Click += delegate
|
||
{
|
||
CopyName(data.Name);
|
||
};
|
||
((Control)val5).ContextMenuStrip = val;
|
||
((Control)roundPanel).Controls.Add((Control)(object)val5);
|
||
if (data.Bitmap != null)
|
||
{
|
||
PictureBox val6 = UiTheme.CreatePreviewBox(18, 46, num3, num2);
|
||
val6.Image = (Image)(object)data.Bitmap;
|
||
((Control)val6).Click += delegate
|
||
{
|
||
CopyName(data.Name);
|
||
FontItem fi;
|
||
if (!string.IsNullOrEmpty(curPath) && pathIndex.TryGetValue(curPath, out fi))
|
||
{
|
||
curPreviewItem = fi;
|
||
curPreviewPic = val6;
|
||
}
|
||
};
|
||
((Control)val6).ContextMenuStrip = val;
|
||
((Control)roundPanel).Controls.Add((Control)(object)val6);
|
||
FontItem fiTrack;
|
||
if (!string.IsNullOrEmpty(curPath) && pathIndex.TryGetValue(curPath, out fiTrack))
|
||
{
|
||
renderedPics.Add(new KeyValuePair<FontItem, PictureBox>(fiTrack, val6));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
((Control)roundPanel).BackColor = Color.FromArgb(247, 248, 250);
|
||
Label val7 = new Label();
|
||
((Control)val7).Text = "加载失败";
|
||
((Control)val7).ForeColor = Color.Gray;
|
||
((Control)val7).SetBounds(24, 64, 140, 20);
|
||
((Control)roundPanel).Controls.Add((Control)(object)val7);
|
||
}
|
||
((Control)flow).Controls.Add((Control)(object)roundPanel);
|
||
}
|
||
|
||
private void RerenderCurrent()
|
||
{
|
||
if (renderedPics.Count == 0) return;
|
||
try
|
||
{
|
||
string sample = (txtInput != null && !string.IsNullOrEmpty(txtInput.Text)) ? txtInput.Text : "永字八法 横平竖直 你好世界 ABC 0123";
|
||
int sz = (int)numSize.Value;
|
||
foreach (var kv in renderedPics)
|
||
{
|
||
if (kv.Value.IsDisposed) continue;
|
||
bool failed;
|
||
Bitmap bmp = Worker.RenderFont(kv.Key.Path, kv.Key.Name, sample, sz, Color.Black, Color.White, out failed);
|
||
if (bmp != null)
|
||
{
|
||
Bitmap old = (Bitmap)kv.Value.Image;
|
||
kv.Value.Image = bmp;
|
||
kv.Value.Size = bmp.Size;
|
||
if (old != null) old.Dispose();
|
||
}
|
||
}
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private void CopyName(string name)
|
||
{
|
||
try
|
||
{
|
||
Clipboard.SetText(name);
|
||
((Control)lblProg).Text = "已复制: " + name;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
((Control)lblProg).Text = "复制失败:" + ex.Message;
|
||
}
|
||
}
|
||
|
||
private void RestoreLastDir()
|
||
{
|
||
try
|
||
{
|
||
if (!File.Exists(CfgFile))
|
||
{
|
||
return;
|
||
}
|
||
string[] array = File.ReadAllLines(CfgFile);
|
||
if (array.Length == 0)
|
||
{
|
||
return;
|
||
}
|
||
if (array.Length > 1 && !string.IsNullOrEmpty(array[1].Trim()))
|
||
{
|
||
string text = array[1].Trim();
|
||
if (text.Length == 2 && text[1] == ':')
|
||
{
|
||
text += "\\";
|
||
}
|
||
moveDir = text;
|
||
if (txtMoveDir != null)
|
||
{
|
||
((Control)txtMoveDir).Text = text;
|
||
}
|
||
}
|
||
string text2 = (array[0] ?? "").Trim();
|
||
if (text2.Length == 0)
|
||
{
|
||
return;
|
||
}
|
||
if (text2.Length == 2 && text2[1] == ':')
|
||
{
|
||
text2 += "\\";
|
||
}
|
||
string text3 = text2;
|
||
string text4 = DiagnosePath(text3);
|
||
if (text4 != null)
|
||
{
|
||
string text5 = DriveToUnc(text3);
|
||
if (text5 != null)
|
||
{
|
||
// 盘符在当前 token 不可见(典型:管理员模式下看不到普通用户映射的网络盘)。
|
||
// 改用 UNC 路径访问,先尝试连接共享,再交给后台扫描;单次探测失败不直接判死。
|
||
TryReconnect(text5);
|
||
text3 = text5;
|
||
}
|
||
else
|
||
{
|
||
((Control)lblStat).Text = "上次目录不可用(已忽略):" + text2;
|
||
return;
|
||
}
|
||
}
|
||
rootDir = text3;
|
||
((Control)txtPath).Text = text3;
|
||
ScanDir();
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
}
|
||
|
||
private void SaveConfig()
|
||
{
|
||
try
|
||
{
|
||
AtomicWrite(CfgFile, rootDir + "\r\n" + moveDir);
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
}
|
||
|
||
private void LoadTags()
|
||
{
|
||
tags.Clear();
|
||
try
|
||
{
|
||
if (!File.Exists(TagFile))
|
||
{
|
||
return;
|
||
}
|
||
string[] array = File.ReadAllLines(TagFile);
|
||
foreach (string text in array)
|
||
{
|
||
if (string.IsNullOrEmpty(text))
|
||
{
|
||
continue;
|
||
}
|
||
int num = text.IndexOf('\t');
|
||
if (num > 0)
|
||
{
|
||
string key = text.Substring(0, num);
|
||
string item = text.Substring(num + 1);
|
||
if (!tags.ContainsKey(key))
|
||
{
|
||
tags[key] = new List<string>();
|
||
}
|
||
if (!tags[key].Contains(item))
|
||
{
|
||
tags[key].Add(item);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
}
|
||
|
||
private void SaveTags()
|
||
{
|
||
try
|
||
{
|
||
List<string> list = new List<string>();
|
||
foreach (KeyValuePair<string, List<string>> tag in tags)
|
||
{
|
||
foreach (string item in tag.Value)
|
||
{
|
||
list.Add(tag.Key + "\t" + item);
|
||
}
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
foreach (string line in list)
|
||
{
|
||
sb.Append(line).Append("\r\n");
|
||
}
|
||
AtomicWrite(TagFile, sb.ToString());
|
||
}
|
||
catch
|
||
{
|
||
}
|
||
}
|
||
|
||
// 原子写:先写临时文件再替换,避免程序崩溃时把 config/tags 写坏
|
||
private static void AtomicWrite(string path, string content)
|
||
{
|
||
string dir = Path.GetDirectoryName(path);
|
||
if (!Directory.Exists(dir))
|
||
{
|
||
Directory.CreateDirectory(dir);
|
||
}
|
||
string tmp = path + ".tmp";
|
||
File.WriteAllText(tmp, content, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
|
||
if (File.Exists(path))
|
||
{
|
||
File.Copy(tmp, path, overwrite: true);
|
||
File.Delete(tmp);
|
||
}
|
||
else
|
||
{
|
||
File.Move(tmp, path);
|
||
}
|
||
}
|
||
|
||
private void AddTag(string name)
|
||
{
|
||
if (!string.IsNullOrEmpty(name) && !tags.ContainsKey(name))
|
||
{
|
||
tags[name] = new List<string>();
|
||
SaveTags();
|
||
}
|
||
}
|
||
|
||
private void ToggleTag(string path, string tag)
|
||
{
|
||
if (!string.IsNullOrEmpty(path) && tags.ContainsKey(tag))
|
||
{
|
||
if (tags[tag].Contains(path))
|
||
{
|
||
tags[tag].Remove(path);
|
||
}
|
||
else
|
||
{
|
||
tags[tag].Add(path);
|
||
}
|
||
SaveTags();
|
||
RefreshTagNodes();
|
||
}
|
||
}
|
||
|
||
private void InsertTagNodes()
|
||
{
|
||
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_007e: Expected O, but got Unknown
|
||
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0166: Expected O, but got Unknown
|
||
for (int num = catBox.Nodes.Count - 1; num >= 0; num--)
|
||
{
|
||
if (catBox.Nodes[num].Tag is string text && text.StartsWith("TAG:", StringComparison.Ordinal))
|
||
{
|
||
catBox.Nodes.RemoveAt(num);
|
||
}
|
||
}
|
||
TreeNode val = new TreeNode("★ 标签");
|
||
val.Tag = "TAGROOT";
|
||
List<string> list = new List<string>(tags.Keys);
|
||
list.Sort(StringComparer.OrdinalIgnoreCase);
|
||
foreach (string item in list)
|
||
{
|
||
int num2 = 0;
|
||
foreach (string item2 in tags[item])
|
||
{
|
||
if (pathIndex.ContainsKey(item2))
|
||
{
|
||
num2++;
|
||
}
|
||
}
|
||
if (num2 != 0)
|
||
{
|
||
TreeNode val2 = new TreeNode(item + " (" + num2 + ")");
|
||
val2.Tag = "TAG:" + item;
|
||
val.Nodes.Add(val2);
|
||
}
|
||
}
|
||
if (val.Nodes.Count > 0)
|
||
{
|
||
catBox.Nodes.Insert(0, val);
|
||
val.Expand();
|
||
}
|
||
}
|
||
|
||
private void RefreshTagNodes()
|
||
{
|
||
if (rootDir.Length != 0)
|
||
{
|
||
InsertTagNodes();
|
||
}
|
||
}
|
||
|
||
private string PromptText(string title, string label)
|
||
{
|
||
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_000e: Expected O, but got Unknown
|
||
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_004f: Expected O, but got Unknown
|
||
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0082: Expected O, but got Unknown
|
||
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00b3: Expected O, but got Unknown
|
||
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00ec: Expected O, but got Unknown
|
||
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_014b: Invalid comparison between Unknown and I4
|
||
Form val = new Form();
|
||
((Control)val).Text = title;
|
||
val.FormBorderStyle = (FormBorderStyle)3;
|
||
val.MaximizeBox = false;
|
||
val.MinimizeBox = false;
|
||
val.StartPosition = (FormStartPosition)4;
|
||
val.ClientSize = new Size(320, 116);
|
||
Label val2 = new Label();
|
||
((Control)val2).Text = label;
|
||
((Control)val2).SetBounds(12, 10, 296, 22);
|
||
((Control)val).Controls.Add((Control)(object)val2);
|
||
TextBox tx = new TextBox();
|
||
((Control)tx).SetBounds(12, 36, 296, 24);
|
||
((Control)val).Controls.Add((Control)(object)tx);
|
||
Button val3 = new Button();
|
||
((Control)val3).Text = "确定";
|
||
val3.DialogResult = (DialogResult)1;
|
||
((Control)val3).SetBounds(150, 74, 74, 30);
|
||
((Control)val).Controls.Add((Control)(object)val3);
|
||
Button val4 = new Button();
|
||
((Control)val4).Text = "取消";
|
||
val4.DialogResult = (DialogResult)2;
|
||
((Control)val4).SetBounds(232, 74, 74, 30);
|
||
((Control)val).Controls.Add((Control)(object)val4);
|
||
val.AcceptButton = (IButtonControl)(object)val3;
|
||
val.CancelButton = (IButtonControl)(object)val4;
|
||
val.Shown += delegate
|
||
{
|
||
((Control)tx).Focus();
|
||
};
|
||
string result = (((int)val.ShowDialog((IWin32Window)(object)this) == 1) ? ((Control)tx).Text.Trim() : null);
|
||
((Component)(object)val).Dispose();
|
||
return result;
|
||
}
|
||
|
||
private void ShowTagManager()
|
||
{
|
||
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_001c: Expected O, but got Unknown
|
||
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_008e: Expected O, but got Unknown
|
||
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_012f: Expected O, but got Unknown
|
||
//IL_0161: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0167: Expected O, but got Unknown
|
||
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_019f: Expected O, but got Unknown
|
||
//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_01da: Expected O, but got Unknown
|
||
//IL_0270: Unknown result type (might be due to invalid IL or missing references)
|
||
Form dlg = new Form();
|
||
((Control)dlg).Text = "标签管理";
|
||
dlg.FormBorderStyle = (FormBorderStyle)3;
|
||
dlg.MaximizeBox = false;
|
||
dlg.MinimizeBox = false;
|
||
dlg.StartPosition = (FormStartPosition)4;
|
||
dlg.ClientSize = new Size(360, 340);
|
||
ListView lst = new ListView();
|
||
lst.View = (View)1;
|
||
lst.FullRowSelect = true;
|
||
lst.HideSelection = false;
|
||
lst.Columns.Add("标签", 150);
|
||
lst.Columns.Add("字体数", 100);
|
||
((Control)lst).SetBounds(12, 12, 336, 230);
|
||
Action refresh = delegate
|
||
{
|
||
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_005a: Expected O, but got Unknown
|
||
lst.BeginUpdate();
|
||
lst.Items.Clear();
|
||
List<string> list = new List<string>(tags.Keys);
|
||
list.Sort(StringComparer.OrdinalIgnoreCase);
|
||
foreach (string item in list)
|
||
{
|
||
ListViewItem val5 = new ListViewItem(item);
|
||
val5.SubItems.Add(tags[item].Count.ToString());
|
||
lst.Items.Add(val5);
|
||
}
|
||
lst.EndUpdate();
|
||
};
|
||
refresh();
|
||
Button val = new Button();
|
||
((Control)val).Text = "新建";
|
||
((Control)val).SetBounds(12, 254, 84, 30);
|
||
((Control)val).Click += delegate
|
||
{
|
||
string text4 = PromptText("新建标签", "标签名:");
|
||
if (!string.IsNullOrEmpty(text4))
|
||
{
|
||
AddTag(text4);
|
||
RefreshTagNodes();
|
||
refresh();
|
||
}
|
||
};
|
||
Button val2 = new Button();
|
||
((Control)val2).Text = "重命名";
|
||
((Control)val2).SetBounds(102, 254, 84, 30);
|
||
((Control)val2).Click += delegate
|
||
{
|
||
if (lst.SelectedItems.Count != 0)
|
||
{
|
||
string text2 = lst.SelectedItems[0].Text;
|
||
string text3 = PromptText("重命名标签", "新标签名:");
|
||
if (!string.IsNullOrEmpty(text3) && !(text3 == text2) && tags.TryGetValue(text2, out var value))
|
||
{
|
||
tags[text3] = value;
|
||
tags.Remove(text2);
|
||
SaveTags();
|
||
RefreshTagNodes();
|
||
refresh();
|
||
}
|
||
}
|
||
};
|
||
Button val3 = new Button();
|
||
((Control)val3).Text = "删除";
|
||
((Control)val3).SetBounds(192, 254, 84, 30);
|
||
((Control)val3).Click += delegate
|
||
{
|
||
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0058: Invalid comparison between Unknown and I4
|
||
if (lst.SelectedItems.Count != 0)
|
||
{
|
||
string text = lst.SelectedItems[0].Text;
|
||
if ((int)MessageBox.Show((IWin32Window)(object)dlg, "删除标签「" + text + "」?(仅移除标签,不删除字体文件)", "确认", (MessageBoxButtons)4, (MessageBoxIcon)32) == 6)
|
||
{
|
||
tags.Remove(text);
|
||
SaveTags();
|
||
RefreshTagNodes();
|
||
refresh();
|
||
}
|
||
}
|
||
};
|
||
Button val4 = new Button();
|
||
((Control)val4).Text = "关闭";
|
||
val4.DialogResult = (DialogResult)2;
|
||
((Control)val4).SetBounds(282, 254, 66, 30);
|
||
((Control)dlg).Controls.Add((Control)(object)lst);
|
||
((Control)dlg).Controls.Add((Control)(object)val);
|
||
((Control)dlg).Controls.Add((Control)(object)val2);
|
||
((Control)dlg).Controls.Add((Control)(object)val3);
|
||
((Control)dlg).Controls.Add((Control)(object)val4);
|
||
dlg.ShowDialog((IWin32Window)(object)this);
|
||
((Component)(object)dlg).Dispose();
|
||
}
|
||
|
||
private void ShowExportDialog()
|
||
{
|
||
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
||
SystemFontExportDialog systemFontExportDialog = new SystemFontExportDialog();
|
||
try
|
||
{
|
||
((Form)systemFontExportDialog).ShowDialog((IWin32Window)(object)this);
|
||
}
|
||
finally
|
||
{
|
||
((IDisposable)systemFontExportDialog)?.Dispose();
|
||
}
|
||
}
|
||
|
||
private List<FontItem> CollectTargetItems()
|
||
{
|
||
List<FontItem> list = new List<FontItem>();
|
||
if (rootDir.Length == 0)
|
||
{
|
||
return list;
|
||
}
|
||
CollectChecked(catBox.Nodes, list);
|
||
if (list.Count == 0)
|
||
{
|
||
foreach (KeyValuePair<string, List<FontItem>> category in categories)
|
||
{
|
||
list.AddRange(category.Value);
|
||
}
|
||
}
|
||
return list;
|
||
}
|
||
|
||
private void ShowRenameDialog()
|
||
{
|
||
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
|
||
if (rootDir.Length == 0)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "请先选择字体目录", "提示");
|
||
return;
|
||
}
|
||
List<FontItem> list = CollectTargetItems();
|
||
if (list.Count == 0)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "目录中没有字体文件", "提示");
|
||
return;
|
||
}
|
||
FontRenameDialog fontRenameDialog = new FontRenameDialog(list);
|
||
try
|
||
{
|
||
((Form)fontRenameDialog).ShowDialog((IWin32Window)(object)this);
|
||
if (fontRenameDialog.Renamed)
|
||
{
|
||
ScanDir();
|
||
((Control)lblProg).Text = "已重命名并刷新目录分类。";
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
((IDisposable)fontRenameDialog)?.Dispose();
|
||
}
|
||
}
|
||
|
||
private void MoveInstallOne(string srcPath)
|
||
{
|
||
List<FontItem> list = new List<FontItem>();
|
||
try
|
||
{
|
||
list.Add(new FontItem
|
||
{
|
||
Path = srcPath,
|
||
Name = Path.GetFileName(srcPath)
|
||
});
|
||
}
|
||
catch
|
||
{
|
||
list.Add(new FontItem
|
||
{
|
||
Path = srcPath,
|
||
Name = srcPath
|
||
});
|
||
}
|
||
MoveInstallAll(list);
|
||
}
|
||
|
||
private void MoveInstallBatch()
|
||
{
|
||
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
|
||
if (rootDir.Length == 0)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "请先选择字体目录", "提示");
|
||
return;
|
||
}
|
||
List<FontItem> list = CollectTargetItems();
|
||
if (list.Count == 0)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "目录中没有字体文件", "提示");
|
||
}
|
||
else
|
||
{
|
||
MoveInstallAll(list);
|
||
}
|
||
}
|
||
|
||
private bool MoveInstallAll(List<FontItem> items)
|
||
{
|
||
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00dd: Invalid comparison between Unknown and I4
|
||
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
|
||
//IL_00f2: Invalid comparison between Unknown and I4
|
||
//IL_0689: Unknown result type (might be due to invalid IL or missing references)
|
||
string text = ((Control)txtMoveDir).Text.Trim().Trim(new char[1] { '"' });
|
||
if (text.Length == 2 && text[1] == ':')
|
||
{
|
||
text += "\\";
|
||
}
|
||
if (text.Length == 0)
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "请先在左侧填写『复制目录』", "提示");
|
||
return false;
|
||
}
|
||
string text2 = DriveToUnc(text) ?? text;
|
||
if (!Directory.Exists(text2))
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "复制目录不存在或不可访问,请检查:" + text, "提示");
|
||
return false;
|
||
}
|
||
int num = 0;
|
||
int num2 = 0;
|
||
int num3 = 0;
|
||
int num4 = 0;
|
||
List<string> list = new List<string>();
|
||
List<string> list2 = new List<string>();
|
||
List<string> list3 = new List<string>();
|
||
List<string> list4 = new List<string>();
|
||
Cursor.Current = Cursors.WaitCursor;
|
||
try
|
||
{
|
||
HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||
string b = text2.TrimEnd(new char[1] { '\\' });
|
||
for (int i = 0; i < items.Count; i++)
|
||
{
|
||
string text3 = DriveToUnc(items[i].Path) ?? items[i].Path;
|
||
if (!File.Exists(text3))
|
||
{
|
||
num2++;
|
||
list.Add(items[i].Name);
|
||
continue;
|
||
}
|
||
string a = Path.GetDirectoryName(text3).TrimEnd(new char[1] { '\\' });
|
||
string fontFullPath;
|
||
if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
fontFullPath = Path.Combine(text, items[i].Name);
|
||
num++;
|
||
}
|
||
else
|
||
{
|
||
string text4 = items[i].Name;
|
||
string text5 = Path.Combine(text2, text4);
|
||
if (File.Exists(text5))
|
||
{
|
||
fontFullPath = Path.Combine(text, text4);
|
||
num4++;
|
||
list3.Add(items[i].Name);
|
||
}
|
||
else
|
||
{
|
||
if (hashSet.Contains(text4))
|
||
{
|
||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text4);
|
||
string extension = Path.GetExtension(text4);
|
||
int num5 = 1;
|
||
do
|
||
{
|
||
text4 = fileNameWithoutExtension + "_" + num5 + extension;
|
||
text5 = Path.Combine(text2, text4);
|
||
num5++;
|
||
}
|
||
while (hashSet.Contains(text4) || File.Exists(text5));
|
||
}
|
||
hashSet.Add(text4);
|
||
try
|
||
{
|
||
MoveFileSafe(text3, text5);
|
||
num++;
|
||
}
|
||
catch (Exception)
|
||
{
|
||
num2++;
|
||
list.Add(items[i].Name);
|
||
continue;
|
||
}
|
||
fontFullPath = Path.Combine(text, text4);
|
||
}
|
||
}
|
||
list4.Add(fontFullPath);
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
Cursor.Current = Cursors.Default;
|
||
}
|
||
|
||
// 安装阶段:本进程已是管理员则直接装;普通权限则弹一次 UAC 拉起无界面安装子进程,主程序不重启
|
||
if (!FontManagerEx.IsAdmin())
|
||
{
|
||
try
|
||
{
|
||
ProcessStartInfo processStartInfo = new ProcessStartInfo();
|
||
processStartInfo.FileName = Application.ExecutablePath;
|
||
processStartInfo.Arguments = "/install \"" + text2 + "\"";
|
||
processStartInfo.Verb = "runas";
|
||
Process.Start(processStartInfo);
|
||
((Control)lblProg).Text = "文件已复制,正在调起 UAC 安装…(点「是」完成注册)";
|
||
}
|
||
catch
|
||
{
|
||
MessageBox.Show((IWin32Window)(object)this, "已取消提权:文件已复制,但未注册为系统字体。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
}
|
||
moveDir = text;
|
||
((Control)txtMoveDir).Text = text;
|
||
SaveConfig();
|
||
return true;
|
||
}
|
||
foreach (string fp in list4)
|
||
{
|
||
string lnk;
|
||
string reg;
|
||
if (FontManagerEx.InstallAsShortcut(fp, out lnk, out reg))
|
||
{
|
||
if (lnk != null && lnk.StartsWith("(已安装"))
|
||
{
|
||
num4++;
|
||
list3.Add(Path.GetFileName(fp));
|
||
}
|
||
else
|
||
{
|
||
num3++;
|
||
list2.Add(lnk + " | " + reg);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
num2++;
|
||
list.Add(Path.GetFileName(fp));
|
||
}
|
||
}
|
||
moveDir = text;
|
||
((Control)txtMoveDir).Text = text;
|
||
SaveConfig();
|
||
StringBuilder stringBuilder = new StringBuilder();
|
||
stringBuilder.Append("复制完成:成功 " + num + " / " + items.Count + "(源文件已保留,同名文件不重复复制)");
|
||
if (num2 > 0)
|
||
{
|
||
stringBuilder.Append(",失败 " + num2);
|
||
}
|
||
stringBuilder.Append("\r\n");
|
||
stringBuilder.Append("快捷方式安装成功 " + num3 + " 个");
|
||
if (num4 > 0)
|
||
{
|
||
stringBuilder.Append("\r\n已存在、未重复安装 " + num4 + " 个");
|
||
if (list3.Count <= 20)
|
||
{
|
||
stringBuilder.Append(":");
|
||
foreach (string item in list3)
|
||
{
|
||
stringBuilder.Append("\r\n " + item);
|
||
}
|
||
}
|
||
}
|
||
if (num3 > 0)
|
||
{
|
||
stringBuilder.Append("\r\n\r\n已写入:");
|
||
foreach (string item2 in list2)
|
||
{
|
||
stringBuilder.Append("\r\n " + item2);
|
||
}
|
||
stringBuilder.Append("\r\n\r\n说明:快捷方式(.lnk)存放在 C:\\Windows\\Fonts,并在注册表 HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts 登记。");
|
||
stringBuilder.Append("\r\n若在『字体设置 / 控制面板-字体』或 Word、PS 等软件中未立即出现,请注销后重新登录或重启系统再查看。");
|
||
}
|
||
if (num2 > 0 && list.Count <= 20)
|
||
{
|
||
stringBuilder.Append("\r\n\r\n失败项:");
|
||
foreach (string item3 in list)
|
||
{
|
||
stringBuilder.Append("\r\n " + item3);
|
||
}
|
||
}
|
||
MessageBox.Show((IWin32Window)(object)this, stringBuilder.ToString(), "复制结果", (MessageBoxButtons)0, (MessageBoxIcon)64);
|
||
return num > 0;
|
||
}
|
||
|
||
private static void MoveFileSafe(string src, string dest)
|
||
{
|
||
File.Copy(src, dest, overwrite: false);
|
||
}
|
||
|
||
public void SetProgress(int pct, int done, int total)
|
||
{
|
||
prog.Value = Math.Min(100, Math.Max(0, pct));
|
||
((Control)lblProg).Text = "正在渲染 " + done + " / " + total + " ...";
|
||
}
|
||
}
|