add:自定义文件名

This commit is contained in:
2026-05-01 14:51:56 +08:00
parent 448a695503
commit f15a293a69
9 changed files with 230 additions and 8 deletions
+1 -1
View File
@@ -44,7 +44,7 @@
<Setter TargetName="Bd" Property="Background" Value="#1affffff"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Bd" Property="BorderBrush" Value="#22c55e"/>
<Setter TargetName="Bd" Property="BorderBrush" Value="#66CCFF"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
+68
View File
@@ -0,0 +1,68 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
namespace Ink_Canvas.Helpers
{
/// <summary>
/// 渲染保存文件名模板。支持占位符: {date} {time} {datetime} {mode} {page} {count} {type}。
/// 当模板为空、渲染结果非法或仅含分隔符时,回退到默认时间戳命名。
/// </summary>
public static class SaveFileNameHelper
{
private const string DefaultDateTime = "yyyy-MM-dd HH-mm-ss-fff";
public static string Render(string template, SaveFileNameContext ctx)
{
if (ctx == null) ctx = new SaveFileNameContext();
var now = ctx.Time ?? DateTime.Now;
if (string.IsNullOrWhiteSpace(template))
return now.ToString(DefaultDateTime);
try
{
string result = template
.Replace("{date}", now.ToString("yyyy-MM-dd"))
.Replace("{time}", now.ToString("HH-mm-ss"))
.Replace("{datetime}", now.ToString(DefaultDateTime))
.Replace("{mode}", ctx.Mode ?? "")
.Replace("{page}", ctx.Page?.ToString() ?? "")
.Replace("{count}", ctx.Count?.ToString() ?? "")
.Replace("{type}", ctx.Type ?? "");
result = SanitizeFileName(result);
if (string.IsNullOrWhiteSpace(result) || Regex.IsMatch(result, @"^[\s\-_]+$"))
return now.ToString(DefaultDateTime);
return result;
}
catch
{
return now.ToString(DefaultDateTime);
}
}
private static string SanitizeFileName(string name)
{
if (string.IsNullOrEmpty(name)) return name;
foreach (var c in Path.GetInvalidFileNameChars())
{
name = name.Replace(c, '_');
}
return name.Trim();
}
}
public class SaveFileNameContext
{
public DateTime? Time { get; set; }
/// <summary>"Annotation" or "BlackBoard" or "Screenshot" etc.</summary>
public string Mode { get; set; }
/// <summary>"User" or "Auto"</summary>
public string Type { get; set; }
public int? Page { get; set; }
public int? Count { get; set; }
}
}
@@ -132,7 +132,19 @@ namespace Ink_Canvas
+ (currentMode == 0 ? "Annotation Strokes" : "BlackBoard Strokes");
if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath);
string savePathWithName;
if (currentMode != 0) // 黑板模式下
if (Settings.Automation.IsUseCustomSaveFileName)
{
var ctx = new SaveFileNameContext
{
Mode = currentMode == 0 ? "Annotation" : "BlackBoard",
Type = saveByUser ? "User" : "Auto",
Page = currentMode != 0 ? CurrentWhiteboardIndex : (int?)null,
Count = inkCanvas.Strokes.Count
};
var fname = SaveFileNameHelper.Render(Settings.Automation.CustomSaveFileNameTemplate, ctx);
savePathWithName = savePath + @"\" + fname + ".icstk";
}
else if (currentMode != 0) // 黑板模式下
savePathWithName = savePath + @"\" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-fff") + " Page-" +
CurrentWhiteboardIndex + " StrokesCount-" + inkCanvas.Strokes.Count + ".icstk";
else
+34 -6
View File
@@ -43,8 +43,23 @@ namespace Ink_Canvas
var basePath = Settings.Automation.AutoSavedStrokesLocation
+ @"\Auto Saved - BlackBoard Strokes";
if (!Directory.Exists(basePath)) Directory.CreateDirectory(basePath);
strokeSavePath = Path.Combine(basePath,
$"{DateTime.Now:yyyy-MM-dd HH-mm-ss-fff} Page-{pageIndexForStrokes} StrokesCount-{strokesToSave.Count}.icstk");
string stem;
if (Settings.Automation.IsUseCustomSaveFileName)
{
stem = SaveFileNameHelper.Render(Settings.Automation.CustomSaveFileNameTemplate,
new SaveFileNameContext
{
Mode = "BlackBoard",
Type = "Auto",
Page = pageIndexForStrokes,
Count = strokesToSave.Count
});
}
else
{
stem = $"{DateTime.Now:yyyy-MM-dd HH-mm-ss-fff} Page-{pageIndexForStrokes} StrokesCount-{strokesToSave.Count}";
}
strokeSavePath = Path.Combine(basePath, stem + ".icstk");
}
}
catch (Exception ex)
@@ -149,7 +164,7 @@ namespace Ink_Canvas
{
var desktopPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
$"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png");
$"{GetScreenshotFileNameStem()}.png");
CaptureAndSaveScreenshot(desktopPath, false);
@@ -188,7 +203,7 @@ namespace Ink_Canvas
var desktopPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
$"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png");
$"{GetScreenshotFileNameStem()}.png");
using (var originalBitmap = CaptureScreenArea(screenshotResult.Value.Area))
{
@@ -437,7 +452,10 @@ namespace Ink_Canvas
{
if (string.IsNullOrWhiteSpace(fileName))
{
fileName = DateTime.Now.ToString("HH-mm-ss");
fileName = Settings.Automation.IsUseCustomSaveFileName
? SaveFileNameHelper.Render(Settings.Automation.CustomSaveFileNameTemplate,
new SaveFileNameContext { Mode = "Screenshot", Type = "Auto", Count = inkCanvas?.Strokes?.Count })
: DateTime.Now.ToString("HH-mm-ss");
}
var basePath = Settings.Automation.AutoSavedStrokesLocation;
@@ -473,7 +491,17 @@ namespace Ink_Canvas
return Path.Combine(
screenshotsFolder,
$"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png");
$"{GetScreenshotFileNameStem()}.png");
}
private string GetScreenshotFileNameStem()
{
if (Settings.Automation.IsUseCustomSaveFileName)
{
return SaveFileNameHelper.Render(Settings.Automation.CustomSaveFileNameTemplate,
new SaveFileNameContext { Mode = "Screenshot", Type = "Auto", Count = inkCanvas?.Strokes?.Count });
}
return DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
}
}
}
+6
View File
@@ -1458,6 +1458,12 @@
<data name="AutoKill_Title" xml:space="preserve">
<value>Auto kill</value>
</data>
<data name="AutoFold_Mode" xml:space="preserve">
<value>Fold mode</value>
</data>
<data name="AutoSave_Title" xml:space="preserve">
<value>Auto save</value>
</data>
<data name="AutoKill_PptTools" xml:space="preserve">
<value>Auto kill Seewo PPT tools</value>
</data>
+6
View File
@@ -1501,6 +1501,12 @@
<data name="AutoKill_Title" xml:space="preserve">
<value>自动查杀</value>
</data>
<data name="AutoFold_Mode" xml:space="preserve">
<value>收纳模式</value>
</data>
<data name="AutoSave_Title" xml:space="preserve">
<value>自动保存</value>
</data>
<data name="AutoKill_PptTools" xml:space="preserve">
<value>自动查杀希沃“PPT 小工具”</value>
</data>
+6
View File
@@ -581,6 +581,12 @@ namespace Ink_Canvas
[JsonProperty("isSaveFullPageStrokes")]
public bool IsSaveFullPageStrokes;
[JsonProperty("isUseCustomSaveFileName")]
public bool IsUseCustomSaveFileName { get; set; } = false;
[JsonProperty("customSaveFileNameTemplate")]
public string CustomSaveFileNameTemplate { get; set; } = "{datetime}";
[JsonProperty("isSaveStrokesAsXML")]
public bool IsSaveStrokesAsXML { get; set; } = false;
@@ -372,6 +372,39 @@
Icon="{x:Static ui:SegoeFluentIcons.Save}"
Toggled="ToggleSwitchSaveFullPageStrokes_Toggled"/>
<controls:LabeledSettingsCard x:Name="CardUseCustomSaveFileName"
Header="使用自定义保存文件名"
Description="开启后可选择保存文件的命名方式"
Icon="{x:Static ui:SegoeFluentIcons.Edit}"
Toggled="ToggleSwitchUseCustomSaveFileName_Toggled"/>
<ui:SettingsExpander x:Name="CardSaveFileNamePreset" Header="文件名格式">
<ui:SettingsExpander.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Edit}"/>
</ui:SettingsExpander.HeaderIcon>
<ComboBox x:Name="ComboBoxSaveFileNamePreset"
MinWidth="260"
SelectionChanged="ComboBoxSaveFileNamePreset_SelectionChanged">
<ComboBoxItem Content="时间戳(默认)" Tag="{}{datetime}"/>
<ComboBoxItem Content="日期" Tag="{}{date}"/>
<ComboBoxItem Content="日期 + 时间" Tag="{}{date}_{time}"/>
<ComboBoxItem Content="日期 + 模式" Tag="{}{date}_{mode}"/>
<ComboBoxItem Content="日期 + 模式 + 页码" Tag="{}{date}_{mode}_Page-{page}"/>
<ComboBoxItem Content="日期 + 模式 + 页码 + 笔画数" Tag="{}{date}_{mode}_Page-{page}_Strokes-{count}"/>
<ComboBoxItem Content="自定义..." Tag="__custom__"/>
</ComboBox>
<ui:SettingsExpander.Items>
<ui:SettingsCard x:Name="CardCustomSaveFileNameTemplate"
Header="自定义模板"
Description="可用占位符:{date} {time} {datetime} {mode} {page} {count} {type}"
Visibility="Collapsed">
<TextBox x:Name="TextBoxCustomSaveFileNameTemplate"
MinWidth="260"
LostFocus="TextBoxCustomSaveFileNameTemplate_LostFocus"/>
</ui:SettingsCard>
</ui:SettingsExpander.Items>
</ui:SettingsExpander>
<TextBlock Text="悬浮窗拦截" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"/>
<ui:SettingsExpander Header="希沃"
@@ -100,6 +100,10 @@ namespace Ink_Canvas.Windows.SettingsViews.Pages
SideControlMinimumAutomationSlider.Value = auto.MinimumAutomationStrokeNumber;
CardSaveFullPageStrokes.IsOn = auto.IsSaveFullPageStrokes;
CardUseCustomSaveFileName.IsOn = auto.IsUseCustomSaveFileName;
TextBoxCustomSaveFileNameTemplate.Text = auto.CustomSaveFileNameTemplate;
SyncSaveFileNamePresetSelection(auto.CustomSaveFileNameTemplate);
if (auto.FloatingWindowInterceptor.InterceptRules != null)
{
ToggleSwitchSeewoWhiteboard3Floating.IsOn = auto.FloatingWindowInterceptor.InterceptRules.ContainsKey("SeewoWhiteboard3Floating") && auto.FloatingWindowInterceptor.InterceptRules["SeewoWhiteboard3Floating"];
@@ -475,6 +479,65 @@ namespace Ink_Canvas.Windows.SettingsViews.Pages
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchUseCustomSaveFileName_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Automation.IsUseCustomSaveFileName = CardUseCustomSaveFileName.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void TextBoxCustomSaveFileNameTemplate_LostFocus(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Automation.CustomSaveFileNameTemplate = TextBoxCustomSaveFileNameTemplate.Text;
SettingsManager.SaveSettingsToFile();
}
private void ComboBoxSaveFileNamePreset_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!_isLoaded || ComboBoxSaveFileNamePreset.SelectedItem == null) return;
var item = ComboBoxSaveFileNamePreset.SelectedItem as ComboBoxItem;
var tag = item?.Tag?.ToString();
if (string.IsNullOrEmpty(tag)) return;
if (tag == "__custom__")
{
CardCustomSaveFileNameTemplate.Visibility = Visibility.Visible;
return;
}
CardCustomSaveFileNameTemplate.Visibility = Visibility.Collapsed;
SettingsManager.Settings.Automation.CustomSaveFileNameTemplate = tag;
TextBoxCustomSaveFileNameTemplate.Text = tag;
SettingsManager.SaveSettingsToFile();
}
private void SyncSaveFileNamePresetSelection(string template)
{
int matchedIndex = -1;
for (int i = 0; i < ComboBoxSaveFileNamePreset.Items.Count; i++)
{
var item = ComboBoxSaveFileNamePreset.Items[i] as ComboBoxItem;
var tag = item?.Tag?.ToString();
if (tag == template)
{
matchedIndex = i;
break;
}
}
if (matchedIndex >= 0)
{
ComboBoxSaveFileNamePreset.SelectedIndex = matchedIndex;
CardCustomSaveFileNameTemplate.Visibility = Visibility.Collapsed;
}
else
{
ComboBoxSaveFileNamePreset.SelectedIndex = ComboBoxSaveFileNamePreset.Items.Count - 1;
CardCustomSaveFileNameTemplate.Visibility = Visibility.Visible;
}
}
#endregion
#region Floating Window Interceptor