1068 lines
40 KiB
C#
1068 lines
40 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
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;
|
|
using Ink_Canvas.Helpers;
|
|
using iNKORE.UI.WPF.Modern;
|
|
using Microsoft.Office.Core;
|
|
using Microsoft.Office.Interop.PowerPoint;
|
|
using Application = System.Windows.Application;
|
|
using File = System.IO.File;
|
|
using MessageBox = System.Windows.MessageBox;
|
|
using MouseButtonEventArgs = System.Windows.Input.MouseButtonEventArgs;
|
|
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
|
|
|
|
namespace Ink_Canvas {
|
|
public partial class MainWindow : Window {
|
|
#region Win32 API Declarations
|
|
[DllImport("user32.dll")]
|
|
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
|
|
|
|
[DllImport("user32.dll")]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
private static extern bool IsWindowVisible(IntPtr hWnd);
|
|
|
|
[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)]
|
|
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
|
|
|
|
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;
|
|
|
|
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
|
|
#endregion
|
|
|
|
#region PPT Application Variables
|
|
public static Microsoft.Office.Interop.PowerPoint.Application pptApplication;
|
|
public static Presentation presentation;
|
|
public static Slides slides;
|
|
public static Slide slide;
|
|
public static int slidescount;
|
|
#endregion
|
|
|
|
#region PPT State Management
|
|
private bool wasFloatingBarFoldedWhenEnterSlideShow;
|
|
private static bool hasShownWpsForceCloseWarning = false;
|
|
private bool isEnteredSlideShowEndEvent; //防止重复调用本函数导致墨迹保存失效
|
|
private bool isPresentationHaveBlackSpace;
|
|
private string pptName;
|
|
private bool _isPptClickingBtnTurned;
|
|
#endregion
|
|
|
|
#region PPT Managers
|
|
private PPTManager _pptManager;
|
|
private PPTInkManager _pptInkManager;
|
|
private PPTUIManager _pptUIManager;
|
|
#endregion
|
|
|
|
#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);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"PPT管理器初始化失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
|
|
private void StartPPTMonitoring()
|
|
{
|
|
if (Settings.PowerPointSettings.PowerPointSupport)
|
|
{
|
|
_pptManager?.StartMonitoring();
|
|
LogHelper.WriteLogToFile("PPT监控已启动", LogHelper.LogType.Event);
|
|
}
|
|
}
|
|
|
|
private void StopPPTMonitoring()
|
|
{
|
|
_pptManager?.StopMonitoring();
|
|
LogHelper.WriteLogToFile("PPT监控已停止", LogHelper.LogType.Event);
|
|
}
|
|
|
|
private void DisposePPTManagers()
|
|
{
|
|
try
|
|
{
|
|
_pptManager?.Dispose();
|
|
_pptInkManager?.Dispose();
|
|
_pptManager = null;
|
|
_pptInkManager = null;
|
|
_pptUIManager = null;
|
|
LogHelper.WriteLogToFile("PPT管理器已释放", LogHelper.LogType.Event);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"释放PPT管理器失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region New PPT Event Handlers
|
|
private void OnPPTConnectionChanged(bool isConnected)
|
|
{
|
|
try
|
|
{
|
|
Application.Current.Dispatcher.InvokeAsync(() =>
|
|
{
|
|
_pptUIManager?.UpdateConnectionStatus(isConnected);
|
|
|
|
if (isConnected)
|
|
{
|
|
LogHelper.WriteLogToFile("PPT连接已建立", LogHelper.LogType.Event);
|
|
}
|
|
else
|
|
{
|
|
LogHelper.WriteLogToFile("PPT连接已断开", LogHelper.LogType.Event);
|
|
// 清理墨迹管理器
|
|
_pptInkManager?.ClearAllStrokes();
|
|
}
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"处理PPT连接状态变化失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
|
|
private void OnPPTPresentationOpen(Presentation pres)
|
|
{
|
|
try
|
|
{
|
|
Application.Current.Dispatcher.InvokeAsync(() =>
|
|
{
|
|
// 初始化墨迹管理器
|
|
_pptInkManager?.InitializePresentation(pres);
|
|
|
|
// 处理跳转到首页或上次播放页的逻辑
|
|
HandlePresentationOpenNavigation(pres);
|
|
|
|
// 检查隐藏幻灯片
|
|
if (Settings.PowerPointSettings.IsNotifyHiddenPage)
|
|
{
|
|
CheckAndNotifyHiddenSlides(pres);
|
|
}
|
|
|
|
// 检查自动播放设置
|
|
if (Settings.PowerPointSettings.IsNotifyAutoPlayPresentation)
|
|
{
|
|
CheckAndNotifyAutoPlaySettings(pres);
|
|
}
|
|
|
|
_pptUIManager?.UpdateConnectionStatus(true);
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"处理演示文稿打开事件失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
|
|
private void OnPPTPresentationClose(Presentation pres)
|
|
{
|
|
try
|
|
{
|
|
Application.Current.Dispatcher.InvokeAsync(() =>
|
|
{
|
|
// 保存所有墨迹
|
|
_pptInkManager?.SaveAllStrokesToFile(pres);
|
|
|
|
// 清理墨迹管理器
|
|
_pptInkManager?.ClearAllStrokes();
|
|
|
|
_pptUIManager?.UpdateConnectionStatus(false);
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"处理演示文稿关闭事件失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
|
|
private async void OnPPTSlideShowBegin(SlideShowWindow wn)
|
|
{
|
|
try
|
|
{
|
|
// 记录进入放映时浮动栏收纳状态
|
|
wasFloatingBarFoldedWhenEnterSlideShow = isFloatingBarFolded;
|
|
|
|
if (Settings.Automation.IsAutoFoldInPPTSlideShow && !isFloatingBarFolded)
|
|
FoldFloatingBar_MouseUp(new object(), null);
|
|
else if (isFloatingBarFolded)
|
|
await UnFoldFloatingBar(new object());
|
|
|
|
isStopInkReplay = true;
|
|
|
|
await Application.Current.Dispatcher.InvokeAsync(() =>
|
|
{
|
|
// 处理跳转到首页
|
|
if (Settings.PowerPointSettings.IsAlwaysGoToFirstPageOnReenter)
|
|
{
|
|
_pptManager?.TryNavigateToSlide(1);
|
|
}
|
|
|
|
// 更新UI状态
|
|
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
|
|
var totalSlides = _pptManager?.SlidesCount ?? 0;
|
|
_pptUIManager?.UpdateSlideShowStatus(true, currentSlide, totalSlides);
|
|
|
|
// 设置浮动栏透明度和边距
|
|
_pptUIManager?.SetFloatingBarOpacity(Settings.Appearance.ViewboxFloatingBarOpacityInPPTValue);
|
|
_pptUIManager?.SetMainPanelMargin(new Thickness(10, 10, 10, 10));
|
|
|
|
// 显示侧边栏退出按钮
|
|
_pptUIManager?.UpdateSidebarExitButtons(true);
|
|
|
|
// 处理画板显示
|
|
if (Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow &&
|
|
!Settings.Automation.IsAutoFoldInPPTSlideShow &&
|
|
GridTransparencyFakeBackground.Background == Brushes.Transparent && !isFloatingBarFolded)
|
|
{
|
|
BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
|
|
}
|
|
|
|
if (currentMode != 0)
|
|
{
|
|
ImageBlackboard_MouseUp(null, null);
|
|
BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
|
|
}
|
|
|
|
BorderFloatingBarMainControls.Visibility = Visibility.Visible;
|
|
|
|
if (Settings.PowerPointSettings.IsShowCanvasAtNewSlideShow &&
|
|
!Settings.Automation.IsAutoFoldInPPTSlideShow)
|
|
BtnColorRed_Click(null, null);
|
|
|
|
isEnteredSlideShowEndEvent = false;
|
|
|
|
// 加载当前页墨迹
|
|
LoadCurrentSlideInk(currentSlide);
|
|
});
|
|
|
|
if (!isFloatingBarFolded)
|
|
{
|
|
new Thread(() =>
|
|
{
|
|
Thread.Sleep(100);
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
ViewboxFloatingBarMarginAnimation(60);
|
|
});
|
|
}).Start();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"处理幻灯片放映开始事件失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
|
|
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);
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"处理幻灯片切换事件失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
|
|
private async void OnPPTSlideShowEnd(Presentation pres)
|
|
{
|
|
try
|
|
{
|
|
// 处理浮动栏状态
|
|
if (Settings.Automation.IsAutoFoldAfterPPTSlideShow && wasFloatingBarFoldedWhenEnterSlideShow)
|
|
{
|
|
if (!isFloatingBarFolded) FoldFloatingBar_MouseUp(new object(), null);
|
|
}
|
|
else
|
|
{
|
|
if (isFloatingBarFolded) await UnFoldFloatingBar(new object());
|
|
}
|
|
|
|
if (isEnteredSlideShowEndEvent) return;
|
|
isEnteredSlideShowEndEvent = true;
|
|
|
|
// 保存所有墨迹
|
|
_pptInkManager?.SaveAllStrokesToFile(pres);
|
|
|
|
await Application.Current.Dispatcher.InvokeAsync(() =>
|
|
{
|
|
try
|
|
{
|
|
isPresentationHaveBlackSpace = false;
|
|
|
|
// 恢复主题
|
|
if (BtnSwitchTheme.Content.ToString() == "深色")
|
|
{
|
|
BtnExit.Foreground = Brushes.Black;
|
|
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
|
|
}
|
|
|
|
// 更新UI状态
|
|
_pptUIManager?.UpdateSlideShowStatus(false);
|
|
_pptUIManager?.UpdateSidebarExitButtons(false);
|
|
_pptUIManager?.SetMainPanelMargin(new Thickness(10, 10, 10, 55));
|
|
_pptUIManager?.SetFloatingBarOpacity(Settings.Appearance.ViewboxFloatingBarOpacityValue);
|
|
|
|
if (currentMode != 0)
|
|
{
|
|
CloseWhiteboardImmediately();
|
|
currentMode = 0;
|
|
}
|
|
|
|
ClearStrokes(true);
|
|
// 清空备份历史记录,防止退出白板时恢复已结束PPT的墨迹
|
|
// 注意:这里只清空索引0的备份,不影响白板页面的墨迹(索引1及以上)
|
|
TimeMachineHistories[0] = null;
|
|
|
|
if (GridTransparencyFakeBackground.Background != Brushes.Transparent)
|
|
BtnHideInkCanvas_Click(BtnHideInkCanvas, null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"处理幻灯片放映结束UI更新失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
});
|
|
|
|
await Task.Delay(150);
|
|
await Application.Current.Dispatcher.InvokeAsync(() =>
|
|
{
|
|
ViewboxFloatingBarMarginAnimation(100, true);
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"处理幻灯片放映结束事件失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Helper Methods
|
|
private void HandlePresentationOpenNavigation(Presentation pres)
|
|
{
|
|
try
|
|
{
|
|
if (Settings.PowerPointSettings.IsAlwaysGoToFirstPageOnReenter)
|
|
{
|
|
_pptManager?.TryNavigateToSlide(1);
|
|
}
|
|
else if (Settings.PowerPointSettings.IsNotifyPreviousPage)
|
|
{
|
|
ShowPreviousPageNotification(pres);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"处理演示文稿导航失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
|
|
private void ShowPreviousPageNotification(Presentation pres)
|
|
{
|
|
try
|
|
{
|
|
if (pres == null) return;
|
|
|
|
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");
|
|
|
|
if (!File.Exists(positionFile)) return;
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
private void CheckAndNotifyAutoPlaySettings(Presentation pres)
|
|
{
|
|
try
|
|
{
|
|
if (BtnPPTSlideShowEnd.Visibility == Visibility.Visible) return;
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
private void SwitchSlideInk(int newSlideIndex)
|
|
{
|
|
try
|
|
{
|
|
var newStrokes = _pptInkManager?.SwitchToSlide(newSlideIndex, inkCanvas.Strokes);
|
|
if (newStrokes != null)
|
|
{
|
|
inkCanvas.Strokes.Clear();
|
|
inkCanvas.Strokes.Add(newStrokes);
|
|
}
|
|
|
|
// 设置墨迹锁定
|
|
_pptInkManager?.LockInkForSlide(newSlideIndex);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"切换页面墨迹失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
|
|
private string GetFileHash(string filePath)
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrEmpty(filePath)) return "unknown";
|
|
|
|
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
|
|
|
|
private void BtnCheckPPT_Click(object sender, RoutedEventArgs e) {
|
|
try {
|
|
// 使用新的PPT管理器进行连接检查
|
|
if (_pptManager == null)
|
|
{
|
|
InitializePPTManagers();
|
|
}
|
|
|
|
// 手动触发一次连接检查
|
|
_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);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
catch (Exception ex) {
|
|
LogHelper.WriteLogToFile($"手动检查PPT应用程序失败: {ex}", LogHelper.LogType.Error);
|
|
_pptUIManager?.UpdateConnectionStatus(false);
|
|
MessageBox.Show("未找到幻灯片");
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void BtnPPTSlidesUp_Click(object sender, RoutedEventArgs e) {
|
|
Application.Current.Dispatcher.Invoke(() => {
|
|
try
|
|
{
|
|
_isPptClickingBtnTurned = true;
|
|
|
|
// 保存当前页墨迹
|
|
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
|
|
if (currentSlide > 0)
|
|
{
|
|
_pptInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
|
}
|
|
|
|
// 保存截图(如果启用)
|
|
if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
|
|
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
catch (Exception ex) {
|
|
LogHelper.WriteLogToFile($"PPT上一页操作异常: {ex}", LogHelper.LogType.Error);
|
|
_pptUIManager?.UpdateConnectionStatus(false);
|
|
}
|
|
});
|
|
}
|
|
|
|
private void BtnPPTSlidesDown_Click(object sender, RoutedEventArgs e) {
|
|
Application.Current.Dispatcher.Invoke(() => {
|
|
try
|
|
{
|
|
_isPptClickingBtnTurned = true;
|
|
|
|
// 保存当前页墨迹
|
|
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
|
|
if (currentSlide > 0)
|
|
{
|
|
_pptInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
|
}
|
|
|
|
// 保存截图(如果启用)
|
|
if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
|
|
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
catch (Exception ex) {
|
|
LogHelper.WriteLogToFile($"PPT下一页操作异常: {ex}", LogHelper.LogType.Error);
|
|
_pptUIManager?.UpdateConnectionStatus(false);
|
|
}
|
|
});
|
|
}
|
|
|
|
private async void PPTNavigationBtn_MouseDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
lastBorderMouseDownObject = sender;
|
|
if (!Settings.PowerPointSettings.EnablePPTButtonPageClickable) return;
|
|
if (sender == PPTLSPageButton)
|
|
{
|
|
PPTLSPageButtonFeedbackBorder.Opacity = 0.15;
|
|
}
|
|
else if (sender == PPTRSPageButton)
|
|
{
|
|
PPTRSPageButtonFeedbackBorder.Opacity = 0.15;
|
|
}
|
|
else if (sender == PPTLBPageButton)
|
|
{
|
|
PPTLBPageButtonFeedbackBorder.Opacity = 0.15;
|
|
}
|
|
else if (sender == PPTRBPageButton)
|
|
{
|
|
PPTRBPageButtonFeedbackBorder.Opacity = 0.15;
|
|
}
|
|
}
|
|
|
|
private async void PPTNavigationBtn_MouseLeave(object sender, MouseEventArgs e)
|
|
{
|
|
lastBorderMouseDownObject = null;
|
|
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;
|
|
}
|
|
}
|
|
|
|
private async void PPTNavigationBtn_MouseUp(object sender, MouseButtonEventArgs e) {
|
|
if (lastBorderMouseDownObject != sender) return;
|
|
|
|
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;
|
|
}
|
|
|
|
if (!Settings.PowerPointSettings.EnablePPTButtonPageClickable) return;
|
|
|
|
// 使用新的PPT管理器检查连接状态
|
|
if (_pptManager?.IsConnected != true || _pptManager?.IsInSlideShow != true)
|
|
{
|
|
LogHelper.WriteLogToFile("PPT未连接或未在放映状态,无法执行页码点击操作", LogHelper.LogType.Warning);
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
GridTransparencyFakeBackground.Opacity = 1;
|
|
GridTransparencyFakeBackground.Background = new SolidColorBrush(StringToColor("#01FFFFFF"));
|
|
CursorIcon_Click(null, null);
|
|
|
|
// 使用新的PPT管理器显示导航
|
|
if (_pptManager.TryShowSlideNavigation())
|
|
{
|
|
LogHelper.WriteLogToFile("成功显示PPT幻灯片导航", LogHelper.LogType.Trace);
|
|
}
|
|
else
|
|
{
|
|
LogHelper.WriteLogToFile("显示PPT幻灯片导航失败", LogHelper.LogType.Warning);
|
|
}
|
|
|
|
// 控制居中
|
|
if (!isFloatingBarFolded) {
|
|
await Task.Delay(100);
|
|
ViewboxFloatingBarMarginAnimation(60);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"PPT翻页控件操作失败: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}
|
|
|
|
private void BtnPPTSlideShow_Click(object sender, RoutedEventArgs e) {
|
|
new Thread(() => {
|
|
try {
|
|
if (_pptManager?.TryStartSlideShow() != true)
|
|
{
|
|
LogHelper.WriteLogToFile("启动幻灯片放映失败", LogHelper.LogType.Warning);
|
|
}
|
|
}
|
|
catch (Exception ex) {
|
|
LogHelper.WriteLogToFile($"启动幻灯片放映异常: {ex}", LogHelper.LogType.Error);
|
|
}
|
|
}).Start();
|
|
}
|
|
|
|
private async void BtnPPTSlideShowEnd_Click(object sender, RoutedEventArgs e) {
|
|
try
|
|
{
|
|
// 保存当前页墨迹
|
|
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
|
|
if (currentSlide > 0)
|
|
{
|
|
Application.Current.Dispatcher.Invoke(() => {
|
|
_pptInkManager?.SaveCurrentSlideStrokes(currentSlide, inkCanvas.Strokes);
|
|
timeMachine.ClearStrokeHistory();
|
|
});
|
|
}
|
|
|
|
// 结束放映
|
|
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);
|
|
});
|
|
}
|
|
|
|
HideSubPanels("cursor");
|
|
await Task.Delay(150);
|
|
ViewboxFloatingBarMarginAnimation(100, true);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogHelper.WriteLogToFile($"结束PPT放映操作异常: {ex}", LogHelper.LogType.Error);
|
|
|
|
// 确保UI状态正确
|
|
await Application.Current.Dispatcher.InvokeAsync(() => {
|
|
_pptUIManager?.UpdateSlideShowStatus(false);
|
|
_pptUIManager?.UpdateSidebarExitButtons(false);
|
|
});
|
|
}
|
|
}
|
|
|
|
private void GridPPTControlPrevious_MouseDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
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;
|
|
}
|
|
else if (sender == PPTRBPreviousButtonBorder)
|
|
{
|
|
PPTRBPreviousButtonFeedbackBorder.Opacity = 0.15;
|
|
}
|
|
}
|
|
private void GridPPTControlPrevious_MouseLeave(object sender, MouseEventArgs e)
|
|
{
|
|
lastBorderMouseDownObject = null;
|
|
if (sender == PPTLSPreviousButtonBorder) {
|
|
PPTLSPreviousButtonFeedbackBorder.Opacity = 0;
|
|
} else if (sender == PPTRSPreviousButtonBorder) {
|
|
PPTRSPreviousButtonFeedbackBorder.Opacity = 0;
|
|
} else if (sender == PPTLBPreviousButtonBorder)
|
|
{
|
|
PPTLBPreviousButtonFeedbackBorder.Opacity = 0;
|
|
}
|
|
else if (sender == PPTRBPreviousButtonBorder)
|
|
{
|
|
PPTRBPreviousButtonFeedbackBorder.Opacity = 0;
|
|
}
|
|
}
|
|
private void GridPPTControlPrevious_MouseUp(object sender, MouseButtonEventArgs e) {
|
|
if (lastBorderMouseDownObject != sender) return;
|
|
if (sender == PPTLSPreviousButtonBorder) {
|
|
PPTLSPreviousButtonFeedbackBorder.Opacity = 0;
|
|
} else if (sender == PPTRSPreviousButtonBorder) {
|
|
PPTRSPreviousButtonFeedbackBorder.Opacity = 0;
|
|
} else if (sender == PPTLBPreviousButtonBorder)
|
|
{
|
|
PPTLBPreviousButtonFeedbackBorder.Opacity = 0;
|
|
}
|
|
else if (sender == PPTRBPreviousButtonBorder)
|
|
{
|
|
PPTRBPreviousButtonFeedbackBorder.Opacity = 0;
|
|
}
|
|
BtnPPTSlidesUp_Click(BtnPPTSlidesUp, null);
|
|
}
|
|
|
|
|
|
private void GridPPTControlNext_MouseDown(object sender, MouseButtonEventArgs e) {
|
|
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;
|
|
}
|
|
else if (sender == PPTRBNextButtonBorder)
|
|
{
|
|
PPTRBNextButtonFeedbackBorder.Opacity = 0.15;
|
|
}
|
|
}
|
|
private void GridPPTControlNext_MouseLeave(object sender, MouseEventArgs e)
|
|
{
|
|
lastBorderMouseDownObject = null;
|
|
if (sender == PPTLSNextButtonBorder) {
|
|
PPTLSNextButtonFeedbackBorder.Opacity = 0;
|
|
} else if (sender == PPTRSNextButtonBorder) {
|
|
PPTRSNextButtonFeedbackBorder.Opacity = 0;
|
|
} else if (sender == PPTLBNextButtonBorder)
|
|
{
|
|
PPTLBNextButtonFeedbackBorder.Opacity = 0;
|
|
}
|
|
else if (sender == PPTRBNextButtonBorder)
|
|
{
|
|
PPTRBNextButtonFeedbackBorder.Opacity = 0;
|
|
}
|
|
}
|
|
private void GridPPTControlNext_MouseUp(object sender, MouseButtonEventArgs e) {
|
|
if (lastBorderMouseDownObject != sender) return;
|
|
if (sender == PPTLSNextButtonBorder) {
|
|
PPTLSNextButtonFeedbackBorder.Opacity = 0;
|
|
} else if (sender == PPTRSNextButtonBorder) {
|
|
PPTRSNextButtonFeedbackBorder.Opacity = 0;
|
|
} else if (sender == PPTLBNextButtonBorder)
|
|
{
|
|
PPTLBNextButtonFeedbackBorder.Opacity = 0;
|
|
}
|
|
else if (sender == PPTRBNextButtonBorder)
|
|
{
|
|
PPTRBNextButtonFeedbackBorder.Opacity = 0;
|
|
}
|
|
BtnPPTSlidesDown_Click(BtnPPTSlidesDown, null);
|
|
}
|
|
|
|
private void ImagePPTControlEnd_MouseUp(object sender, MouseButtonEventArgs e) {
|
|
BtnPPTSlideShowEnd_Click(BtnPPTSlideShowEnd, null);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|