命名优化,达芬奇字体修改工具
This commit is contained in:
595
DrfxFontFixer/MainWindow.xaml.cs
Normal file
595
DrfxFontFixer/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,595 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using Microsoft.Win32;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DrfxFontFixer
|
||||
{
|
||||
public class FullMapping : INotifyPropertyChanged
|
||||
{
|
||||
private static Dictionary<string, FontFamily> _systemFontDict;
|
||||
|
||||
public static void Initialize(Dictionary<string, FontFamily> fontDict)
|
||||
{
|
||||
_systemFontDict = fontDict;
|
||||
}
|
||||
|
||||
public string OriginalFont { get; init; }
|
||||
public string OriginalStyle { get; init; }
|
||||
private string newFont;
|
||||
|
||||
public string NewFont
|
||||
{
|
||||
get => newFont;
|
||||
set
|
||||
{
|
||||
if (newFont != value)
|
||||
{
|
||||
newFont = value;
|
||||
OnPropertyChanged(nameof(NewFont));
|
||||
UpdateAvailableStyles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string newStyle;
|
||||
|
||||
public string NewStyle
|
||||
{
|
||||
get => newStyle;
|
||||
set
|
||||
{
|
||||
newStyle = value;
|
||||
OnPropertyChanged(nameof(NewStyle));
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<string> AvailableNewStyles { get; } = [];
|
||||
public bool IsNewFontInSystem { get; private set; }
|
||||
[JsonIgnore] private string usageInfo;
|
||||
|
||||
[JsonIgnore]
|
||||
public string UsageInfo
|
||||
{
|
||||
get => usageInfo;
|
||||
set
|
||||
{
|
||||
usageInfo = value;
|
||||
OnPropertyChanged(nameof(UsageInfo));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAvailableStyles()
|
||||
{
|
||||
IsNewFontInSystem = _systemFontDict.TryGetValue(NewFont, out var fontFamily);
|
||||
Application.Current.Dispatcher.Invoke(() => AvailableNewStyles.Clear());
|
||||
if (IsNewFontInSystem)
|
||||
{
|
||||
var styles = new List<string>();
|
||||
foreach (var typeface in fontFamily.GetTypefaces())
|
||||
{
|
||||
styles.Add(typeface.FaceNames[System.Windows.Markup.XmlLanguage.GetLanguage("en-us")]);
|
||||
}
|
||||
|
||||
styles.Distinct().OrderBy(s => s).ToList().ForEach(s => Application.Current.Dispatcher.Invoke(() => AvailableNewStyles.Add(s)));
|
||||
if (!AvailableNewStyles.Contains(NewStyle))
|
||||
{
|
||||
NewStyle = AvailableNewStyles.Contains("Regular") ? "Regular" : AvailableNewStyles.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(IsNewFontInSystem));
|
||||
OnPropertyChanged(nameof(AvailableNewStyles));
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
protected void OnPropertyChanged(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||
}
|
||||
|
||||
public partial class MainWindow
|
||||
{
|
||||
public ObservableCollection<FullMapping> FullMappings { get; set; } = new ObservableCollection<FullMapping>();
|
||||
public List<string> SystemFonts { get; set; } = new List<string>();
|
||||
private readonly string mappingFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "mapping.json");
|
||||
private bool isProcessingComplete = false;
|
||||
private string lastOutputDirectory = "";
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.DataContext = this;
|
||||
LoadSystemFonts();
|
||||
OutputPath.Text = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"Blackmagic Design",
|
||||
"DaVinci Resolve",
|
||||
"Support",
|
||||
"Fusion",
|
||||
"Templates"
|
||||
);
|
||||
LoadMapping(false);
|
||||
MappingDataGrid.ItemsSource = FullMappings;
|
||||
}
|
||||
|
||||
#region Initialization, Persistence and Font Management
|
||||
|
||||
private void LoadSystemFonts()
|
||||
{
|
||||
var fontDict = new Dictionary<string, FontFamily>();
|
||||
foreach (var fontFamily in Fonts.SystemFontFamilies.OrderBy(f => f.Source))
|
||||
{
|
||||
if (!fontDict.ContainsKey(fontFamily.Source)) fontDict.Add(fontFamily.Source, fontFamily);
|
||||
}
|
||||
|
||||
SystemFonts = fontDict.Keys.ToList();
|
||||
FullMapping.Initialize(fontDict);
|
||||
}
|
||||
|
||||
private void SaveMapping()
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = JsonConvert.SerializeObject(FullMappings, Formatting.Indented);
|
||||
File.WriteAllText(mappingFilePath, json);
|
||||
Log("映射表已成功保存。", Brushes.Blue);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"保存映射表失败: {ex.Message}", Brushes.Red);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadMapping(bool userInitiated = true)
|
||||
{
|
||||
if (!File.Exists(mappingFilePath))
|
||||
{
|
||||
if (userInitiated) MessageBox.Show("未找到 mapping.json 文件。", "提示");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(mappingFilePath);
|
||||
var loaded = JsonConvert.DeserializeObject<ObservableCollection<FullMapping>>(json);
|
||||
if (loaded != null)
|
||||
{
|
||||
FullMappings = loaded;
|
||||
MappingDataGrid.ItemsSource = null;
|
||||
MappingDataGrid.ItemsSource = FullMappings;
|
||||
Log("已成功加载本地映射表。", Brushes.Blue);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"加载映射表失败: {ex.Message}", Brushes.Red);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI Event Handlers
|
||||
|
||||
private void NewFontComboBox_LostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var comboBox = sender as ComboBox;
|
||||
var mapping = comboBox?.DataContext as FullMapping;
|
||||
if (mapping != null && mapping.NewFont != comboBox.Text)
|
||||
{
|
||||
mapping.NewFont = comboBox.Text;
|
||||
}
|
||||
}
|
||||
|
||||
private void NewStyleComboBox_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var comboBox = sender as ComboBox;
|
||||
var mapping = comboBox?.DataContext as FullMapping;
|
||||
if (mapping != null)
|
||||
{
|
||||
comboBox.ItemsSource = mapping.AvailableNewStyles;
|
||||
}
|
||||
}
|
||||
|
||||
private async void StartButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FileListBox.Items.Count == 0)
|
||||
{
|
||||
MessageBox.Show("请先添加 .drfx 文件。");
|
||||
return;
|
||||
}
|
||||
|
||||
if (FullMappings.Count == 0)
|
||||
{
|
||||
MessageBox.Show("映射表为空。");
|
||||
return;
|
||||
}
|
||||
|
||||
var files = FileListBox.Items.Cast<string>().ToList();
|
||||
SetUiState(false);
|
||||
LogTextBlock.Text = "";
|
||||
MainProgressBar.Value = 0;
|
||||
isProcessingComplete = false;
|
||||
try
|
||||
{
|
||||
var progress = new Progress<ProgressReport>(r =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(r.Message)) Log(r.Message, r.Color);
|
||||
MainProgressBar.Value = r.Percentage;
|
||||
});
|
||||
var outputPath = OutputPath.Text;
|
||||
await Task.Run(() => ProcessFiles_Mapping(files, outputPath, FullMappings.ToList(), progress));
|
||||
Log("====== 所有任务已完成! ======", Brushes.Green);
|
||||
isProcessingComplete = true;
|
||||
var result = MessageBox.Show("处理完成!是否打开输出目录", "完成", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
if (result== MessageBoxResult.Yes)
|
||||
{
|
||||
Process.Start("explorer.exe", outputPath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"严重错误: {ex.Message}", Brushes.Red);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetUiState(true);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ScanFilesButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FileListBox.Items.Count == 0)
|
||||
{
|
||||
MessageBox.Show("请先添加要扫描的 .drfx 文件。");
|
||||
return;
|
||||
}
|
||||
|
||||
SetUiState(false);
|
||||
Log("开始扫描文件...");
|
||||
|
||||
var usageDict = new Dictionary<Tuple<string, string>, List<string>>();
|
||||
try
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
foreach (var drfxFile in FileListBox.Items.Cast<string>())
|
||||
{
|
||||
using (var archive = ZipFile.OpenRead(drfxFile))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(en => en.Name.EndsWith(".setting", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
using (var entryStream = entry.Open())
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
entryStream.CopyTo(memoryStream);
|
||||
byte[] contentBytes = memoryStream.ToArray();
|
||||
using (var readableStream = new MemoryStream(contentBytes))
|
||||
{
|
||||
var encoding = GetFileEncoding(readableStream);
|
||||
string content = encoding.GetString(contentBytes);
|
||||
var foundPairs = ExtractFontAndStylePairs(content);
|
||||
foreach (var pair in foundPairs)
|
||||
{
|
||||
if (!usageDict.ContainsKey(pair))
|
||||
{
|
||||
usageDict[pair] = new List<string>();
|
||||
}
|
||||
|
||||
usageDict[pair].Add(entry.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
int newItems = 0;
|
||||
var existingMappings = FullMappings.ToDictionary(m => (m.OriginalFont, m.OriginalStyle));
|
||||
|
||||
foreach (var entry in usageDict.OrderBy(p => p.Key.Item1).ThenBy(p => p.Key.Item2))
|
||||
{
|
||||
var pair = (entry.Key.Item1, entry.Key.Item2);
|
||||
string usageInfo = $"使用文件:\n{string.Join("\n", entry.Value.Distinct())}";
|
||||
if (existingMappings.TryGetValue(pair, out var existingMapping))
|
||||
{
|
||||
existingMapping.UsageInfo = usageInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
FullMappings.Add(new FullMapping
|
||||
{
|
||||
OriginalFont = pair.Item1, OriginalStyle = pair.Item2, NewFont = pair.Item1, NewStyle = pair.Item2, UsageInfo = usageInfo
|
||||
});
|
||||
newItems++;
|
||||
}
|
||||
}
|
||||
|
||||
Log($"扫描完成,新增 {newItems} 个组合,并已更新所有文件引用信息。", Brushes.Blue);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"扫描失败: {ex.Message}", Brushes.Red);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetUiState(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveMapButton_Click(object sender, RoutedEventArgs e) => SaveMapping();
|
||||
|
||||
private void LoadMapButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (MessageBox.Show("加载将覆盖当前更改,确定吗?", "确认", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
|
||||
{
|
||||
LoadMapping();
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearMapButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (MessageBox.Show("确定要清空映射表吗?", "确认", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
|
||||
{
|
||||
FullMappings.Clear();
|
||||
Log("映射表已清空。");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Core Processing Logic
|
||||
|
||||
private void ProcessFiles_Mapping(List<string> files, string outputDir, List<FullMapping> mappings, IProgress<ProgressReport> progress)
|
||||
{
|
||||
int filesCompleted = 0;
|
||||
var mappingDict = mappings.ToDictionary(m => (m.OriginalFont, m.OriginalStyle));
|
||||
|
||||
foreach (var drfxFile in files)
|
||||
{
|
||||
int totalReplacementsInFile = 0;
|
||||
string tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
|
||||
try
|
||||
{
|
||||
progress.Report(new ProgressReport { Message = $"---处理: {Path.GetFileName(drfxFile)} ---" });
|
||||
ZipFile.ExtractToDirectory(drfxFile, tempDir);
|
||||
|
||||
var settingFiles = Directory.GetFiles(tempDir, "*.setting", SearchOption.AllDirectories);
|
||||
foreach (var settingFile in settingFiles)
|
||||
{
|
||||
var (modifiedContent, replacementsCount) = ProcessSingleFile(settingFile, mappingDict, progress);
|
||||
if (replacementsCount > 0)
|
||||
{
|
||||
Encoding encoding;
|
||||
using (var stream = new FileStream(settingFile, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
encoding = GetFileEncoding(stream);
|
||||
}
|
||||
|
||||
File.WriteAllText(settingFile, modifiedContent, encoding);
|
||||
totalReplacementsInFile += replacementsCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Directory.Exists(outputDir))
|
||||
{
|
||||
Directory.CreateDirectory(outputDir);
|
||||
}
|
||||
|
||||
lastOutputDirectory = outputDir;
|
||||
string finalDrfxPath = Path.Combine(outputDir, Path.GetFileName(drfxFile));
|
||||
if (File.Exists(finalDrfxPath)) File.Delete(finalDrfxPath);
|
||||
ZipFile.CreateFromDirectory(tempDir, finalDrfxPath, CompressionLevel.Optimal, false);
|
||||
|
||||
progress.Report(totalReplacementsInFile > 0
|
||||
? new ProgressReport { Message = $" - 总结: 共应用 {totalReplacementsInFile} 条替换规则。", Color = Brushes.Purple }
|
||||
: new ProgressReport { Message = $" - 总结: 无需任何替换。", Color = Brushes.Gray });
|
||||
progress.Report(new ProgressReport { Message = $" -> 成功! 已保存到 '{outputDir}' 文件夹。", Color = Brushes.Blue });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
progress.Report(new ProgressReport { Message = $" -> 失败: {ex.Message}", Color = Brushes.Red });
|
||||
}
|
||||
finally
|
||||
{
|
||||
filesCompleted++;
|
||||
progress.Report(new ProgressReport { Percentage = (int)(100.0 * filesCompleted / files.Count) });
|
||||
if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private (string ModifiedContent, int ReplacementsCount) ProcessSingleFile(string filePath,
|
||||
Dictionary<(string, string), FullMapping> mappingDict, IProgress<ProgressReport> progress)
|
||||
{
|
||||
Encoding encoding;
|
||||
// if (filePath.Contains("Title 03"))
|
||||
// {
|
||||
// }
|
||||
|
||||
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
encoding = GetFileEncoding(stream);
|
||||
}
|
||||
|
||||
string originalContent = File.ReadAllText(filePath, encoding);
|
||||
|
||||
int replacementsCount = 0;
|
||||
string toolBlockPattern =
|
||||
@"\w+\s*=\s*(?:TextPlus)\s*(\{((?>[^{}]+|\{(?<open>)|\}(?<-open>))*(?(open)(?!)))\})";
|
||||
|
||||
string modifiedContent = Regex.Replace(originalContent, toolBlockPattern, (match) =>
|
||||
{
|
||||
string toolBlockContent = match.Value;
|
||||
string font = ExtractValue(toolBlockContent, "Font");
|
||||
string style = ExtractValue(toolBlockContent, "Style");
|
||||
|
||||
if (font != null && style != null && mappingDict.TryGetValue((font, style), out var rule))
|
||||
{
|
||||
string newBlock = toolBlockContent;
|
||||
if (rule.NewFont != font)
|
||||
{
|
||||
newBlock = Regex.Replace(newBlock, GetPattern("Font"), $"$1{rule.NewFont}$2");
|
||||
progress.Report(new ProgressReport
|
||||
{ Message = $" - 字体映射: '{font}' -> '{rule.NewFont}' (文件: {Path.GetFileName(filePath)})", Color = Brushes.DarkGreen });
|
||||
replacementsCount++;
|
||||
}
|
||||
|
||||
if (rule.NewStyle != style)
|
||||
{
|
||||
newBlock = Regex.Replace(newBlock, GetPattern("Style"), $"$1{rule.NewStyle}$2");
|
||||
progress.Report(new ProgressReport
|
||||
{ Message = $" - 样式映射: '{style}' -> '{rule.NewStyle}' (文件: {Path.GetFileName(filePath)})", Color = Brushes.DarkCyan });
|
||||
replacementsCount++;
|
||||
}
|
||||
|
||||
return newBlock;
|
||||
}
|
||||
|
||||
return toolBlockContent;
|
||||
});
|
||||
|
||||
return (modifiedContent, replacementsCount);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
// --- 核心BUG终极修复: 使用两个捕获组,确保替换的完整性 ---
|
||||
private string GetPattern(string fieldName) => $@"({GetExtractionPattern(fieldName, true)})[^""]*({GetTrailingPattern()})";
|
||||
|
||||
// 这个辅助方法只用于 GetPattern
|
||||
private string GetTrailingPattern() => @"""(,?)\s*\S*\s*\}";
|
||||
|
||||
// 这个辅助方法只用于 GetPattern
|
||||
private string GetExtractionPattern(string fieldName, bool forCapture)
|
||||
{
|
||||
string pattern = $@"\b{fieldName}\s*=\s*Input\s*\{{[^{{}}]*?Value\s*=\s*""";
|
||||
return forCapture ? pattern : pattern + @"(?<value>[^""]*)""";
|
||||
}
|
||||
|
||||
private string ExtractValue(string content, string fieldName)
|
||||
{
|
||||
var match = Regex.Match(content, GetExtractionPattern(fieldName, false));
|
||||
return match.Success ? match.Groups["value"].Value : null;
|
||||
}
|
||||
|
||||
private List<Tuple<string, string>> ExtractFontAndStylePairs(string content)
|
||||
{
|
||||
var pairs = new List<Tuple<string, string>>();
|
||||
string toolBlockPattern =
|
||||
@"\w+\s*=\s*(?:TextPlus)\s*(\{((?>[^{}]+|\{(?<open>)|\}(?<-open>))*(?(open)(?!)))\})";
|
||||
var matches = Regex.Matches(content, toolBlockPattern);
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
string font = ExtractValue(match.Value, "Font");
|
||||
string style = ExtractValue(match.Value, "Style");
|
||||
if (font != null && style != null)
|
||||
{
|
||||
pairs.Add(new Tuple<string, string>(font, style));
|
||||
}
|
||||
}
|
||||
|
||||
return pairs;
|
||||
}
|
||||
|
||||
private Encoding GetFileEncoding(Stream stream)
|
||||
{
|
||||
var bom = new byte[4];
|
||||
stream.Read(bom, 0, 4);
|
||||
stream.Position = 0;
|
||||
if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf) return Encoding.UTF8;
|
||||
if (bom[0] == 0xff && bom[1] == 0xfe) return Encoding.Unicode;
|
||||
if (bom[0] == 0xfe && bom[1] == 0xff) return Encoding.BigEndianUnicode;
|
||||
return new UTF8Encoding(false);
|
||||
}
|
||||
|
||||
private void SetUiState(bool isEnabled)
|
||||
{
|
||||
StartButton.IsEnabled = isEnabled;
|
||||
AddFilesButton.IsEnabled = isEnabled;
|
||||
ClearListButton.IsEnabled = isEnabled;
|
||||
ScanFilesButton.IsEnabled = isEnabled;
|
||||
SaveMapButton.IsEnabled = isEnabled;
|
||||
ClearMapButton.IsEnabled = isEnabled;
|
||||
LoadMapButton.IsEnabled = isEnabled;
|
||||
MappingDataGrid.IsEnabled = isEnabled;
|
||||
OpenOutputButton.IsEnabled = isProcessingComplete || isEnabled;
|
||||
}
|
||||
|
||||
private void Log(string message, Brush color = null)
|
||||
{
|
||||
var run = new Run(DateTime.Now.ToString("HH:mm:ss") + " - " + message + Environment.NewLine) { Foreground = color ?? Brushes.Black };
|
||||
LogTextBlock.Inlines.Add(run);
|
||||
LogScrollViewer.ScrollToEnd();
|
||||
}
|
||||
|
||||
private void AddFilesButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog { Filter = "DRFX Files (*.drfx)|*.drfx", Multiselect = true, Title = "选择 DRFX 文件" };
|
||||
if (ofd.ShowDialog() == true)
|
||||
foreach (string f in ofd.FileNames)
|
||||
if (!FileListBox.Items.Contains(f))
|
||||
FileListBox.Items.Add(f);
|
||||
}
|
||||
|
||||
private void ClearListButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
FileListBox.Items.Clear();
|
||||
Log("文件列表已清空。");
|
||||
}
|
||||
|
||||
private void OpenOutputButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(lastOutputDirectory) || !Directory.Exists(lastOutputDirectory))
|
||||
{
|
||||
MessageBox.Show("输出目录不存在。请先处理至少一个文件。", "提示");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Process.Start("explorer.exe", lastOutputDirectory);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("无法打开目录: " + ex.Message, "错误");
|
||||
}
|
||||
}
|
||||
|
||||
public struct ProgressReport
|
||||
{
|
||||
public int Percentage { get; set; }
|
||||
public string Message { get; set; }
|
||||
public Brush Color { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void BrowserOutputPathButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dlg = new OpenFolderDialog()
|
||||
{
|
||||
Title = "选择输出目录",
|
||||
};
|
||||
if (dlg.ShowDialog()== true)
|
||||
{
|
||||
OutputPath.Text = dlg.FolderName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user