Files
community/Ink Canvas/MainWindow_cs/MW_PPT.cs
T

1068 lines
40 KiB
C#
Raw Normal View History

2025-07-28 14:40:44 +08:00
using System;
2025-05-25 09:29:48 +08:00
using System.IO;
using System.Runtime.InteropServices;
2025-07-28 14:40:44 +08:00
using System.Security.Cryptography;
using System.Text;
2025-05-25 09:29:48 +08:00
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
2025-07-28 14:40:44 +08:00
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.PowerPoint;
2025-05-25 09:29:48 +08:00
using Application = System.Windows.Application;
using File = System.IO.File;
using MessageBox = System.Windows.MessageBox;
2025-07-29 01:15:32 +08:00
using MouseButtonEventArgs = System.Windows.Input.MouseButtonEventArgs;
2025-07-28 14:40:44 +08:00
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
2025-05-25 09:29:48 +08:00
namespace Ink_Canvas {
public partial class MainWindow : Window {
2025-07-29 01:15:32 +08:00
#region Win32 API Declarations
2025-07-20 12:01:30 +08:00
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
2025-07-20 15:00:11 +08:00
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
2025-07-28 14:40:44 +08:00
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
2025-07-20 15:00:11 +08:00
2025-07-20 19:36:58 +08:00
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindowVisible(IntPtr hWnd);
2025-07-21 08:37:37 +08:00
[DllImport("user32.dll")]
private static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool IsZoomed(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
[DllImport("user32.dll")]
private static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out ForegroundWindowInfo.RECT lpRect);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
2025-07-28 14:40:44 +08:00
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
2025-07-21 08:37:37 +08:00
private const int GWL_STYLE = -16;
private const int WS_VISIBLE = 0x10000000;
private const int WS_MINIMIZE = 0x20000000;
private const uint GW_HWNDNEXT = 2;
private const uint GW_HWNDPREV = 3;
2025-07-20 15:00:11 +08:00
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
2025-07-29 01:15:32 +08:00
#endregion
2025-07-20 15:00:11 +08:00
2025-07-29 01:15:32 +08:00
#region PPT Application Variables
2025-07-28 14:40:44 +08:00
public static Microsoft.Office.Interop.PowerPoint.Application pptApplication;
public static Presentation presentation;
public static Slides slides;
public static Slide slide;
public static int slidescount;
2025-07-29 01:15:32 +08:00
#endregion
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
#region PPT State Management
2025-07-28 14:40:44 +08:00
private bool wasFloatingBarFoldedWhenEnterSlideShow;
2025-07-25 10:21:55 +08:00
private static bool hasShownWpsForceCloseWarning = false;
2025-07-29 01:15:32 +08:00
private bool isEnteredSlideShowEndEvent; //防止重复调用本函数导致墨迹保存失效
private bool isPresentationHaveBlackSpace;
private string pptName;
private bool _isPptClickingBtnTurned;
#endregion
2025-07-25 10:21:55 +08:00
2025-07-29 01:15:32 +08:00
#region PPT Managers
private PPTManager _pptManager;
private PPTInkManager _pptInkManager;
private PPTUIManager _pptUIManager;
#endregion
2025-07-19 23:42:43 +08:00
2025-07-29 01:15:32 +08:00
#region PPT Manager Initialization
private void InitializePPTManagers()
{
try
{
// 初始化PPT管理器
_pptManager = new PPTManager();
_pptManager.IsSupportWPS = Settings.PowerPointSettings.IsSupportWPS;
// 注册事件
_pptManager.PPTConnectionChanged += OnPPTConnectionChanged;
_pptManager.SlideShowBegin += OnPPTSlideShowBegin;
_pptManager.SlideShowNextSlide += OnPPTSlideShowNextSlide;
_pptManager.SlideShowEnd += OnPPTSlideShowEnd;
_pptManager.PresentationOpen += OnPPTPresentationOpen;
_pptManager.PresentationClose += OnPPTPresentationClose;
// 初始化墨迹管理器
_pptInkManager = new PPTInkManager();
_pptInkManager.IsAutoSaveEnabled = Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint;
_pptInkManager.AutoSaveLocation = Settings.Automation.AutoSavedStrokesLocation;
// 初始化UI管理器
_pptUIManager = new PPTUIManager(this);
_pptUIManager.ShowPPTButton = Settings.PowerPointSettings.ShowPPTButton;
_pptUIManager.PPTButtonsDisplayOption = Settings.PowerPointSettings.PPTButtonsDisplayOption;
_pptUIManager.PPTSButtonsOption = Settings.PowerPointSettings.PPTSButtonsOption;
_pptUIManager.PPTBButtonsOption = Settings.PowerPointSettings.PPTBButtonsOption;
_pptUIManager.PPTLSButtonPosition = Settings.PowerPointSettings.PPTLSButtonPosition;
_pptUIManager.PPTRSButtonPosition = Settings.PowerPointSettings.PPTRSButtonPosition;
_pptUIManager.EnablePPTButtonPageClickable = Settings.PowerPointSettings.EnablePPTButtonPageClickable;
LogHelper.WriteLogToFile("PPT管理器初始化完成", LogHelper.LogType.Event);
2025-05-25 09:29:48 +08:00
}
2025-07-29 01:15:32 +08:00
catch (Exception ex)
{
LogHelper.WriteLogToFile($"PPT管理器初始化失败: {ex}", LogHelper.LogType.Error);
2025-05-25 09:29:48 +08:00
}
}
2025-07-29 01:15:32 +08:00
private void StartPPTMonitoring()
{
if (Settings.PowerPointSettings.PowerPointSupport)
{
_pptManager?.StartMonitoring();
LogHelper.WriteLogToFile("PPT监控已启动", LogHelper.LogType.Event);
}
2025-05-25 09:29:48 +08:00
}
2025-07-29 01:15:32 +08:00
private void StopPPTMonitoring()
{
_pptManager?.StopMonitoring();
LogHelper.WriteLogToFile("PPT监控已停止", LogHelper.LogType.Event);
}
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
private void DisposePPTManagers()
{
try
{
_pptManager?.Dispose();
_pptInkManager?.Dispose();
_pptManager = null;
_pptInkManager = null;
_pptUIManager = null;
LogHelper.WriteLogToFile("PPT管理器已释放", LogHelper.LogType.Event);
2025-05-25 09:29:48 +08:00
}
2025-07-20 19:36:58 +08:00
catch (Exception ex)
{
2025-07-29 01:15:32 +08:00
LogHelper.WriteLogToFile($"释放PPT管理器失败: {ex}", LogHelper.LogType.Error);
2025-05-25 09:29:48 +08:00
}
}
2025-07-29 01:15:32 +08:00
#endregion
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
#region New PPT Event Handlers
private void OnPPTConnectionChanged(bool isConnected)
{
try
2025-07-21 17:19:27 +08:00
{
2025-07-29 01:15:32 +08:00
Application.Current.Dispatcher.InvokeAsync(() =>
{
_pptUIManager?.UpdateConnectionStatus(isConnected);
if (isConnected)
2025-07-21 17:19:27 +08:00
{
2025-07-29 01:15:32 +08:00
LogHelper.WriteLogToFile("PPT连接已建立", LogHelper.LogType.Event);
2025-07-21 17:19:27 +08:00
}
2025-07-29 01:15:32 +08:00
else
2025-07-21 17:19:27 +08:00
{
2025-07-29 01:15:32 +08:00
LogHelper.WriteLogToFile("PPT连接已断开", LogHelper.LogType.Event);
// 清理墨迹管理器
_pptInkManager?.ClearAllStrokes();
2025-07-21 17:19:27 +08:00
}
2025-07-29 01:15:32 +08:00
});
2025-07-21 17:19:27 +08:00
}
2025-07-29 01:15:32 +08:00
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理PPT连接状态变化失败: {ex}", LogHelper.LogType.Error);
}
}
2025-07-20 16:14:26 +08:00
2025-07-29 01:15:32 +08:00
private void OnPPTPresentationOpen(Presentation pres)
{
try
{
Application.Current.Dispatcher.InvokeAsync(() =>
{
// 初始化墨迹管理器
_pptInkManager?.InitializePresentation(pres);
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
// 处理跳转到首页或上次播放页的逻辑
HandlePresentationOpenNavigation(pres);
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
// 检查隐藏幻灯片
if (Settings.PowerPointSettings.IsNotifyHiddenPage)
2025-07-20 16:14:26 +08:00
{
2025-07-29 01:15:32 +08:00
CheckAndNotifyHiddenSlides(pres);
2025-05-25 09:29:48 +08:00
}
2025-07-29 01:15:32 +08:00
// 检查自动播放设置
if (Settings.PowerPointSettings.IsNotifyAutoPlayPresentation)
2025-07-20 16:14:26 +08:00
{
2025-07-29 01:15:32 +08:00
CheckAndNotifyAutoPlaySettings(pres);
2025-07-20 16:14:26 +08:00
}
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
_pptUIManager?.UpdateConnectionStatus(true);
2025-05-25 09:29:48 +08:00
});
}
2025-07-29 01:15:32 +08:00
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理演示文稿打开事件失败: {ex}", LogHelper.LogType.Error);
2025-05-25 09:29:48 +08:00
}
}
2025-07-29 01:15:32 +08:00
private void OnPPTPresentationClose(Presentation pres)
{
try
{
Application.Current.Dispatcher.InvokeAsync(() =>
2025-05-25 09:29:48 +08:00
{
2025-07-29 01:15:32 +08:00
// 保存所有墨迹
_pptInkManager?.SaveAllStrokesToFile(pres);
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
// 清理墨迹管理器
_pptInkManager?.ClearAllStrokes();
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
_pptUIManager?.UpdateConnectionStatus(false);
});
2025-05-25 09:29:48 +08:00
}
2025-07-29 01:15:32 +08:00
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理演示文稿关闭事件失败: {ex}", LogHelper.LogType.Error);
2025-05-25 09:29:48 +08:00
}
}
2025-07-29 01:15:32 +08:00
private async void OnPPTSlideShowBegin(SlideShowWindow wn)
{
try
{
// 记录进入放映时浮动栏收纳状态
wasFloatingBarFoldedWhenEnterSlideShow = isFloatingBarFolded;
2025-07-29 01:15:32 +08:00
2025-05-25 09:29:48 +08:00
if (Settings.Automation.IsAutoFoldInPPTSlideShow && !isFloatingBarFolded)
FoldFloatingBar_MouseUp(new object(), null);
2025-07-29 01:15:32 +08:00
else if (isFloatingBarFolded)
await UnFoldFloatingBar(new object());
2025-05-25 09:29:48 +08:00
isStopInkReplay = true;
2025-07-29 01:15:32 +08:00
await Application.Current.Dispatcher.InvokeAsync(() =>
{
// 处理跳转到首页
2025-07-21 17:19:27 +08:00
if (Settings.PowerPointSettings.IsAlwaysGoToFirstPageOnReenter)
{
2025-07-29 01:15:32 +08:00
_pptManager?.TryNavigateToSlide(1);
2025-07-21 17:19:27 +08:00
}
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
// 更新UI状态
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
var totalSlides = _pptManager?.SlidesCount ?? 0;
_pptUIManager?.UpdateSlideShowStatus(true, currentSlide, totalSlides);
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
// 设置浮动栏透明度和边距
_pptUIManager?.SetFloatingBarOpacity(Settings.Appearance.ViewboxFloatingBarOpacityInPPTValue);
_pptUIManager?.SetMainPanelMargin(new Thickness(10, 10, 10, 10));
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
// 显示侧边栏退出按钮
_pptUIManager?.UpdateSidebarExitButtons(true);
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
// 处理画板显示
2025-05-25 09:29:48 +08:00
if (Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow &&
!Settings.Automation.IsAutoFoldInPPTSlideShow &&
2025-07-29 01:15:32 +08:00
GridTransparencyFakeBackground.Background == Brushes.Transparent && !isFloatingBarFolded)
{
2025-05-25 09:29:48 +08:00
BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
}
if (currentMode != 0)
{
2025-07-29 01:15:32 +08:00
ImageBlackboard_MouseUp(null, null);
2025-05-25 09:29:48 +08:00
BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
}
BorderFloatingBarMainControls.Visibility = Visibility.Visible;
if (Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow &&
!Settings.Automation.IsAutoFoldInPPTSlideShow)
BtnColorRed_Click(null, null);
isEnteredSlideShowEndEvent = false;
2025-07-29 01:15:32 +08:00
// 加载当前页墨迹
LoadCurrentSlideInk(currentSlide);
});
if (!isFloatingBarFolded)
{
new Thread(() =>
2025-07-21 14:35:30 +08:00
{
2025-07-29 01:15:32 +08:00
Thread.Sleep(100);
Application.Current.Dispatcher.Invoke(() =>
2025-07-21 14:35:30 +08:00
{
2025-07-29 01:15:32 +08:00
ViewboxFloatingBarMarginAnimation(60);
});
}).Start();
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理幻灯片放映开始事件失败: {ex}", LogHelper.LogType.Error);
}
}
2025-07-21 14:35:30 +08:00
2025-07-29 01:15:32 +08:00
private void OnPPTSlideShowNextSlide(SlideShowWindow wn)
{
try
{
Application.Current.Dispatcher.InvokeAsync(() =>
{
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
var totalSlides = _pptManager?.SlidesCount ?? 0;
// 保存上一页墨迹并加载当前页墨迹
SwitchSlideInk(currentSlide);
// 更新UI
_pptUIManager?.UpdateCurrentSlideNumber(currentSlide, totalSlides);
LogHelper.WriteLogToFile($"幻灯片切换到第{currentSlide}页", LogHelper.LogType.Trace);
2025-07-21 16:43:29 +08:00
});
2025-05-25 09:29:48 +08:00
}
2025-07-29 01:15:32 +08:00
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理幻灯片切换事件失败: {ex}", LogHelper.LogType.Error);
2025-05-25 09:29:48 +08:00
}
}
2025-07-29 01:15:32 +08:00
private async void OnPPTSlideShowEnd(Presentation pres)
{
try
{
// 处理浮动栏状态
if (Settings.Automation.IsAutoFoldAfterPPTSlideShow && wasFloatingBarFoldedWhenEnterSlideShow)
{
if (!isFloatingBarFolded) FoldFloatingBar_MouseUp(new object(), null);
2025-07-29 01:15:32 +08:00
}
else
{
if (isFloatingBarFolded) await UnFoldFloatingBar(new object());
}
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
if (isEnteredSlideShowEndEvent) return;
isEnteredSlideShowEndEvent = true;
// 保存所有墨迹
_pptInkManager?.SaveAllStrokesToFile(pres);
await Application.Current.Dispatcher.InvokeAsync(() =>
2025-07-20 12:01:30 +08:00
{
2025-07-21 08:37:37 +08:00
try
{
2025-07-29 01:15:32 +08:00
isPresentationHaveBlackSpace = false;
// 恢复主题
if (BtnSwitchTheme.Content.ToString() == "深色")
2025-07-21 08:37:37 +08:00
{
2025-07-29 01:15:32 +08:00
BtnExit.Foreground = Brushes.Black;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
2025-07-21 08:37:37 +08:00
}
2025-07-29 01:15:32 +08:00
// 更新UI状态
_pptUIManager?.UpdateSlideShowStatus(false);
_pptUIManager?.UpdateSidebarExitButtons(false);
_pptUIManager?.SetMainPanelMargin(new Thickness(10, 10, 10, 55));
_pptUIManager?.SetFloatingBarOpacity(Settings.Appearance.ViewboxFloatingBarOpacityValue);
if (currentMode != 0)
2025-07-21 08:37:37 +08:00
{
2025-07-29 01:15:32 +08:00
CloseWhiteboardImmediately();
currentMode = 0;
2025-07-21 08:37:37 +08:00
}
2025-07-29 01:15:32 +08:00
ClearStrokes(true);
2025-07-29 01:31:21 +08:00
// 清空备份历史记录,防止退出白板时恢复已结束PPT的墨迹
// 注意:这里只清空索引0的备份,不影响白板页面的墨迹(索引1及以上)
2025-07-29 01:15:32 +08:00
TimeMachineHistories[0] = null;
if (GridTransparencyFakeBackground.Background != Brushes.Transparent)
BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
2025-07-21 08:37:37 +08:00
}
catch (Exception ex)
{
2025-07-29 01:15:32 +08:00
LogHelper.WriteLogToFile($"处理幻灯片放映结束UI更新失败: {ex}", LogHelper.LogType.Error);
2025-07-21 08:37:37 +08:00
}
2025-07-29 01:15:32 +08:00
});
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
await Task.Delay(150);
await Application.Current.Dispatcher.InvokeAsync(() =>
{
ViewboxFloatingBarMarginAnimation(100, true);
});
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理幻灯片放映结束事件失败: {ex}", LogHelper.LogType.Error);
}
}
#endregion
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
#region Helper Methods
private void HandlePresentationOpenNavigation(Presentation pres)
{
try
{
if (Settings.PowerPointSettings.IsAlwaysGoToFirstPageOnReenter)
{
_pptManager?.TryNavigateToSlide(1);
2025-05-25 09:29:48 +08:00
}
2025-07-29 01:15:32 +08:00
else if (Settings.PowerPointSettings.IsNotifyPreviousPage)
{
ShowPreviousPageNotification(pres);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理演示文稿导航失败: {ex}", LogHelper.LogType.Error);
}
}
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
private void ShowPreviousPageNotification(Presentation pres)
{
try
{
if (pres == null) return;
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
var presentationPath = pres.FullName;
var fileHash = GetFileHash(presentationPath);
var folderName = pres.Name + "_" + pres.Slides.Count + "_" + fileHash;
var folderPath = Path.Combine(Settings.Automation.AutoSavedStrokesLocation, "Auto Saved - Presentations", folderName);
var positionFile = Path.Combine(folderPath, "Position");
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
if (!File.Exists(positionFile)) return;
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
if (int.TryParse(File.ReadAllText(positionFile), out var page) && page > 0)
{
new YesOrNoNotificationWindow($"上次播放到了第 {page} 页, 是否立即跳转", () =>
{
_pptManager?.TryNavigateToSlide(page);
}).ShowDialog();
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"显示上次播放页通知失败: {ex}", LogHelper.LogType.Error);
}
}
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
private void CheckAndNotifyHiddenSlides(Presentation pres)
{
try
{
bool hasHiddenSlides = false;
if (pres?.Slides != null)
{
foreach (Slide slide in pres.Slides)
{
if (slide.SlideShowTransition.Hidden == MsoTriState.msoTrue)
{
hasHiddenSlides = true;
break;
2025-05-25 09:29:48 +08:00
}
2025-07-29 01:15:32 +08:00
}
}
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
if (hasHiddenSlides && !IsShowingRestoreHiddenSlidesWindow)
{
IsShowingRestoreHiddenSlidesWindow = true;
new YesOrNoNotificationWindow("检测到此演示文档中包含隐藏的幻灯片,是否取消隐藏?",
() =>
{
try
{
if (pres?.Slides != null)
{
foreach (Slide slide in pres.Slides)
{
if (slide.SlideShowTransition.Hidden == MsoTriState.msoTrue)
slide.SlideShowTransition.Hidden = MsoTriState.msoFalse;
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"取消隐藏幻灯片失败: {ex}", LogHelper.LogType.Error);
}
finally
{
IsShowingRestoreHiddenSlidesWindow = false;
}
},
() => { IsShowingRestoreHiddenSlidesWindow = false; },
() => { IsShowingRestoreHiddenSlidesWindow = false; }).ShowDialog();
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"检查隐藏幻灯片失败: {ex}", LogHelper.LogType.Error);
}
}
2025-07-28 18:23:07 +08:00
2025-07-29 01:15:32 +08:00
private void CheckAndNotifyAutoPlaySettings(Presentation pres)
{
try
{
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) return;
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
bool hasSlideTimings = false;
if (pres?.Slides != null)
{
foreach (Slide slide in pres.Slides)
{
if (slide.SlideShowTransition.AdvanceOnTime == MsoTriState.msoTrue &&
slide.SlideShowTransition.AdvanceTime > 0)
{
hasSlideTimings = true;
break;
}
2025-05-25 09:29:48 +08:00
}
2025-07-29 01:15:32 +08:00
}
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
if (hasSlideTimings && !IsShowingAutoplaySlidesWindow)
{
IsShowingAutoplaySlidesWindow = true;
new YesOrNoNotificationWindow("检测到此演示文档中自动播放或排练计时已经启用,可能导致幻灯片自动翻页,是否取消?",
() =>
{
try
{
if (pres != null)
{
pres.SlideShowSettings.AdvanceMode = PpSlideShowAdvanceMode.ppSlideShowManualAdvance;
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"设置手动播放模式失败: {ex}", LogHelper.LogType.Error);
}
finally
{
IsShowingAutoplaySlidesWindow = false;
}
},
() => { IsShowingAutoplaySlidesWindow = false; },
() => { IsShowingAutoplaySlidesWindow = false; }).ShowDialog();
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"检查自动播放设置失败: {ex}", LogHelper.LogType.Error);
}
}
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
private void LoadCurrentSlideInk(int slideIndex)
{
try
{
var strokes = _pptInkManager?.LoadSlideStrokes(slideIndex);
if (strokes != null)
{
inkCanvas.Strokes.Clear();
inkCanvas.Strokes.Add(strokes);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"加载当前页墨迹失败: {ex}", LogHelper.LogType.Error);
}
}
2025-07-20 12:36:21 +08:00
2025-07-29 01:15:32 +08:00
private void SwitchSlideInk(int newSlideIndex)
{
try
{
var newStrokes = _pptInkManager?.SwitchToSlide(newSlideIndex, inkCanvas.Strokes);
if (newStrokes != null)
2025-07-20 12:36:21 +08:00
{
2025-07-29 01:15:32 +08:00
inkCanvas.Strokes.Clear();
inkCanvas.Strokes.Add(newStrokes);
2025-07-20 12:36:21 +08:00
}
2025-07-29 01:15:32 +08:00
// 设置墨迹锁定
_pptInkManager?.LockInkForSlide(newSlideIndex);
2025-05-25 09:29:48 +08:00
}
2025-07-29 01:15:32 +08:00
catch (Exception ex)
{
LogHelper.WriteLogToFile($"切换页面墨迹失败: {ex}", LogHelper.LogType.Error);
2025-05-25 09:29:48 +08:00
}
}
2025-07-29 01:15:32 +08:00
private string GetFileHash(string filePath)
{
try
{
if (string.IsNullOrEmpty(filePath)) return "unknown";
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
using (var md5 = MD5.Create())
{
byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(filePath));
return BitConverter.ToString(hashBytes).Replace("-", "").Substring(0, 8);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"计算文件哈希值失败: {ex}", LogHelper.LogType.Error);
return "error";
}
}
#endregion
2025-07-21 21:02:23 +08:00
2025-07-29 01:15:32 +08:00
private void BtnCheckPPT_Click(object sender, RoutedEventArgs e) {
2025-05-25 09:29:48 +08:00
try {
2025-07-29 01:15:32 +08:00
// 使用新的PPT管理器进行连接检查
if (_pptManager == null)
2025-07-20 16:14:26 +08:00
{
2025-07-29 01:15:32 +08:00
InitializePPTManagers();
2025-07-20 16:14:26 +08:00
}
2025-07-29 01:15:32 +08:00
// 手动触发一次连接检查
_pptManager?.StartMonitoring();
// 等待一小段时间让连接建立
Task.Delay(500).ContinueWith(_ =>
{
Application.Current.Dispatcher.Invoke(() =>
{
if (_pptManager?.IsConnected == true)
{
LogHelper.WriteLogToFile("手动PPT连接检查成功", LogHelper.LogType.Event);
}
else
{
MessageBox.Show("未找到幻灯片");
LogHelper.WriteLogToFile("手动PPT连接检查失败", LogHelper.LogType.Warning);
}
});
2025-05-25 09:29:48 +08:00
});
}
catch (Exception ex) {
2025-07-29 01:15:32 +08:00
LogHelper.WriteLogToFile($"手动检查PPT应用程序失败: {ex}", LogHelper.LogType.Error);
_pptUIManager?.UpdateConnectionStatus(false);
MessageBox.Show("未找到幻灯片");
2025-05-25 09:29:48 +08:00
}
}
2025-07-29 01:15:32 +08:00
private void ToggleSwitchSupportWPS_Toggled(object sender, RoutedEventArgs e) {
if (!isLoaded) return;
Settings.PowerPointSettings.IsSupportWPS = ToggleSwitchSupportWPS.IsOn;
// 更新PPT管理器的WPS支持设置
if (_pptManager != null)
{
_pptManager.IsSupportWPS = Settings.PowerPointSettings.IsSupportWPS;
}
SaveSettingsToFile();
}
private static bool isWPSSupportOn => Settings.PowerPointSettings.IsSupportWPS;
public static bool IsShowingRestoreHiddenSlidesWindow;
private static bool IsShowingAutoplaySlidesWindow;
2025-05-25 09:29:48 +08:00
2025-06-12 18:55:50 +08:00
private void BtnPPTSlidesUp_Click(object sender, RoutedEventArgs e) {
2025-07-21 09:56:51 +08:00
Application.Current.Dispatcher.Invoke(() => {
2025-07-21 20:30:07 +08:00
try
2025-07-20 16:14:26 +08:00
{
2025-07-29 01:15:32 +08:00
_isPptClickingBtnTurned = true;
// 保存当前页墨迹
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
if (currentSlide > 0)
2025-07-20 16:14:26 +08:00
{
2025-07-29 01:15:32 +08:00
_pptInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
2025-05-25 09:29:48 +08:00
}
2025-07-29 01:15:32 +08:00
// 保存截图(如果启用)
if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint)
2025-07-21 20:30:07 +08:00
{
2025-07-29 01:15:32 +08:00
var presentationName = _pptManager?.GetPresentationName() ?? "";
SaveScreenShot(true, $"{presentationName}/{currentSlide}");
}
// 执行翻页
if (_pptManager?.TryNavigatePrevious() == true)
{
// 翻页成功,等待事件处理墨迹切换
LogHelper.WriteLogToFile("成功切换到上一页", LogHelper.LogType.Trace);
}
else
{
LogHelper.WriteLogToFile("切换到上一页失败", LogHelper.LogType.Warning);
_pptUIManager?.UpdateConnectionStatus(false);
2025-06-12 18:55:50 +08:00
}
2025-07-21 20:30:07 +08:00
}
catch (Exception ex) {
2025-07-28 14:40:44 +08:00
LogHelper.WriteLogToFile($"PPT上一页操作异常: {ex}", LogHelper.LogType.Error);
2025-07-29 01:15:32 +08:00
_pptUIManager?.UpdateConnectionStatus(false);
2025-07-21 20:30:07 +08:00
}
});
2025-05-25 09:29:48 +08:00
}
private void BtnPPTSlidesDown_Click(object sender, RoutedEventArgs e) {
2025-07-21 09:56:51 +08:00
Application.Current.Dispatcher.Invoke(() => {
2025-07-21 20:30:07 +08:00
try
2025-07-20 16:14:26 +08:00
{
2025-07-29 01:15:32 +08:00
_isPptClickingBtnTurned = true;
// 保存当前页墨迹
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
if (currentSlide > 0)
2025-07-20 16:14:26 +08:00
{
2025-07-29 01:15:32 +08:00
_pptInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
2025-06-12 18:55:50 +08:00
}
2025-07-29 01:15:32 +08:00
// 保存截图(如果启用)
if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint)
2025-07-21 20:30:07 +08:00
{
2025-07-29 01:15:32 +08:00
var presentationName = _pptManager?.GetPresentationName() ?? "";
SaveScreenShot(true, $"{presentationName}/{currentSlide}");
}
// 执行翻页
if (_pptManager?.TryNavigateNext() == true)
{
// 翻页成功,等待事件处理墨迹切换
LogHelper.WriteLogToFile("成功切换到下一页", LogHelper.LogType.Trace);
}
else
{
LogHelper.WriteLogToFile("切换到下一页失败", LogHelper.LogType.Warning);
_pptUIManager?.UpdateConnectionStatus(false);
2025-05-25 09:29:48 +08:00
}
2025-07-21 20:30:07 +08:00
}
catch (Exception ex) {
2025-07-28 14:40:44 +08:00
LogHelper.WriteLogToFile($"PPT下一页操作异常: {ex}", LogHelper.LogType.Error);
2025-07-29 01:15:32 +08:00
_pptUIManager?.UpdateConnectionStatus(false);
2025-07-21 20:30:07 +08:00
}
});
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
private async void PPTNavigationBtn_MouseDown(object sender, MouseButtonEventArgs e)
2025-05-25 09:29:48 +08:00
{
2025-06-12 18:55:50 +08:00
lastBorderMouseDownObject = sender;
if (!Settings.PowerPointSettings.EnablePPTButtonPageClickable) return;
if (sender == PPTLSPageButton)
2025-05-25 09:29:48 +08:00
{
2025-06-12 18:55:50 +08:00
PPTLSPageButtonFeedbackBorder.Opacity = 0.15;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
else if (sender == PPTRSPageButton)
2025-05-25 09:29:48 +08:00
{
2025-06-12 18:55:50 +08:00
PPTRSPageButtonFeedbackBorder.Opacity = 0.15;
}
else if (sender == PPTLBPageButton)
{
PPTLBPageButtonFeedbackBorder.Opacity = 0.15;
}
else if (sender == PPTRBPageButton)
{
PPTRBPageButtonFeedbackBorder.Opacity = 0.15;
2025-05-25 09:29:48 +08:00
}
}
2025-06-12 18:55:50 +08:00
private async void PPTNavigationBtn_MouseLeave(object sender, MouseEventArgs e)
2025-05-25 09:29:48 +08:00
{
2025-06-12 18:55:50 +08:00
lastBorderMouseDownObject = null;
if (sender == PPTLSPageButton)
2025-05-25 09:29:48 +08:00
{
2025-06-12 18:55:50 +08:00
PPTLSPageButtonFeedbackBorder.Opacity = 0;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
else if (sender == PPTRSPageButton)
2025-05-25 09:29:48 +08:00
{
2025-06-12 18:55:50 +08:00
PPTRSPageButtonFeedbackBorder.Opacity = 0;
}
else if (sender == PPTLBPageButton)
{
PPTLBPageButtonFeedbackBorder.Opacity = 0;
}
else if (sender == PPTRBPageButton)
{
PPTRBPageButtonFeedbackBorder.Opacity = 0;
2025-05-25 09:29:48 +08:00
}
}
private async void PPTNavigationBtn_MouseUp(object sender, MouseButtonEventArgs e) {
2025-06-12 18:55:50 +08:00
if (lastBorderMouseDownObject != sender) return;
2025-05-25 09:29:48 +08:00
2025-06-12 18:55:50 +08:00
if (sender == PPTLSPageButton)
{
PPTLSPageButtonFeedbackBorder.Opacity = 0;
}
else if (sender == PPTRSPageButton)
{
PPTRSPageButtonFeedbackBorder.Opacity = 0;
}
else if (sender == PPTLBPageButton)
{
PPTLBPageButtonFeedbackBorder.Opacity = 0;
}
else if (sender == PPTRBPageButton)
{
PPTRBPageButtonFeedbackBorder.Opacity = 0;
}
2025-05-25 09:29:48 +08:00
2025-06-12 18:55:50 +08:00
if (!Settings.PowerPointSettings.EnablePPTButtonPageClickable) return;
2025-05-25 09:29:48 +08:00
2025-07-29 01:15:32 +08:00
// 使用新的PPT管理器检查连接状态
if (_pptManager?.IsConnected != true || _pptManager?.IsInSlideShow != true)
2025-07-20 16:14:26 +08:00
{
2025-07-29 01:15:32 +08:00
LogHelper.WriteLogToFile("PPT未连接或未在放映状态,无法执行页码点击操作", LogHelper.LogType.Warning);
2025-07-20 16:14:26 +08:00
return;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
2025-07-20 16:14:26 +08:00
try
{
GridTransparencyFakeBackground.Opacity = 1;
GridTransparencyFakeBackground.Background = new SolidColorBrush(StringToColor("#01FFFFFF"));
CursorIcon_Click(null, null);
2025-07-29 01:15:32 +08:00
// 使用新的PPT管理器显示导航
if (_pptManager.TryShowSlideNavigation())
{
LogHelper.WriteLogToFile("成功显示PPT幻灯片导航", LogHelper.LogType.Trace);
2025-07-20 16:14:26 +08:00
}
2025-07-29 01:15:32 +08:00
else
{
LogHelper.WriteLogToFile("显示PPT幻灯片导航失败", LogHelper.LogType.Warning);
2025-07-20 16:14:26 +08:00
}
// 控制居中
if (!isFloatingBarFolded) {
await Task.Delay(100);
ViewboxFloatingBarMarginAnimation(60);
}
}
catch (Exception ex)
{
2025-07-28 14:40:44 +08:00
LogHelper.WriteLogToFile($"PPT翻页控件操作失败: {ex}", LogHelper.LogType.Error);
2025-05-25 09:29:48 +08:00
}
}
private void BtnPPTSlideShow_Click(object sender, RoutedEventArgs e) {
2025-07-28 14:40:44 +08:00
new Thread(() => {
2025-06-12 18:55:50 +08:00
try {
2025-07-29 01:15:32 +08:00
if (_pptManager?.TryStartSlideShow() != true)
{
LogHelper.WriteLogToFile("启动幻灯片放映失败", LogHelper.LogType.Warning);
}
}
catch (Exception ex) {
LogHelper.WriteLogToFile($"启动幻灯片放映异常: {ex}", LogHelper.LogType.Error);
2025-06-12 18:55:50 +08:00
}
2025-07-28 14:40:44 +08:00
}).Start();
2025-05-25 09:29:48 +08:00
}
2025-06-08 23:47:27 +08:00
private async void BtnPPTSlideShowEnd_Click(object sender, RoutedEventArgs e) {
2025-07-20 16:14:26 +08:00
try
{
2025-07-29 01:15:32 +08:00
// 保存当前页墨迹
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
if (currentSlide > 0)
2025-07-20 16:14:26 +08:00
{
2025-07-29 01:15:32 +08:00
Application.Current.Dispatcher.Invoke(() => {
_pptInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
timeMachine.ClearStrokeHistory();
});
2025-06-12 18:55:50 +08:00
}
2025-06-08 23:47:27 +08:00
2025-07-29 01:15:32 +08:00
// 结束放映
if (_pptManager?.TryEndSlideShow() == true)
{
LogHelper.WriteLogToFile("成功结束幻灯片放映", LogHelper.LogType.Event);
}
else
{
LogHelper.WriteLogToFile("结束幻灯片放映失败", LogHelper.LogType.Warning);
// 手动更新UI状态,防止事件未触发
await Application.Current.Dispatcher.InvokeAsync(() => {
_pptUIManager?.UpdateSlideShowStatus(false);
_pptUIManager?.UpdateSidebarExitButtons(false);
LogHelper.WriteLogToFile("手动更新放映结束UI状态", LogHelper.LogType.Trace);
});
}
2025-07-20 16:14:26 +08:00
HideSubPanels("cursor");
await Task.Delay(150);
ViewboxFloatingBarMarginAnimation(100, true);
}
catch (Exception ex)
{
2025-07-28 14:40:44 +08:00
LogHelper.WriteLogToFile($"结束PPT放映操作异常: {ex}", LogHelper.LogType.Error);
2025-07-29 01:15:32 +08:00
// 确保UI状态正确
await Application.Current.Dispatcher.InvokeAsync(() => {
_pptUIManager?.UpdateSlideShowStatus(false);
_pptUIManager?.UpdateSidebarExitButtons(false);
});
2025-07-20 16:14:26 +08:00
}
2025-05-25 09:29:48 +08:00
}
private void GridPPTControlPrevious_MouseDown(object sender, MouseButtonEventArgs e)
{
2025-06-12 18:55:50 +08:00
lastBorderMouseDownObject = sender;
if (sender == PPTLSPreviousButtonBorder) {
PPTLSPreviousButtonFeedbackBorder.Opacity = 0.15;
} else if (sender == PPTRSPreviousButtonBorder) {
PPTRSPreviousButtonFeedbackBorder.Opacity = 0.15;
} else if (sender == PPTLBPreviousButtonBorder)
{
PPTLBPreviousButtonFeedbackBorder.Opacity = 0.15;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
else if (sender == PPTRBPreviousButtonBorder)
{
PPTRBPreviousButtonFeedbackBorder.Opacity = 0.15;
2025-05-25 09:29:48 +08:00
}
}
private void GridPPTControlPrevious_MouseLeave(object sender, MouseEventArgs e)
{
2025-06-12 18:55:50 +08:00
lastBorderMouseDownObject = null;
if (sender == PPTLSPreviousButtonBorder) {
PPTLSPreviousButtonFeedbackBorder.Opacity = 0;
} else if (sender == PPTRSPreviousButtonBorder) {
PPTRSPreviousButtonFeedbackBorder.Opacity = 0;
} else if (sender == PPTLBPreviousButtonBorder)
{
PPTLBPreviousButtonFeedbackBorder.Opacity = 0;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
else if (sender == PPTRBPreviousButtonBorder)
{
PPTRBPreviousButtonFeedbackBorder.Opacity = 0;
2025-05-25 09:29:48 +08:00
}
}
private void GridPPTControlPrevious_MouseUp(object sender, MouseButtonEventArgs e) {
2025-06-12 18:55:50 +08:00
if (lastBorderMouseDownObject != sender) return;
if (sender == PPTLSPreviousButtonBorder) {
PPTLSPreviousButtonFeedbackBorder.Opacity = 0;
} else if (sender == PPTRSPreviousButtonBorder) {
PPTRSPreviousButtonFeedbackBorder.Opacity = 0;
} else if (sender == PPTLBPreviousButtonBorder)
{
PPTLBPreviousButtonFeedbackBorder.Opacity = 0;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
else if (sender == PPTRBPreviousButtonBorder)
{
PPTRBPreviousButtonFeedbackBorder.Opacity = 0;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
BtnPPTSlidesUp_Click(BtnPPTSlidesUp, null);
2025-05-25 09:29:48 +08:00
}
private void GridPPTControlNext_MouseDown(object sender, MouseButtonEventArgs e) {
2025-06-12 18:55:50 +08:00
lastBorderMouseDownObject = sender;
if (sender == PPTLSNextButtonBorder) {
PPTLSNextButtonFeedbackBorder.Opacity = 0.15;
} else if (sender == PPTRSNextButtonBorder) {
PPTRSNextButtonFeedbackBorder.Opacity = 0.15;
} else if (sender == PPTLBNextButtonBorder)
{
PPTLBNextButtonFeedbackBorder.Opacity = 0.15;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
else if (sender == PPTRBNextButtonBorder)
{
PPTRBNextButtonFeedbackBorder.Opacity = 0.15;
2025-05-25 09:29:48 +08:00
}
}
private void GridPPTControlNext_MouseLeave(object sender, MouseEventArgs e)
{
2025-06-12 18:55:50 +08:00
lastBorderMouseDownObject = null;
if (sender == PPTLSNextButtonBorder) {
PPTLSNextButtonFeedbackBorder.Opacity = 0;
} else if (sender == PPTRSNextButtonBorder) {
PPTRSNextButtonFeedbackBorder.Opacity = 0;
} else if (sender == PPTLBNextButtonBorder)
{
PPTLBNextButtonFeedbackBorder.Opacity = 0;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
else if (sender == PPTRBNextButtonBorder)
{
PPTRBNextButtonFeedbackBorder.Opacity = 0;
2025-05-25 09:29:48 +08:00
}
}
private void GridPPTControlNext_MouseUp(object sender, MouseButtonEventArgs e) {
2025-06-12 18:55:50 +08:00
if (lastBorderMouseDownObject != sender) return;
if (sender == PPTLSNextButtonBorder) {
PPTLSNextButtonFeedbackBorder.Opacity = 0;
} else if (sender == PPTRSNextButtonBorder) {
PPTRSNextButtonFeedbackBorder.Opacity = 0;
} else if (sender == PPTLBNextButtonBorder)
{
PPTLBNextButtonFeedbackBorder.Opacity = 0;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
else if (sender == PPTRBNextButtonBorder)
{
PPTRBNextButtonFeedbackBorder.Opacity = 0;
2025-05-25 09:29:48 +08:00
}
2025-06-12 18:55:50 +08:00
BtnPPTSlidesDown_Click(BtnPPTSlidesDown, null);
2025-05-25 09:29:48 +08:00
}
private void ImagePPTControlEnd_MouseUp(object sender, MouseButtonEventArgs e) {
2025-06-12 18:55:50 +08:00
BtnPPTSlideShowEnd_Click(BtnPPTSlideShowEnd, null);
2025-06-10 11:09:51 +08:00
}
2025-07-20 12:36:21 +08:00
2025-07-21 08:43:16 +08:00
2025-07-21 08:37:37 +08:00
2025-07-20 15:00:11 +08:00
2025-07-21 08:37:37 +08:00
2025-07-20 15:00:11 +08:00
2025-07-20 18:27:08 +08:00
2025-07-21 09:56:51 +08:00
2025-07-21 21:02:23 +08:00
2025-05-25 09:29:48 +08:00
}
2025-07-12 09:09:20 +08:00
}