Loading src/WatermarkClock/MainWindow.xaml +9 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,14 @@ <MenuItem Header="文件(_F)"> <MenuItem Header="应用设置(_A)" Click="BtnApply_Click"/> <Separator/> <MenuItem Header="保存配置(_S)" Click="MenuSaveConfig_Click"/> <MenuItem Header="加载配置(_L)" Click="MenuLoadConfig_Click"/> <Separator/> <MenuItem Header="保存为默认配置(_D)" Click="MenuSaveDefault_Click"/> <MenuItem Header="加载默认配置(_R)" Click="MenuLoadDefault_Click"/> <Separator/> <MenuItem Header="还原默认值(_N)" Click="MenuResetDefaults_Click"/> <Separator/> <MenuItem Header="隐藏到托盘(_H)" Click="BtnHide_Click"/> <Separator/> <MenuItem Header="退出(_X)" Click="MenuExit_Click"/> Loading Loading @@ -112,6 +120,7 @@ <!-- 底部按钮 --> <StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Right" Margin="0,8,0,0"> <Button Content="还原默认值" Width="90" Margin="0,0,8,0" Click="BtnResetDefaults_Click"/> <Button Content="应用" Width="80" Margin="0,0,8,0" Click="BtnApply_Click"/> <Button Content="隐藏到托盘" Width="90" Click="BtnHide_Click"/> </StackPanel> Loading src/WatermarkClock/MainWindow.xaml.cs +134 −18 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ using System.Windows; using System.Windows.Media; using System.Windows.Threading; using WatermarkClock.Templates; using Microsoft.Win32; namespace WatermarkClock { Loading @@ -16,6 +17,7 @@ namespace WatermarkClock private int _currentTemplateIndex; private NotifyIconWrapper _notifyIcon; private Color _selectedColor = Color.FromRgb(255, 255, 255); private string _configPath; public MainWindow() { Loading @@ -23,9 +25,14 @@ namespace WatermarkClock _ctx = new Context(); InitComboBox(); LoadDefaults(); DgTemplates.ItemsSource = _ctx.Templates; // 从命令行参数或默认路径加载配置 _configPath = ConfigManager.GetConfigPathFromArgs(); var config = ConfigManager.LoadOrCreate(_configPath); ConfigManager.ApplyToContext(config, _ctx); LoadConfigToUi(config); DgTemplates.ItemsSource = _ctx.Templates; _notifyIcon = new NotifyIconWrapper(this); ApplySettings(); } Loading @@ -33,19 +40,56 @@ namespace WatermarkClock private void InitComboBox() { CbPosition.ItemsSource = Enum.GetValues(typeof(MarkPosition)); CbPosition.SelectedIndex = 1; CbFontFamily.ItemsSource = Fonts.SystemFontFamilies.OrderBy(f => f.Source); CbFontFamily.SelectedItem = _ctx.FontFamily; } private void LoadDefaults() /// <summary> /// 将 AppConfig 加载到 UI 控件 /// </summary> private void LoadConfigToUi(AppConfig config) { _ctx.Templates.Add(new TemplateItem("{DatetimeF}", 10)); // NumericUpDown 控件已有默认值,无需额外设置 CbPosition.SelectedItem = config.MarkPosition; NudPadding.Value = (uint)config.Padding; NudFontSize.Value = config.FontSize; // 设置字体 var fontFamily = new FontFamily(config.FontFamily); CbFontFamily.SelectedItem = fontFamily; if (CbFontFamily.SelectedItem == null) CbFontFamily.Text = config.FontFamily; // 设置颜色 try { var color = (Color)ColorConverter.ConvertFromString(config.TextColor); _selectedColor = color; BtnColor.Background = new SolidColorBrush(color); } catch { } NudRefreshInterval.Value = (uint)config.RefreshInterval; // 模板已在 ApplyToContext 中加载到 _ctx.Templates } private void ApplySettings() { SyncContextFromUi(); if (_watermarkWindow == null) { _watermarkWindow = new WatermarkClockWindow(_ctx); _watermarkWindow.Show(); } StartRefreshTimer(); StartRotationTimer(); } /// <summary> /// 从 UI 控件同步到 Context /// </summary> private void SyncContextFromUi() { if (CbPosition.SelectedItem is MarkPosition pos) _ctx.MarkPosition = pos; Loading @@ -61,15 +105,6 @@ namespace WatermarkClock _ctx.FontFamily = new FontFamily(CbFontFamily.Text); _ctx.RefreshInterval = (int)NudRefreshInterval.Value; if (_watermarkWindow == null) { _watermarkWindow = new WatermarkClockWindow(_ctx); _watermarkWindow.Show(); } StartRefreshTimer(); StartRotationTimer(); } private void StartRefreshTimer() Loading Loading @@ -251,6 +286,87 @@ namespace WatermarkClock dlg.ShowDialog(); } #region 配置菜单处理 private void MenuSaveConfig_Click(object sender, RoutedEventArgs e) { var dlg = new SaveFileDialog { Filter = "JSON 配置文件|*.json|所有文件|*.*", DefaultExt = ".json", FileName = "WatermarkClock", InitialDirectory = AppDomain.CurrentDomain.BaseDirectory }; if (dlg.ShowDialog() == true) { SyncContextFromUi(); var config = ConfigManager.FromContext(_ctx); ConfigManager.Save(dlg.FileName, config); _configPath = dlg.FileName; MessageBox.Show("配置已保存", "保存成功", MessageBoxButton.OK, MessageBoxImage.Information); } } private void MenuLoadConfig_Click(object sender, RoutedEventArgs e) { var dlg = new OpenFileDialog { Filter = "JSON 配置文件|*.json|所有文件|*.*", DefaultExt = ".json", InitialDirectory = AppDomain.CurrentDomain.BaseDirectory }; if (dlg.ShowDialog() == true) { var config = ConfigManager.LoadOrCreate(dlg.FileName); ConfigManager.ApplyToContext(config, _ctx); LoadConfigToUi(config); ApplySettings(); _configPath = dlg.FileName; } } private void MenuSaveDefault_Click(object sender, RoutedEventArgs e) { SyncContextFromUi(); var config = ConfigManager.FromContext(_ctx); var defaultPath = ConfigManager.GetDefaultConfigPath(); ConfigManager.Save(defaultPath, config); MessageBox.Show($"配置已保存到默认位置:\n{defaultPath}", "保存成功", MessageBoxButton.OK, MessageBoxImage.Information); } private void MenuLoadDefault_Click(object sender, RoutedEventArgs e) { var defaultPath = ConfigManager.GetDefaultConfigPath(); var config = ConfigManager.LoadOrCreate(defaultPath); ConfigManager.ApplyToContext(config, _ctx); LoadConfigToUi(config); ApplySettings(); _configPath = defaultPath; } private void MenuResetDefaults_Click(object sender, RoutedEventArgs e) { ResetToDefaults(); } private void BtnResetDefaults_Click(object sender, RoutedEventArgs e) { ResetToDefaults(); } private void ResetToDefaults() { var defaultConfig = ConfigManager.CreateDefault(); ConfigManager.ApplyToContext(defaultConfig, _ctx); LoadConfigToUi(defaultConfig); ApplySettings(); MessageBox.Show("已还原为默认值", "还原完成", MessageBoxButton.OK, MessageBoxImage.Information); } #endregion protected override void OnClosed(EventArgs e) { _refreshTimer?.Stop(); Loading src/WatermarkClock/WatermarkClock.csproj +5 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,9 @@ <Reference Include="ColorPickerWPF, Version=1.0.9.0, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\..\packages\ColorPickerWPF.1.0.9\lib\net461\ColorPickerWPF.dll</HintPath> </Reference> <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <HintPath>..\..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath> </Reference> <Reference Include="NumericUpDownLib, Version=3.4.0.0, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\..\packages\Dirkster.NumericUpDownLib.3.4.0\lib\net40\NumericUpDownLib.dll</HintPath> </Reference> Loading Loading @@ -82,6 +85,8 @@ <DependentUpon>App.xaml</DependentUpon> <SubType>Code</SubType> </Compile> <Compile Include="AppConfig.cs" /> <Compile Include="ConfigManager.cs" /> <Compile Include="MainWindow.xaml.cs"> <DependentUpon>MainWindow.xaml</DependentUpon> <SubType>Code</SubType> Loading src/WatermarkClock/packages.config +1 −0 Original line number Diff line number Diff line Loading @@ -2,5 +2,6 @@ <packages> <package id="ColorPickerWPF" version="1.0.9" targetFramework="net48" /> <package id="Dirkster.NumericUpDownLib" version="3.4.0" targetFramework="net48" /> <package id="Newtonsoft.Json" version="13.0.4" targetFramework="net48" /> <package id="WriteableBitmapEx" version="1.5.1.0" targetFramework="net48" /> </packages> No newline at end of file Loading
src/WatermarkClock/MainWindow.xaml +9 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,14 @@ <MenuItem Header="文件(_F)"> <MenuItem Header="应用设置(_A)" Click="BtnApply_Click"/> <Separator/> <MenuItem Header="保存配置(_S)" Click="MenuSaveConfig_Click"/> <MenuItem Header="加载配置(_L)" Click="MenuLoadConfig_Click"/> <Separator/> <MenuItem Header="保存为默认配置(_D)" Click="MenuSaveDefault_Click"/> <MenuItem Header="加载默认配置(_R)" Click="MenuLoadDefault_Click"/> <Separator/> <MenuItem Header="还原默认值(_N)" Click="MenuResetDefaults_Click"/> <Separator/> <MenuItem Header="隐藏到托盘(_H)" Click="BtnHide_Click"/> <Separator/> <MenuItem Header="退出(_X)" Click="MenuExit_Click"/> Loading Loading @@ -112,6 +120,7 @@ <!-- 底部按钮 --> <StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Right" Margin="0,8,0,0"> <Button Content="还原默认值" Width="90" Margin="0,0,8,0" Click="BtnResetDefaults_Click"/> <Button Content="应用" Width="80" Margin="0,0,8,0" Click="BtnApply_Click"/> <Button Content="隐藏到托盘" Width="90" Click="BtnHide_Click"/> </StackPanel> Loading
src/WatermarkClock/MainWindow.xaml.cs +134 −18 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ using System.Windows; using System.Windows.Media; using System.Windows.Threading; using WatermarkClock.Templates; using Microsoft.Win32; namespace WatermarkClock { Loading @@ -16,6 +17,7 @@ namespace WatermarkClock private int _currentTemplateIndex; private NotifyIconWrapper _notifyIcon; private Color _selectedColor = Color.FromRgb(255, 255, 255); private string _configPath; public MainWindow() { Loading @@ -23,9 +25,14 @@ namespace WatermarkClock _ctx = new Context(); InitComboBox(); LoadDefaults(); DgTemplates.ItemsSource = _ctx.Templates; // 从命令行参数或默认路径加载配置 _configPath = ConfigManager.GetConfigPathFromArgs(); var config = ConfigManager.LoadOrCreate(_configPath); ConfigManager.ApplyToContext(config, _ctx); LoadConfigToUi(config); DgTemplates.ItemsSource = _ctx.Templates; _notifyIcon = new NotifyIconWrapper(this); ApplySettings(); } Loading @@ -33,19 +40,56 @@ namespace WatermarkClock private void InitComboBox() { CbPosition.ItemsSource = Enum.GetValues(typeof(MarkPosition)); CbPosition.SelectedIndex = 1; CbFontFamily.ItemsSource = Fonts.SystemFontFamilies.OrderBy(f => f.Source); CbFontFamily.SelectedItem = _ctx.FontFamily; } private void LoadDefaults() /// <summary> /// 将 AppConfig 加载到 UI 控件 /// </summary> private void LoadConfigToUi(AppConfig config) { _ctx.Templates.Add(new TemplateItem("{DatetimeF}", 10)); // NumericUpDown 控件已有默认值,无需额外设置 CbPosition.SelectedItem = config.MarkPosition; NudPadding.Value = (uint)config.Padding; NudFontSize.Value = config.FontSize; // 设置字体 var fontFamily = new FontFamily(config.FontFamily); CbFontFamily.SelectedItem = fontFamily; if (CbFontFamily.SelectedItem == null) CbFontFamily.Text = config.FontFamily; // 设置颜色 try { var color = (Color)ColorConverter.ConvertFromString(config.TextColor); _selectedColor = color; BtnColor.Background = new SolidColorBrush(color); } catch { } NudRefreshInterval.Value = (uint)config.RefreshInterval; // 模板已在 ApplyToContext 中加载到 _ctx.Templates } private void ApplySettings() { SyncContextFromUi(); if (_watermarkWindow == null) { _watermarkWindow = new WatermarkClockWindow(_ctx); _watermarkWindow.Show(); } StartRefreshTimer(); StartRotationTimer(); } /// <summary> /// 从 UI 控件同步到 Context /// </summary> private void SyncContextFromUi() { if (CbPosition.SelectedItem is MarkPosition pos) _ctx.MarkPosition = pos; Loading @@ -61,15 +105,6 @@ namespace WatermarkClock _ctx.FontFamily = new FontFamily(CbFontFamily.Text); _ctx.RefreshInterval = (int)NudRefreshInterval.Value; if (_watermarkWindow == null) { _watermarkWindow = new WatermarkClockWindow(_ctx); _watermarkWindow.Show(); } StartRefreshTimer(); StartRotationTimer(); } private void StartRefreshTimer() Loading Loading @@ -251,6 +286,87 @@ namespace WatermarkClock dlg.ShowDialog(); } #region 配置菜单处理 private void MenuSaveConfig_Click(object sender, RoutedEventArgs e) { var dlg = new SaveFileDialog { Filter = "JSON 配置文件|*.json|所有文件|*.*", DefaultExt = ".json", FileName = "WatermarkClock", InitialDirectory = AppDomain.CurrentDomain.BaseDirectory }; if (dlg.ShowDialog() == true) { SyncContextFromUi(); var config = ConfigManager.FromContext(_ctx); ConfigManager.Save(dlg.FileName, config); _configPath = dlg.FileName; MessageBox.Show("配置已保存", "保存成功", MessageBoxButton.OK, MessageBoxImage.Information); } } private void MenuLoadConfig_Click(object sender, RoutedEventArgs e) { var dlg = new OpenFileDialog { Filter = "JSON 配置文件|*.json|所有文件|*.*", DefaultExt = ".json", InitialDirectory = AppDomain.CurrentDomain.BaseDirectory }; if (dlg.ShowDialog() == true) { var config = ConfigManager.LoadOrCreate(dlg.FileName); ConfigManager.ApplyToContext(config, _ctx); LoadConfigToUi(config); ApplySettings(); _configPath = dlg.FileName; } } private void MenuSaveDefault_Click(object sender, RoutedEventArgs e) { SyncContextFromUi(); var config = ConfigManager.FromContext(_ctx); var defaultPath = ConfigManager.GetDefaultConfigPath(); ConfigManager.Save(defaultPath, config); MessageBox.Show($"配置已保存到默认位置:\n{defaultPath}", "保存成功", MessageBoxButton.OK, MessageBoxImage.Information); } private void MenuLoadDefault_Click(object sender, RoutedEventArgs e) { var defaultPath = ConfigManager.GetDefaultConfigPath(); var config = ConfigManager.LoadOrCreate(defaultPath); ConfigManager.ApplyToContext(config, _ctx); LoadConfigToUi(config); ApplySettings(); _configPath = defaultPath; } private void MenuResetDefaults_Click(object sender, RoutedEventArgs e) { ResetToDefaults(); } private void BtnResetDefaults_Click(object sender, RoutedEventArgs e) { ResetToDefaults(); } private void ResetToDefaults() { var defaultConfig = ConfigManager.CreateDefault(); ConfigManager.ApplyToContext(defaultConfig, _ctx); LoadConfigToUi(defaultConfig); ApplySettings(); MessageBox.Show("已还原为默认值", "还原完成", MessageBoxButton.OK, MessageBoxImage.Information); } #endregion protected override void OnClosed(EventArgs e) { _refreshTimer?.Stop(); Loading
src/WatermarkClock/WatermarkClock.csproj +5 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,9 @@ <Reference Include="ColorPickerWPF, Version=1.0.9.0, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\..\packages\ColorPickerWPF.1.0.9\lib\net461\ColorPickerWPF.dll</HintPath> </Reference> <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <HintPath>..\..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath> </Reference> <Reference Include="NumericUpDownLib, Version=3.4.0.0, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\..\packages\Dirkster.NumericUpDownLib.3.4.0\lib\net40\NumericUpDownLib.dll</HintPath> </Reference> Loading Loading @@ -82,6 +85,8 @@ <DependentUpon>App.xaml</DependentUpon> <SubType>Code</SubType> </Compile> <Compile Include="AppConfig.cs" /> <Compile Include="ConfigManager.cs" /> <Compile Include="MainWindow.xaml.cs"> <DependentUpon>MainWindow.xaml</DependentUpon> <SubType>Code</SubType> Loading
src/WatermarkClock/packages.config +1 −0 Original line number Diff line number Diff line Loading @@ -2,5 +2,6 @@ <packages> <package id="ColorPickerWPF" version="1.0.9" targetFramework="net48" /> <package id="Dirkster.NumericUpDownLib" version="3.4.0" targetFramework="net48" /> <package id="Newtonsoft.Json" version="13.0.4" targetFramework="net48" /> <package id="WriteableBitmapEx" version="1.5.1.0" targetFramework="net48" /> </packages> No newline at end of file