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 nodeIndex = new Dictionary(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> categories = new Dictionary>(); private string rootDir = ""; private Worker worker; private string renderHash = ""; private Dictionary cache = new Dictionary(); private List allItems = new List(); private Dictionary pathIndex = new Dictionary(StringComparer.OrdinalIgnoreCase); private List compareList = new List(); private Dictionary> tags = new Dictionary>(StringComparer.OrdinalIgnoreCase); private bool isScanning; private FontItem curPreviewItem; private PictureBox curPreviewPic; private List> renderedPics = new List>(); 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 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(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 exts = new HashSet(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 lst; if (!categories.TryGetValue(key, out lst)) { lst = new List(); 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 cachedByPath = null; if (hasCache) { cachedByPath = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (FontItem it in cached.Items) { cachedByPath[it.Path] = it; } } Dictionary bgStamps = new Dictionary(StringComparer.OrdinalIgnoreCase); bool[] firstBatch = new bool[1] { true }; // 生产者-消费者:一个线程快速遍历目录把文件路径入队,N 个线程同时取文件解析,I/O 等待重叠 Queue q = new Queue(); object qlock = new object(); bool[] producerDone = new bool[1] { false }; object stampsLock = new object(); int progressTotal = 0; Action 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 localBatch = new List(); 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 flush = localBatch; localBatch = new List(); FlushBatch(flush, ref progressTotal, firstBatch); } } }; int nw = Math.Max(2, Environment.ProcessorCount); List workers = new List(); 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 WalkDisk(string dir, string rel, HashSet exts) { List result = new List(); 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 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 touched = new HashSet(StringComparer.Ordinal); foreach (FontItem fi in flush) { string key = string.IsNullOrEmpty(fi.Cat) ? "(未分类)" : fi.Cat; List lst; if (!categories.TryGetValue(key, out lst)) { lst = new List(); categories[key] = lst; } lst.Add(fi); allItems.Add(fi); pathIndex[fi.Path] = fi; touched.Add(key); } foreach (string key in touched) { List lst; if (categories.TryGetValue(key, out lst)) { InsertCatNode(key, lst.Count); } } ((Control)lblStat).Text = "正在扫描… 已 " + total + " 个字体"; })); } private void FillTreeFromCategories() { int num = 0; List list = new List(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 exts) { try { List list = null; string[] files = Directory.GetFiles(dir); foreach (string text in files) { if (exts.Contains(Path.GetExtension(text))) { if (list == null) { list = new List(); } 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 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 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 list = new List(); // 搜索框非空时跳过分类勾选检查 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 list2 = new List(); 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 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(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(); } if (!tags[key].Contains(item)) { tags[key].Add(item); } } } } catch { } } private void SaveTags() { try { List list = new List(); foreach (KeyValuePair> 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(); 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 list = new List(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 list = new List(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 CollectTargetItems() { List list = new List(); if (rootDir.Length == 0) { return list; } CollectChecked(catBox.Nodes, list); if (list.Count == 0) { foreach (KeyValuePair> 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 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 list = new List(); 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 list = CollectTargetItems(); if (list.Count == 0) { MessageBox.Show((IWin32Window)(object)this, "目录中没有字体文件", "提示"); } else { MoveInstallAll(list); } } private bool MoveInstallAll(List 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 list = new List(); List list2 = new List(); List list3 = new List(); List list4 = new List(); Cursor.Current = Cursors.WaitCursor; try { HashSet hashSet = new HashSet(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 + " ..."; } }