This commit is contained in:
PrefacedCorg
2025-09-22 09:34:45 +08:00
23 changed files with 1269 additions and 343 deletions
-1
View File
@@ -237,7 +237,6 @@
<ResourceDictionary Source="Resources/SeewoImageDictionary.xaml"/>
<ResourceDictionary Source="Resources/DrawShapeImageDictionary.xaml"/>
<ResourceDictionary Source="Resources/IconImageDictionary.xaml"/>
<ResourceDictionary Source="Resources/Styles/Light.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
+2 -2
View File
@@ -49,5 +49,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.7.11.1")]
[assembly: AssemblyFileVersion("1.7.11.1")]
[assembly: AssemblyVersion("1.7.11.3")]
[assembly: AssemblyFileVersion("1.7.11.3")]
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using Ink_Canvas.Helpers;
namespace Ink_Canvas
@@ -5,7 +5,6 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
namespace Ink_Canvas.Helpers
+157 -9
View File
@@ -1,7 +1,6 @@
using Microsoft.Office.Interop.PowerPoint;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
@@ -27,6 +26,11 @@ namespace Ink_Canvas.Helpers
private readonly object _lockObject = new object();
private bool _disposed;
private string _currentActivePresentationId = "";
// 墨迹备份机制
private readonly Dictionary<string, Dictionary<int, StrokeCollection>> _strokeBackups;
private DateTime _lastBackupTime = DateTime.MinValue;
private const int BackupIntervalMinutes = 2; // 每2分钟备份一次
#endregion
#region Constructor
@@ -34,6 +38,7 @@ namespace Ink_Canvas.Helpers
{
_presentationManagers = new Dictionary<string, PPTInkManager>();
_presentationInfos = new Dictionary<string, PresentationInfo>();
_strokeBackups = new Dictionary<string, Dictionary<int, StrokeCollection>>();
}
#endregion
@@ -113,8 +118,15 @@ namespace Ink_Canvas.Helpers
var currentPresentation = GetCurrentActivePresentation();
if (currentPresentation != null)
{
currentManager.SaveAllStrokesToFile(currentPresentation);
LogHelper.WriteLogToFile($"已保存当前演示文稿墨迹: {currentPresentation.Name}", LogHelper.LogType.Trace);
try
{
currentManager.SaveAllStrokesToFile(currentPresentation);
LogHelper.WriteLogToFile($"已保存当前演示文稿墨迹: {currentPresentation.Name}", LogHelper.LogType.Trace);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"保存当前演示文稿墨迹失败: {ex}", LogHelper.LogType.Error);
}
}
}
}
@@ -127,10 +139,10 @@ namespace Ink_Canvas.Helpers
_presentationInfos[presentationId].LastAccessTime = DateTime.Now;
}
if (_currentActivePresentationId != presentationId)
{
LogHelper.WriteLogToFile($"已切换到演示文稿: {presentation.Name}", LogHelper.LogType.Trace);
}
if (_currentActivePresentationId != presentationId)
{
LogHelper.WriteLogToFile($"已切换到演示文稿: {presentation.Name}", LogHelper.LogType.Trace);
}
return true;
}
else
@@ -162,7 +174,17 @@ namespace Ink_Canvas.Helpers
var manager = GetCurrentManager();
if (manager != null)
{
// 保存到管理器
manager.SaveCurrentSlideStrokes(slideIndex, strokes);
// 只有在保存成功后才创建备份
if (!string.IsNullOrEmpty(_currentActivePresentationId))
{
CreateStrokeBackup(_currentActivePresentationId, slideIndex, strokes);
}
// 检查是否需要执行定期备份
CheckAndPerformBackup();
}
}
catch (Exception ex)
@@ -210,12 +232,29 @@ namespace Ink_Canvas.Helpers
var manager = GetCurrentManager();
if (manager != null)
{
return manager.LoadSlideStrokes(slideIndex);
var strokes = manager.LoadSlideStrokes(slideIndex);
// 如果从管理器加载失败,尝试从备份恢复
if (strokes == null || strokes.Count == 0)
{
if (!string.IsNullOrEmpty(_currentActivePresentationId))
{
strokes = RestoreStrokeFromBackup(_currentActivePresentationId, slideIndex);
}
}
return strokes ?? new StrokeCollection();
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"加载页面墨迹失败: {ex}", LogHelper.LogType.Error);
// 尝试从备份恢复
if (!string.IsNullOrEmpty(_currentActivePresentationId))
{
return RestoreStrokeFromBackup(_currentActivePresentationId, slideIndex);
}
}
}
@@ -512,6 +551,12 @@ namespace Ink_Canvas.Helpers
}
_presentationInfos.Remove(id);
// 清理备份数据
if (_strokeBackups.ContainsKey(id))
{
_strokeBackups.Remove(id);
}
LogHelper.WriteLogToFile($"已清理非活跃演示文稿: {id}", LogHelper.LogType.Trace);
}
}
@@ -521,6 +566,97 @@ namespace Ink_Canvas.Helpers
}
}
}
/// <summary>
/// 创建墨迹备份
/// </summary>
private void CreateStrokeBackup(string presentationId, int slideIndex, StrokeCollection strokes)
{
try
{
if (strokes == null || strokes.Count == 0) return;
if (!_strokeBackups.ContainsKey(presentationId))
{
_strokeBackups[presentationId] = new Dictionary<int, StrokeCollection>();
}
// 释放旧的备份
if (_strokeBackups[presentationId].ContainsKey(slideIndex))
{
_strokeBackups[presentationId][slideIndex] = null;
}
// 创建新的备份
_strokeBackups[presentationId][slideIndex] = strokes.Clone();
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"创建墨迹备份失败: {ex}", LogHelper.LogType.Error);
}
}
/// <summary>
/// 从备份恢复墨迹
/// </summary>
private StrokeCollection RestoreStrokeFromBackup(string presentationId, int slideIndex)
{
try
{
if (_strokeBackups.ContainsKey(presentationId) &&
_strokeBackups[presentationId].ContainsKey(slideIndex))
{
var backup = _strokeBackups[presentationId][slideIndex];
if (backup != null)
{
LogHelper.WriteLogToFile($"从备份恢复第{slideIndex}页墨迹", LogHelper.LogType.Trace);
return backup.Clone();
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"从备份恢复墨迹失败: {ex}", LogHelper.LogType.Error);
}
return new StrokeCollection();
}
/// <summary>
/// 检查并执行定期备份
/// </summary>
private void CheckAndPerformBackup()
{
try
{
var now = DateTime.Now;
// 检查是否需要执行备份
if (now - _lastBackupTime < TimeSpan.FromMinutes(BackupIntervalMinutes))
{
return;
}
// 备份当前活跃演示文稿的所有墨迹
if (!string.IsNullOrEmpty(_currentActivePresentationId) &&
_presentationManagers.ContainsKey(_currentActivePresentationId))
{
var manager = _presentationManagers[_currentActivePresentationId];
if (manager != null)
{
// 这里可以添加更详细的备份逻辑
LogHelper.WriteLogToFile($"执行定期墨迹备份: {_currentActivePresentationId}", LogHelper.LogType.Trace);
}
}
_lastBackupTime = now;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"定期备份检查失败: {ex}", LogHelper.LogType.Error);
}
}
#endregion
#region Private Methods
@@ -562,7 +698,7 @@ namespace Ink_Canvas.Helpers
var presentationPath = presentation.FullName;
var fileHash = GetFileHash(presentationPath);
var processId = GetProcessId(presentation);
return $"{presentation.Name}_{fileHash}_{processId}";
return $"{presentation.Name}_{presentation.Slides.Count}_{fileHash}_{processId}";
}
catch (COMException comEx)
{
@@ -638,12 +774,24 @@ namespace Ink_Canvas.Helpers
{
lock (_lockObject)
{
// 释放所有管理器
foreach (var manager in _presentationManagers.Values)
{
manager?.Dispose();
}
_presentationManagers.Clear();
_presentationInfos.Clear();
// 清理备份数据
foreach (var backupDict in _strokeBackups.Values)
{
foreach (var backup in backupDict.Values)
{
backup?.Clear();
}
backupDict.Clear();
}
_strokeBackups.Clear();
}
_disposed = true;
}
+164 -12
View File
@@ -35,6 +35,12 @@ namespace Ink_Canvas.Helpers
private DateTime _lastSwitchTime = DateTime.MinValue;
private int _lastSwitchSlideIndex = -1;
private const int MinSwitchIntervalMs = 100; // 最小切换间隔100毫秒
// 内存管理相关字段
private long _totalMemoryUsage = 0;
private const long MaxMemoryUsageBytes = 100 * 1024 * 1024; // 100MB限制
private DateTime _lastMemoryCleanup = DateTime.MinValue;
private const int MemoryCleanupIntervalMinutes = 5; // 5分钟清理一次
#endregion
#region Constructor
@@ -118,24 +124,34 @@ namespace Ink_Canvas.Helpers
{
if (DateTime.Now < _inkLockUntil)
{
LogHelper.WriteLogToFile($"墨迹写入被锁定,当前页:{slideIndex},锁定页:{_lockedSlideIndex}", LogHelper.LogType.Warning);
}
return;
}
if (slideIndex < _memoryStreams.Length)
{
// 先释放旧的内存流,防止内存泄漏
try
{
_memoryStreams[slideIndex]?.Dispose();
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"释放旧内存流失败: {ex}", LogHelper.LogType.Warning);
}
// 创建新的内存流
var ms = new MemoryStream();
strokes.Save(ms);
ms.Position = 0;
// 释放旧的内存流
_memoryStreams[slideIndex]?.Dispose();
_memoryStreams[slideIndex] = ms;
if (ms.Length > 0)
{
}
// 检查内存使用情况
CheckAndPerformMemoryCleanup();
}
}
catch (Exception ex)
@@ -158,12 +174,20 @@ namespace Ink_Canvas.Helpers
{
if (slideIndex < _memoryStreams.Length)
{
// 先释放旧的内存流,防止内存泄漏
try
{
_memoryStreams[slideIndex]?.Dispose();
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"释放旧内存流失败: {ex}", LogHelper.LogType.Warning);
}
// 创建新的内存流
var ms = new MemoryStream();
strokes.Save(ms);
ms.Position = 0;
// 释放旧的内存流
_memoryStreams[slideIndex]?.Dispose();
_memoryStreams[slideIndex] = ms;
LogHelper.WriteLogToFile($"已强制保存第{slideIndex}页墨迹,大小: {ms.Length} bytes", LogHelper.LogType.Trace);
@@ -388,13 +412,30 @@ namespace Ink_Canvas.Helpers
{
try
{
for (int i = 0; i < _memoryStreams.Length; i++)
// 安全释放所有内存流
if (_memoryStreams != null)
{
_memoryStreams[i]?.Dispose();
_memoryStreams[i] = null;
for (int i = 0; i < _memoryStreams.Length; i++)
{
try
{
_memoryStreams[i]?.Dispose();
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"释放内存流{i}失败: {ex}", LogHelper.LogType.Warning);
}
finally
{
_memoryStreams[i] = null;
}
}
// 重新初始化数组
_memoryStreams = new MemoryStream[_maxSlides + 2];
}
CurrentStrokes.Clear();
CurrentStrokes?.Clear();
LogHelper.WriteLogToFile("已清除所有墨迹", LogHelper.LogType.Trace);
}
catch (Exception ex)
@@ -430,6 +471,13 @@ namespace Ink_Canvas.Helpers
return true;
}
// 如果当前页面不是锁定页面,但锁定时间很短(小于50ms),允许写入
// 这样可以确保旧页面的墨迹能够及时保存
if (DateTime.Now - (_inkLockUntil.AddMilliseconds(-InkLockMilliseconds)) < TimeSpan.FromMilliseconds(50))
{
return true;
}
// 只有在快速切换且页面不同时才锁定
return false;
}
@@ -447,6 +495,110 @@ namespace Ink_Canvas.Helpers
_lastSwitchSlideIndex = -1;
}
}
/// <summary>
/// 检查并执行内存清理
/// </summary>
private void CheckAndPerformMemoryCleanup()
{
try
{
var now = DateTime.Now;
// 检查是否需要执行内存清理
if (now - _lastMemoryCleanup < TimeSpan.FromMinutes(MemoryCleanupIntervalMinutes))
{
return;
}
// 计算当前内存使用量
long currentMemoryUsage = 0;
if (_memoryStreams != null)
{
for (int i = 0; i < _memoryStreams.Length; i++)
{
if (_memoryStreams[i] != null)
{
currentMemoryUsage += _memoryStreams[i].Length;
}
}
}
_totalMemoryUsage = currentMemoryUsage;
// 如果内存使用量超过限制,执行清理
if (currentMemoryUsage > MaxMemoryUsageBytes)
{
LogHelper.WriteLogToFile($"内存使用量超限 ({currentMemoryUsage / 1024 / 1024}MB),开始清理", LogHelper.LogType.Warning);
// 清理非当前页面的墨迹
CleanupInactiveSlideStrokes();
_lastMemoryCleanup = now;
LogHelper.WriteLogToFile($"内存清理完成,当前使用量: {_totalMemoryUsage / 1024 / 1024}MB", LogHelper.LogType.Trace);
}
else
{
_lastMemoryCleanup = now;
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"内存清理检查失败: {ex}", LogHelper.LogType.Error);
}
}
/// <summary>
/// 清理非活跃页面的墨迹
/// </summary>
private void CleanupInactiveSlideStrokes()
{
try
{
if (_memoryStreams == null) return;
int cleanedCount = 0;
long freedMemory = 0;
for (int i = 0; i < _memoryStreams.Length; i++)
{
// 保留当前锁定页面和最近访问的页面
if (i == _lockedSlideIndex || i == _lastSwitchSlideIndex)
{
continue;
}
if (_memoryStreams[i] != null)
{
long memorySize = _memoryStreams[i].Length;
try
{
_memoryStreams[i].Dispose();
freedMemory += memorySize;
cleanedCount++;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"清理页面{i}墨迹失败: {ex}", LogHelper.LogType.Warning);
}
finally
{
_memoryStreams[i] = null;
}
}
}
if (cleanedCount > 0)
{
LogHelper.WriteLogToFile($"已清理{cleanedCount}个页面的墨迹,释放内存: {freedMemory / 1024}KB", LogHelper.LogType.Trace);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"清理非活跃页面墨迹失败: {ex}", LogHelper.LogType.Error);
}
}
#endregion
#region Private Methods
@@ -456,7 +608,7 @@ namespace Ink_Canvas.Helpers
{
var presentationPath = presentation.FullName;
var fileHash = GetFileHash(presentationPath);
return $"{presentation.Name}_{fileHash}";
return $"{presentation.Name}_{presentation.Slides.Count}_{fileHash}";
}
catch (Exception ex)
{
+52 -51
View File
@@ -93,7 +93,6 @@ namespace Ink_Canvas.Helpers
// COM对象已失效,触发断开连接
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"验证PPT放映窗口失败: {comEx.Message} (HR: 0x{hr:X8})", LogHelper.LogType.Warning);
return false;
}
}
@@ -411,63 +410,30 @@ namespace Ink_Canvas.Helpers
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
LogHelper.WriteLogToFile($"取消PPT事件注册时COM异常: {comEx.Message} (HR: 0x{hr:X8})", LogHelper.LogType.Warning);
}
catch (InvalidCastException)
{
// COM对象类型转换失败,通常是因为对象已经被释放
LogHelper.WriteLogToFile("PPT COM对象已被释放,跳过事件注册取消", LogHelper.LogType.Trace);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"取消PPT事件注册时发生异常: {ex}", LogHelper.LogType.Warning);
}
}, DispatcherPriority.Normal, CancellationToken.None, TimeSpan.FromSeconds(1));
}
}
catch (Exception)
catch (Exception ex)
{
LogHelper.WriteLogToFile($"取消PPT事件注册失败: {ex}", LogHelper.LogType.Warning);
}
// 释放COM对象
try
{
if (Marshal.IsComObject(CurrentSlide))
{
Marshal.ReleaseComObject(CurrentSlide);
}
}
catch (Exception)
{
}
try
{
if (Marshal.IsComObject(CurrentSlides))
{
Marshal.ReleaseComObject(CurrentSlides);
}
}
catch (Exception)
{
}
try
{
if (Marshal.IsComObject(CurrentPresentation))
{
Marshal.ReleaseComObject(CurrentPresentation);
}
}
catch (Exception)
{
}
try
{
if (Marshal.IsComObject(PPTApplication))
{
Marshal.ReleaseComObject(PPTApplication);
}
}
catch (Exception)
{
}
// 安全释放COM对象
SafeReleaseComObject(CurrentSlide, "CurrentSlide");
SafeReleaseComObject(CurrentSlides, "CurrentSlides");
SafeReleaseComObject(CurrentPresentation, "CurrentPresentation");
SafeReleaseComObject(PPTApplication, "PPTApplication");
// 清理引用
PPTApplication = null;
@@ -491,6 +457,30 @@ namespace Ink_Canvas.Helpers
}
}
/// <summary>
/// 安全释放COM对象
/// </summary>
private void SafeReleaseComObject(object comObject, string objectName)
{
try
{
if (comObject != null && Marshal.IsComObject(comObject))
{
int refCount = Marshal.ReleaseComObject(comObject);
LogHelper.WriteLogToFile($"已释放COM对象 {objectName},引用计数: {refCount}", LogHelper.LogType.Trace);
}
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
LogHelper.WriteLogToFile($"释放COM对象 {objectName} 时COM异常: {comEx.Message} (HR: 0x{hr:X8})", LogHelper.LogType.Warning);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"释放COM对象 {objectName} 时发生异常: {ex}", LogHelper.LogType.Warning);
}
}
private void UpdateCurrentPresentationInfo()
{
try
@@ -859,10 +849,23 @@ namespace Ink_Canvas.Helpers
// 如果在放映模式,获取放映窗口的演示文稿
if (IsInSlideShow && PPTApplication.SlideShowWindows.Count > 0)
{
var slideShowWindow = PPTApplication.SlideShowWindows[1];
if (slideShowWindow?.View != null)
try
{
return (Presentation)slideShowWindow.View.Slide.Parent;
var slideShowWindow = PPTApplication.SlideShowWindows[1];
if (slideShowWindow?.View != null)
{
return (Presentation)slideShowWindow.View.Slide.Parent;
}
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x80048240) // Integer out of range
{
// 放映窗口已不存在,返回null
return null;
}
throw; // 重新抛出其他COM异常
}
}
@@ -935,12 +938,10 @@ namespace Ink_Canvas.Helpers
// COM对象已失效,触发断开连接
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"获取当前幻灯片编号失败: {comEx.Message}", LogHelper.LogType.Warning);
return 0;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"获取当前幻灯片编号失败: {ex}", LogHelper.LogType.Error);
return 0;
}
}
-2
View File
@@ -92,7 +92,6 @@ namespace Ink_Canvas.Helpers
// 页数无效时清空页码显示
_mainWindow.PPTBtnPageNow.Text = "?";
_mainWindow.PPTBtnPageTotal.Text = "/ ?";
LogHelper.WriteLogToFile($"PPT页数无效,清空页码显示: 当前页={currentSlide}, 总页数={totalSlides}", LogHelper.LogType.Warning);
}
UpdateNavigationPanelsVisibility();
@@ -132,7 +131,6 @@ namespace Ink_Canvas.Helpers
// 页数无效时清空页码显示
_mainWindow.PPTBtnPageNow.Text = "?";
_mainWindow.PPTBtnPageTotal.Text = "/ ?";
LogHelper.WriteLogToFile($"PPT页数无效,清空页码显示: 当前页={currentSlide}, 总页数={totalSlides}", LogHelper.LogType.Warning);
}
}
catch (Exception ex)
@@ -1,6 +1,5 @@
using System;
using System.Drawing;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;
+203 -189
View File
File diff suppressed because it is too large Load Diff
+142 -2
View File
@@ -457,8 +457,30 @@ namespace Ink_Canvas
// HasNewUpdateWindow hasNewUpdateWindow = new HasNewUpdateWindow();
if (Environment.Is64BitProcess) GroupBoxInkRecognition.Visibility = Visibility.Collapsed;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
SystemEvents_UserPreferenceChanged(null, null);
// 根据设置应用主题
switch (Settings.Appearance.Theme)
{
case 0: // 浅色主题
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
SetTheme("Light");
break;
case 1: // 深色主题
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
SetTheme("Dark");
break;
case 2: // 跟随系统
if (IsSystemThemeLight())
{
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
SetTheme("Light");
}
else
{
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
SetTheme("Dark");
}
break;
}
//TextBlockVersion.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString();
LogHelper.WriteLogToFile("Ink Canvas Loaded", LogHelper.LogType.Event);
@@ -2741,5 +2763,123 @@ namespace Ink_Canvas
}
#endregion
#region Theme Toggle
/// <summary>
/// 主题下拉框选择变化事件
/// </summary>
private void ComboBoxTheme_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!isLoaded) return;
try
{
System.Windows.Controls.ComboBox comboBox = sender as System.Windows.Controls.ComboBox;
if (comboBox != null)
{
Settings.Appearance.Theme = comboBox.SelectedIndex;
// 应用新主题
ApplyTheme(comboBox.SelectedIndex);
// 保存设置
SaveSettingsToFile();
// 显示通知
string themeName;
switch (comboBox.SelectedIndex)
{
case 0:
themeName = "浅色主题";
break;
case 1:
themeName = "深色主题";
break;
case 2:
themeName = "跟随系统";
break;
default:
themeName = "未知主题";
break;
}
ShowNotification($"已切换到{themeName}");
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"切换主题时出错: {ex.Message}", LogHelper.LogType.Error);
ShowNotification("主题切换失败");
}
}
/// <summary>
/// 应用指定主题
/// </summary>
/// <param name="themeIndex">主题索引:0-浅色,1-深色,2-跟随系统</param>
private void ApplyTheme(int themeIndex)
{
try
{
switch (themeIndex)
{
case 0: // 浅色主题
SetTheme("Light");
// 浅色主题下设置浮动栏为完全不透明
ViewboxFloatingBar.Opacity = 1.0;
break;
case 1: // 深色主题
SetTheme("Dark");
// 深色主题下设置浮动栏为完全不透明
ViewboxFloatingBar.Opacity = 1.0;
break;
case 2: // 跟随系统
if (IsSystemThemeLight())
{
SetTheme("Light");
ViewboxFloatingBar.Opacity = 1.0;
}
else
{
SetTheme("Dark");
ViewboxFloatingBar.Opacity = 1.0;
}
break;
}
// 强制刷新通知框的颜色资源
RefreshNotificationColors();
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"应用主题时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
/// <summary>
/// 刷新通知框的颜色资源
/// </summary>
private void RefreshNotificationColors()
{
try
{
// 强制刷新通知框的背景和前景色
var border = GridNotifications.Children.OfType<Border>().FirstOrDefault();
if (border != null)
{
border.Background = (Brush)Application.Current.FindResource("SettingsPageBackground");
border.BorderBrush = new SolidColorBrush(Color.FromRgb(185, 28, 28)); // 保持红色边框
}
TextBlockNotice.Foreground = (Brush)Application.Current.FindResource("SettingsPageForeground");
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"刷新通知框颜色时出错: {ex.Message}", LogHelper.LogType.Error);
}
}
#endregion
}
}
+113 -4
View File
@@ -1,6 +1,7 @@
using iNKORE.UI.WPF.Modern;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using Application = System.Windows.Application;
@@ -9,16 +10,34 @@ namespace Ink_Canvas
{
public partial class MainWindow : Window
{
private Color FloatBarForegroundColor = Color.FromRgb(102, 102, 102);
private Color FloatBarForegroundColor;
private void SetTheme(string theme)
{
// 清理现有的主题资源
var resourcesToRemove = new List<ResourceDictionary>();
foreach (var dict in Application.Current.Resources.MergedDictionaries)
{
if (dict.Source != null &&
(dict.Source.ToString().Contains("Light.xaml") ||
dict.Source.ToString().Contains("Dark.xaml")))
{
resourcesToRemove.Add(dict);
}
}
foreach (var dict in resourcesToRemove)
{
Application.Current.Resources.MergedDictionaries.Remove(dict);
}
if (theme == "Light")
{
var rd1 = new ResourceDictionary
{ Source = new Uri("Resources/Styles/Light.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd1);
// 在主题资源之后添加其他资源
var rd2 = new ResourceDictionary
{ Source = new Uri("Resources/DrawShapeImageDictionary.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd2);
@@ -33,13 +52,17 @@ namespace Ink_Canvas
ThemeManager.SetRequestedTheme(window, ElementTheme.Light);
FloatBarForegroundColor = (Color)Application.Current.FindResource("FloatBarForegroundColor");
InitializeFloatBarForegroundColor();
// 强制刷新UI
window.InvalidateVisual();
}
else if (theme == "Dark")
{
var rd1 = new ResourceDictionary { Source = new Uri("Resources/Styles/Dark.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd1);
// 在主题资源之后添加其他资源
var rd2 = new ResourceDictionary
{ Source = new Uri("Resources/DrawShapeImageDictionary.xaml", UriKind.Relative) };
Application.Current.Resources.MergedDictionaries.Add(rd2);
@@ -54,7 +77,93 @@ namespace Ink_Canvas
ThemeManager.SetRequestedTheme(window, ElementTheme.Dark);
InitializeFloatBarForegroundColor();
// 强制刷新UI
window.InvalidateVisual();
}
}
/// <summary>
/// 初始化FloatBarForegroundColor,从当前主题资源中加载颜色
/// </summary>
private void InitializeFloatBarForegroundColor()
{
try
{
FloatBarForegroundColor = (Color)Application.Current.FindResource("FloatBarForegroundColor");
// 强制刷新浮动工具栏按钮颜色
RefreshFloatingBarButtonColors();
}
catch (Exception)
{
// 如果无法从资源中加载,使用默认颜色
FloatBarForegroundColor = Color.FromRgb(0, 0, 0);
}
}
/// <summary>
/// 刷新浮动工具栏按钮颜色
/// </summary>
private void RefreshFloatingBarButtonColors()
{
try
{
// 选中状态的颜色(蓝底)
var selectedColor = Color.FromRgb(30, 58, 138);
// 根据当前模式设置按钮颜色
switch (_currentToolMode)
{
case "cursor":
CursorIconGeometry.Brush = new SolidColorBrush(selectedColor);
PenIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
StrokeEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
CircleEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
LassoSelectIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
break;
case "pen":
case "color":
CursorIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
PenIconGeometry.Brush = new SolidColorBrush(selectedColor);
StrokeEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
CircleEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
LassoSelectIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
break;
case "eraser":
CursorIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
PenIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
StrokeEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
CircleEraserIconGeometry.Brush = new SolidColorBrush(selectedColor);
LassoSelectIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
break;
case "eraserByStrokes":
CursorIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
PenIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
StrokeEraserIconGeometry.Brush = new SolidColorBrush(selectedColor);
CircleEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
LassoSelectIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
break;
case "select":
CursorIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
PenIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
StrokeEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
CircleEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
LassoSelectIconGeometry.Brush = new SolidColorBrush(selectedColor);
break;
default:
// 默认情况,所有按钮都使用主题颜色
CursorIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
PenIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
StrokeEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
CircleEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
LassoSelectIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
break;
}
}
catch (Exception)
{
}
}
+85 -31
View File
@@ -84,11 +84,23 @@ namespace Ink_Canvas
EnableTwoFingerGestureBtn.Source =
new BitmapImage(new Uri("/Resources/new-icons/gesture.png", UriKind.Relative));
BoardGesture.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardGestureGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGestureGeometry2.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGestureLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGesture.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
// 根据主题设置颜色
if (Settings.Appearance.Theme == 1) // 深色主题
{
BoardGesture.Background = new SolidColorBrush(Color.FromRgb(42, 42, 42));
BoardGestureGeometry.Brush = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardGestureGeometry2.Brush = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardGestureLabel.Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardGesture.BorderBrush = new SolidColorBrush(Color.FromRgb(85, 85, 85));
}
else // 浅色主题或跟随系统
{
BoardGesture.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardGestureGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGestureGeometry2.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGestureLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGesture.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
}
BoardGestureGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.DisabledGestureIcon);
BoardGestureGeometry2.Geometry = Geometry.Parse("F0 M24,24z M0,0z");
@@ -122,11 +134,23 @@ namespace Ink_Canvas
EnableTwoFingerGestureBtn.Source =
new BitmapImage(new Uri("/Resources/new-icons/gesture.png", UriKind.Relative));
BoardGesture.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardGestureGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGestureGeometry2.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGestureLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGesture.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
// 根据主题设置颜色
if (Settings.Appearance.Theme == 1) // 深色主题
{
BoardGesture.Background = new SolidColorBrush(Color.FromRgb(42, 42, 42));
BoardGestureGeometry.Brush = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardGestureGeometry2.Brush = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardGestureLabel.Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardGesture.BorderBrush = new SolidColorBrush(Color.FromRgb(85, 85, 85));
}
else // 浅色主题或跟随系统
{
BoardGesture.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardGestureGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGestureGeometry2.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGestureLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardGesture.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
}
BoardGestureGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.DisabledGestureIcon);
BoardGestureGeometry2.Geometry = Geometry.Parse("F0 M24,24z M0,0z");
}
@@ -404,31 +428,50 @@ namespace Ink_Canvas
{
if (mode != "clear")
{
CursorIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27));
CursorIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
CursorIconGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.LinedCursorIcon);
PenIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27));
PenIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
PenIconGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.LinedPenIcon);
StrokeEraserIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27));
StrokeEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
StrokeEraserIconGeometry.Geometry =
Geometry.Parse(XamlGraphicsIconGeometries.LinedEraserStrokeIcon);
CircleEraserIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27));
CircleEraserIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
CircleEraserIconGeometry.Geometry =
Geometry.Parse(XamlGraphicsIconGeometries.LinedEraserCircleIcon);
LassoSelectIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27));
LassoSelectIconGeometry.Brush = new SolidColorBrush(FloatBarForegroundColor);
LassoSelectIconGeometry.Geometry = Geometry.Parse(XamlGraphicsIconGeometries.LinedLassoSelectIcon);
BoardPen.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardSelect.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardEraser.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardSelectGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardPenGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardEraserGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardPenLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardSelectLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardEraserLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardSelect.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
BoardEraser.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
BoardPen.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
// 根据主题设置颜色
if (Settings.Appearance.Theme == 1) // 深色主题
{
BoardPen.Background = new SolidColorBrush(Color.FromRgb(42, 42, 42));
BoardSelect.Background = new SolidColorBrush(Color.FromRgb(42, 42, 42));
BoardEraser.Background = new SolidColorBrush(Color.FromRgb(42, 42, 42));
BoardSelectGeometry.Brush = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardPenGeometry.Brush = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardEraserGeometry.Brush = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardPenLabel.Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardSelectLabel.Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardEraserLabel.Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardSelect.BorderBrush = new SolidColorBrush(Color.FromRgb(85, 85, 85));
BoardEraser.BorderBrush = new SolidColorBrush(Color.FromRgb(85, 85, 85));
BoardPen.BorderBrush = new SolidColorBrush(Color.FromRgb(85, 85, 85));
}
else // 浅色主题或跟随系统
{
BoardPen.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardSelect.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardEraser.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardSelectGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardPenGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardEraserGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardPenLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardSelectLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardEraserLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardSelect.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
BoardEraser.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
BoardPen.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
}
HideFloatingBarHighlight();
}
@@ -492,10 +535,21 @@ namespace Ink_Canvas
CursorIconGeometry.Brush = new SolidColorBrush(Color.FromRgb(30, 58, 138));
CursorIconGeometry.Geometry =
Geometry.Parse(XamlGraphicsIconGeometries.LinedCursorIcon);
BoardPen.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardPen.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
BoardPenGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardPenLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
// 根据主题设置颜色
if (Settings.Appearance.Theme == 1) // 深色主题
{
BoardPen.Background = new SolidColorBrush(Color.FromRgb(42, 42, 42));
BoardPen.BorderBrush = new SolidColorBrush(Color.FromRgb(85, 85, 85));
BoardPenGeometry.Brush = new SolidColorBrush(Color.FromRgb(255, 255, 255));
BoardPenLabel.Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255));
}
else // 浅色主题或跟随系统
{
BoardPen.Background = new SolidColorBrush(Color.FromRgb(244, 244, 245));
BoardPen.BorderBrush = new SolidColorBrush(Color.FromRgb(161, 161, 170));
BoardPenGeometry.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
BoardPenLabel.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
}
SetFloatingBarHighlightPosition("cursor");
break;
@@ -3,7 +3,6 @@ using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace Ink_Canvas
{
+31 -4
View File
@@ -1121,14 +1121,42 @@ namespace Ink_Canvas
{
try
{
// 检查PPT连接状态
if (_pptManager?.IsConnected != true || _pptManager?.IsInSlideShow != true)
{
return;
}
// 获取当前页面索引
var currentSlideIndex = _pptManager?.GetCurrentSlideNumber() ?? 0;
// 验证页面索引的有效性
if (newSlideIndex <= 0)
{
LogHelper.WriteLogToFile($"无效的新页面索引: {newSlideIndex},跳过页面切换", LogHelper.LogType.Warning);
return;
}
// 如果有当前墨迹且不是第一次切换,先保存到当前页面
if (inkCanvas.Strokes.Count > 0 && currentSlideIndex > 0 && currentSlideIndex != newSlideIndex)
{
_multiPPTInkManager?.SaveCurrentSlideStrokes(currentSlideIndex, inkCanvas.Strokes);
LogHelper.WriteLogToFile($"切换前保存第{currentSlideIndex}页墨迹,墨迹数量: {inkCanvas.Strokes.Count}", LogHelper.LogType.Trace);
// 检查是否可以写入墨迹
bool canWrite = _multiPPTInkManager?.CanWriteInk(currentSlideIndex) == true;
if (canWrite)
{
// 正常保存
_multiPPTInkManager?.SaveCurrentSlideStrokes(currentSlideIndex, inkCanvas.Strokes);
}
else
{
// 墨迹被锁定,跳过保存以避免墨迹错页
}
}
else if (inkCanvas.Strokes.Count > 0 && currentSlideIndex <= 0)
{
// 无法获取当前页面索引时,不保存墨迹,直接清空
}
// 切换到新页面并加载墨迹
@@ -1139,8 +1167,7 @@ namespace Ink_Canvas
inkCanvas.Strokes.Add(newStrokes);
}
// 设置墨迹锁定
_multiPPTInkManager?.LockInkForSlide(newSlideIndex);
// 注意:LockInkForSlide已经在SwitchToSlide中调用,这里不需要重复调用
}
catch (Exception ex)
{
@@ -245,6 +245,9 @@ namespace Ink_Canvas
break;
}
// 设置主题下拉框
ComboBoxTheme.SelectedIndex = Settings.Appearance.Theme;
ComboBoxChickenSoupSource.SelectedIndex = Settings.Appearance.ChickenSoupSource;
ToggleSwitchEnableQuickPanel.IsOn = Settings.Appearance.IsShowQuickPanel;
@@ -9,7 +9,6 @@ using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Point = System.Windows.Point;
namespace Ink_Canvas
+2 -2
View File
@@ -49,5 +49,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.7.11.1")]
[assembly: AssemblyFileVersion("1.7.11.1")]
[assembly: AssemblyVersion("1.7.11.3")]
[assembly: AssemblyFileVersion("1.7.11.3")]
+30 -5
View File
@@ -1,7 +1,32 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="FloatBarBackground" Color="Black" Opacity="0.5"/>
<SolidColorBrush x:Key="FloatBarBorderBrush" Color="White" Opacity="0.5"/>
<SolidColorBrush x:Key="FloatBarForeground" Color="White"/>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="FloatBarBackground" Opacity="0.6" Color="Black" />
<SolidColorBrush x:Key="FloatBarBackgroundWithoutOpacity" Opacity="0.95" Color="Black" />
<SolidColorBrush x:Key="FloatBarTitleBackground" Opacity="0.5" Color="#2156c9" />
<SolidColorBrush x:Key="FloatBarBorderBrush" Opacity="0.6" Color="White" />
<SolidColorBrush x:Key="FloatBarForeground" Color="White" />
<Color x:Key="FloatBarForegroundColor">#FFcccccc</Color>
<SolidColorBrush x:Key="SettingsPageForeground" Color="White" />
<SolidColorBrush x:Key="SettingsPageAnnotationForeground" Opacity="0.7" Color="White" />
<SolidColorBrush x:Key="SettingsPageBorderBrush" Opacity="0.8" Color="White" />
<SolidColorBrush x:Key="SettingsPageBackground" Opacity="0.95" Color="#1f1f1f" />
<SolidColorBrush x:Key="IconForeground" Color="White" />
<SolidColorBrush x:Key="TextForeground" Color="White" />
<SolidColorBrush x:Key="RedBrush" Color="IndianRed" />
<SolidColorBrush x:Key="PurpleBrush" Color="MediumPurple" />
<Color x:Key="FloatBarButtonBackgroundKey">Transparent</Color>
<Color x:Key="FloatBarButtonBackgroundPointerOverKey">#2200CDCD</Color>
<Color x:Key="FloatBarButtonButtonBackgroundPressedKey">#4400CDCD</Color>
<!-- 白板模式浮动栏颜色 -->
<SolidColorBrush x:Key="BoardFloatBarBackground" Color="#2a2a2a" />
<SolidColorBrush x:Key="BoardFloatBarBorderBrush" Color="#555555" />
<!-- 白板模式按钮选中状态颜色 -->
<SolidColorBrush x:Key="BoardFloatBarSelectedBackground" Color="#2563eb" />
<SolidColorBrush x:Key="BoardFloatBarSelectedBorderBrush" Color="#2563eb" />
<SolidColorBrush x:Key="BoardFloatBarSelectedForeground" Color="White" />
</ResourceDictionary>
+31 -6
View File
@@ -1,7 +1,32 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="FloatBarBackground" Color="#fafafa" Opacity="0.95"/>
<SolidColorBrush x:Key="FloatBarBorderBrush" Color="#52525b" Opacity="0.6"/>
<SolidColorBrush x:Key="FloatBarForeground" Color="#18181b"/>
<Color x:Key="FloatBarForegroundColor">#18181b</Color>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="FloatBarBackground" Opacity="1.0" Color="White" />
<SolidColorBrush x:Key="FloatBarBackgroundWithoutOpacity" Opacity="1.0" Color="White" />
<SolidColorBrush x:Key="FloatBarTitleBackground" Opacity="0.25" Color="#588bfc" />
<SolidColorBrush x:Key="FloatBarBorderBrush" Opacity="0.8" Color="Black" />
<SolidColorBrush x:Key="FloatBarForeground" Color="Black" />
<Color x:Key="FloatBarForegroundColor">#FF000000</Color>
<SolidColorBrush x:Key="SettingsPageForeground" Color="Black" />
<SolidColorBrush x:Key="SettingsPageAnnotationForeground" Color="#666666" />
<SolidColorBrush x:Key="SettingsPageBorderBrush" Opacity="0.8" Color="Black" />
<SolidColorBrush x:Key="SettingsPageBackground" Opacity="0.95" Color="White" />
<SolidColorBrush x:Key="IconForeground" Color="#18181b" />
<SolidColorBrush x:Key="TextForeground" Color="Black" />
<SolidColorBrush x:Key="RedBrush" Color="DarkRed" />
<SolidColorBrush x:Key="PurpleBrush" Color="DarkBlue" />
<Color x:Key="FloatBarButtonBackgroundKey">Transparent</Color>
<Color x:Key="FloatBarButtonBackgroundPointerOverKey">#66FFFFFF</Color>
<Color x:Key="FloatBarButtonButtonBackgroundPressedKey">#99FFFFFF</Color>
<!-- 白板模式浮动栏颜色 -->
<SolidColorBrush x:Key="BoardFloatBarBackground" Color="#f4f4f5" />
<SolidColorBrush x:Key="BoardFloatBarBorderBrush" Color="#a1a1aa" />
<!-- 白板模式按钮选中状态颜色 -->
<SolidColorBrush x:Key="BoardFloatBarSelectedBackground" Color="#2563eb" />
<SolidColorBrush x:Key="BoardFloatBarSelectedBorderBrush" Color="#2563eb" />
<SolidColorBrush x:Key="BoardFloatBarSelectedForeground" Color="White" />
</ResourceDictionary>
+5 -5
View File
@@ -11,13 +11,13 @@
ui:WindowHelper.SystemBackdropType="Mica"
Title="InkCanvasForClass CE有新版本可用" Height="650" Width="900" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen" WindowStyle="None" AllowsTransparency="True"
Background="#f8fafc">
Background="Transparent">
<Window.Template>
<ControlTemplate TargetType="Window">
<Border Background="{TemplateBinding Background}"
<Border Background="#f8fafc"
CornerRadius="16"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
BorderBrush="Transparent"
BorderThickness="0">
<Border.Effect>
<DropShadowEffect Color="#000000" BlurRadius="30" ShadowDepth="0" Opacity="0.15"/>
</Border.Effect>
@@ -140,7 +140,7 @@
</Window.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<Grid Margin="0,0,0,0">
<Grid Margin="0,0,0,0" Background="Transparent">
<ui:SimpleStackPanel VerticalAlignment="Stretch" Spacing="0">
<!-- 统一的主容器 -->
<Border Background="White" CornerRadius="16" Margin="0,0,0,0"
+230 -13
View File
@@ -6,19 +6,236 @@
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:mdxam="clr-namespace:MdXaml;assembly=MdXaml"
mc:Ignorable="d"
Title="历史版本回滚" Height="600" Width="850" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
<Grid Background="#fafafa">
<ui:SimpleStackPanel VerticalAlignment="Stretch" Spacing="0">
<TextBlock Text="选择历史版本进行回滚" FontSize="24" FontWeight="Bold" Foreground="#2563eb" Margin="24,24,0,12"/>
<ComboBox x:Name="VersionComboBox" Width="400" Height="36" Margin="24,0,0,0" DisplayMemberPath="Version" SelectionChanged="VersionComboBox_SelectionChanged"/>
<Border BorderBrush="#3f3f46" Background="White" BorderThickness="1" CornerRadius="4" Margin="24,16,24,0" Height="180">
<mdxam:MarkdownScrollViewer x:Name="ReleaseNotesViewer" Foreground="Black" MarkdownStyleName="GithubLike"/>
ui:WindowHelper.UseModernWindowStyle="False"
ui:WindowHelper.SystemBackdropType="Mica"
Title="历史版本回滚" Height="650" Width="900" ResizeMode="CanResize"
WindowStartupLocation="CenterScreen" WindowStyle="None" AllowsTransparency="True"
Background="Transparent" MinHeight="550" MinWidth="800">
<Window.Template>
<ControlTemplate TargetType="Window">
<Border Background="#f8fafc"
CornerRadius="16"
BorderBrush="Transparent"
BorderThickness="0">
<Border.Effect>
<DropShadowEffect Color="#000000" BlurRadius="30" ShadowDepth="0" Opacity="0.15"/>
</Border.Effect>
<Grid>
<!-- 标题栏 -->
<Border Background="Transparent" Height="40" VerticalAlignment="Top">
<Grid>
<TextBlock Text="{TemplateBinding Title}"
FontSize="16" FontWeight="SemiBold"
Foreground="#374151"
VerticalAlignment="Center"
Margin="20,0,0,0"/>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<Button Name="MinimizeButton"
Width="40" Height="30"
Background="Transparent"
BorderThickness="0"
Click="MinimizeButton_Click"
Margin="0,0,2,0">
<TextBlock Text="" FontSize="16" Foreground="#6b7280"/>
</Button>
<Button Name="CloseButton"
Width="40" Height="30"
Background="Transparent"
BorderThickness="0"
Click="CloseButton_Click">
<TextBlock Text="×" FontSize="16" Foreground="#6b7280"/>
</Button>
</StackPanel>
</Grid>
</Border>
<!-- 内容区域 -->
<ContentPresenter Margin="0,40,0,0"/>
</Grid>
</Border>
</ControlTemplate>
</Window.Template>
<Window.Resources>
<!-- 现代化按钮样式 -->
<Style x:Key="ModernPrimaryButton" TargetType="Button">
<Setter Property="Background" Value="#3b82f6"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="Padding" Value="24,12"/>
<Setter Property="Height" Value="48"/>
<Setter Property="Width" Value="320"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="12"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Border.Effect>
<DropShadowEffect Color="#3b82f6" BlurRadius="8" ShadowDepth="0" Opacity="0.3"/>
</Border.Effect>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#2563eb"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#1d4ed8"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#9ca3af"/>
<Setter Property="Foreground" Value="#6b7280"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- 现代化ComboBox样式 -->
<Style x:Key="ModernComboBox" TargetType="ComboBox">
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="#374151"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="#d1d5db"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Padding" Value="12,8"/>
</Style>
<!-- ComboBoxItem样式 -->
<Style TargetType="ComboBoxItem">
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="#374151"/>
<Setter Property="Padding" Value="12,8"/>
<Setter Property="Margin" Value="0,1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Border Background="{TemplateBinding Background}"
CornerRadius="4"
Margin="2">
<ContentPresenter Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#f0f9ff"/>
<Setter Property="Foreground" Value="#1e40af"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#3b82f6"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Background="Transparent">
<!-- 主内容区域 -->
<Border Background="White" CornerRadius="16" Margin="20"
BorderThickness="0" Padding="0">
<Border.Effect>
<DropShadowEffect Color="#000000" BlurRadius="20" ShadowDepth="0" Opacity="0.08"/>
</Border.Effect>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<ui:SimpleStackPanel VerticalAlignment="Stretch" Spacing="0" Margin="28">
<!-- 标题区域 -->
<ui:SimpleStackPanel Orientation="Horizontal" Spacing="12" Margin="0,32,0,24">
<Border Background="#3b82f6" CornerRadius="8" Width="40" Height="40"
VerticalAlignment="Center">
<TextBlock Text="↶" FontSize="20" Foreground="White"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ui:SimpleStackPanel VerticalAlignment="Center" Spacing="4">
<TextBlock Text="历史版本回滚" FontSize="28" FontWeight="Bold"
Foreground="#1f2937"/>
<TextBlock Text="选择要回滚到的历史版本" FontSize="14"
Foreground="#6b7280"/>
</ui:SimpleStackPanel>
</ui:SimpleStackPanel>
<!-- 版本选择卡片 -->
<Border Background="#f8fafc" CornerRadius="12" Padding="20" Margin="0,0,0,20">
<Border.Effect>
<DropShadowEffect Color="#000000" BlurRadius="8" ShadowDepth="0" Opacity="0.05"/>
</Border.Effect>
<ui:SimpleStackPanel Spacing="12">
<TextBlock Text="选择版本" FontSize="16" FontWeight="SemiBold"
Foreground="#374151"/>
<ComboBox x:Name="VersionComboBox"
Width="400" Height="40"
DisplayMemberPath="Version"
SelectionChanged="VersionComboBox_SelectionChanged"
Background="White"
BorderBrush="#d1d5db"
BorderThickness="1"
FontSize="14"/>
</ui:SimpleStackPanel>
</Border>
<!-- 发布说明卡片 -->
<Border Background="#f8fafc" CornerRadius="12" Padding="20" Margin="0,0,0,20">
<Border.Effect>
<DropShadowEffect Color="#000000" BlurRadius="8" ShadowDepth="0" Opacity="0.05"/>
</Border.Effect>
<ui:SimpleStackPanel Spacing="12">
<TextBlock Text="版本更新说明" FontSize="16" FontWeight="SemiBold"
Foreground="#374151"/>
<Border Background="White" BorderBrush="#e5e7eb" BorderThickness="1"
CornerRadius="8" MinHeight="200" MaxHeight="300">
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"
Padding="16">
<mdxam:MarkdownScrollViewer x:Name="ReleaseNotesViewer"
Foreground="#374151"
MarkdownStyleName="GithubLike"/>
</ScrollViewer>
</Border>
</ui:SimpleStackPanel>
</Border>
<!-- 操作按钮区域 -->
<ui:SimpleStackPanel Spacing="16" Margin="0,0,0,32">
<Button x:Name="RollbackButton"
Content="回滚到此版本"
Style="{StaticResource ModernPrimaryButton}"
Click="RollbackButton_Click"/>
<!-- 下载进度面板 -->
<StackPanel x:Name="DownloadProgressPanel"
Orientation="Vertical"
HorizontalAlignment="Center"
Visibility="Collapsed"
Margin="0,8,0,0">
<Border Background="#f0f9ff" BorderBrush="#3b82f6"
BorderThickness="1" CornerRadius="8" Padding="16">
<ui:SimpleStackPanel Spacing="12">
<ProgressBar x:Name="DownloadProgressBar"
Width="400" Height="8"
Minimum="0" Maximum="100" Value="0"
Background="#e0f2fe"
Foreground="#3b82f6"/>
<TextBlock x:Name="DownloadProgressText"
Text="正在下载..."
FontSize="14"
Foreground="#1e40af"
HorizontalAlignment="Center"/>
</ui:SimpleStackPanel>
</Border>
<Button x:Name="RollbackButton" Content="回滚到此版本" Width="360" Height="48" Margin="24,24,0,0" Click="RollbackButton_Click"/>
<StackPanel x:Name="DownloadProgressPanel" Orientation="Vertical" HorizontalAlignment="Center" Margin="0,10,0,0" Visibility="Collapsed">
<ProgressBar x:Name="DownloadProgressBar" Width="360" Height="18" Minimum="0" Maximum="100" Value="0"/>
<TextBlock x:Name="DownloadProgressText" Text="正在下载..." FontSize="14" Foreground="#2563eb" HorizontalAlignment="Center" Margin="0,6,0,0"/>
</StackPanel>
</ui:SimpleStackPanel>
</ui:SimpleStackPanel>
</ui:SimpleStackPanel>
</ScrollViewer>
</Border>
</Grid>
</Window>
</Window>
@@ -32,6 +32,15 @@ namespace Ink_Canvas
InitializeComponent();
this.channel = channel;
LoadVersions();
// 添加窗口拖动功能
this.MouseDown += (sender, e) =>
{
if (e.ChangedButton == MouseButton.Left)
{
this.DragMove();
}
};
}
private async void LoadVersions()
@@ -135,6 +144,16 @@ namespace Ink_Canvas
}
}
private void MinimizeButton_Click(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
protected override void OnClosing(CancelEventArgs e)
{
downloadCts?.Cancel();