From 17c020284d231ca7776d56790fe3385a809bed8e Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sun, 22 Feb 2026 17:52:33 +0800 Subject: [PATCH] =?UTF-8?q?improve:PPT=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/PPTManager.cs | 148 +++++++++++++---------------- Ink Canvas/MainWindow_cs/MW_PPT.cs | 100 ++++++++++--------- 2 files changed, 119 insertions(+), 129 deletions(-) diff --git a/Ink Canvas/Helpers/PPTManager.cs b/Ink Canvas/Helpers/PPTManager.cs index 1111a747..6579551f 100644 --- a/Ink Canvas/Helpers/PPTManager.cs +++ b/Ink Canvas/Helpers/PPTManager.cs @@ -38,89 +38,11 @@ namespace Ink_Canvas.Helpers { get { - try - { - if (PPTApplication == null) return false; - if (!Marshal.IsComObject(PPTApplication)) return false; - - // 尝试访问一个简单的属性来验证连接是否有效 - var _ = PPTApplication.Name; - return true; - } - catch (COMException comEx) - { - var hr = (uint)comEx.HResult; - // 如果COM对象已失效,返回false - if (hr == 0x8001010E || hr == 0x80004005 || hr == 0x800706B5) - { - return false; - } - return false; - } - catch - { - return false; - } - } - } - public bool IsInSlideShow - { - get - { - object slideShowWindows = null; - object slideShowWindow = null; - object view = null; - try - { - if (PPTApplication == null || !Marshal.IsComObject(PPTApplication)) return false; - - slideShowWindows = PPTApplication.SlideShowWindows; - if (slideShowWindows == null) return false; - - dynamic ssw = slideShowWindows; - if (ssw.Count == 0) return false; - - try - { - slideShowWindow = ssw[1]; - if (slideShowWindow == null) return false; - - dynamic sswObj = slideShowWindow; - view = sswObj.View; - if (view == null) return false; - - return true; - } - catch (COMException comEx) - { - var hr = (uint)comEx.HResult; - if (!IsPptBusyHResult(hr) && (hr == 0x8001010E || hr == 0x80004005)) - DisconnectFromPPT(); - return false; - } - } - catch (COMException comEx) - { - var hr = (uint)comEx.HResult; - if (!IsPptBusyHResult(hr) && (hr == 0x8001010E || hr == 0x80004005)) - DisconnectFromPPT(); - if (!IsPptBusyHResult(hr)) - LogHelper.WriteLogToFile($"检查PPT放映状态失败: {comEx.Message} (HR: 0x{hr:X8})", LogHelper.LogType.Warning); - return false; - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"检查PPT放映状态时发生意外错误: {ex}", LogHelper.LogType.Warning); - return false; - } - finally - { - SafeReleaseComObject(view); - SafeReleaseComObject(slideShowWindow); - SafeReleaseComObject(slideShowWindows); - } + if (PPTApplication == null) return false; + return _cachedIsConnected; } } + public bool IsInSlideShow => _cachedIsInSlideShow; public bool IsSupportWPS { get; set; } = false; public bool SkipAnimationsWhenNavigating { get; set; } = false; @@ -140,6 +62,8 @@ namespace Ink_Canvas.Helpers private WpsWindowInfo _lastForegroundWpsWindow; private DateTime _lastWindowCheckTime = DateTime.MinValue; private bool _lastSlideShowState; + private volatile bool _cachedIsConnected; + private volatile bool _cachedIsInSlideShow; private readonly object _lockObject = new object(); private bool _disposed; private static bool IsPptBusyHResult(uint hr) => hr == 0x80010001 || hr == 0x8001010A; @@ -259,13 +183,64 @@ namespace Ink_Canvas.Helpers } } + private bool RefreshIsInSlideShowFromCom() + { + object slideShowWindows = null; + object slideShowWindow = null; + object view = null; + try + { + if (PPTApplication == null) { _cachedIsInSlideShow = false; return false; } + if (!Marshal.IsComObject(PPTApplication)) { _cachedIsInSlideShow = false; return false; } + + slideShowWindows = PPTApplication.SlideShowWindows; + if (slideShowWindows == null) { _cachedIsInSlideShow = false; return false; } + + dynamic ssw = slideShowWindows; + if (ssw.Count == 0) { _cachedIsInSlideShow = false; return false; } + + slideShowWindow = ssw[1]; + if (slideShowWindow == null) { _cachedIsInSlideShow = false; return false; } + + dynamic sswObj = slideShowWindow; + view = sswObj.View; + if (view == null) { _cachedIsInSlideShow = false; return false; } + + _cachedIsInSlideShow = true; + return true; + } + catch (COMException comEx) + { + var hr = (uint)comEx.HResult; + _cachedIsInSlideShow = false; + if (!IsPptBusyHResult(hr) && (hr == 0x8001010E || hr == 0x80004005 || hr == 0x800706B5)) + { + _cachedIsConnected = false; + DisconnectFromPPT(); + } + return false; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"检查PPT放映状态时发生意外错误: {ex}", LogHelper.LogType.Warning); + _cachedIsInSlideShow = false; + return false; + } + finally + { + SafeReleaseComObject(view); + SafeReleaseComObject(slideShowWindow); + SafeReleaseComObject(slideShowWindows); + } + } + private void CheckSlideShowState() { try { if (!IsConnected) return; - var currentSlideShowState = IsInSlideShow; + var currentSlideShowState = RefreshIsInSlideShowFromCom(); if (currentSlideShowState != _lastSlideShowState) { _lastSlideShowState = currentSlideShowState; @@ -341,6 +316,7 @@ namespace Ink_Canvas.Helpers try { PPTApplication = pptApp; + _cachedIsConnected = true; // 在主线程中注册事件,确保COM对象在正确的线程中 Application.Current?.Dispatcher?.Invoke(() => @@ -370,7 +346,8 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile("成功连接到PPT应用程序", LogHelper.LogType.Event); - if (IsInSlideShow) + RefreshIsInSlideShowFromCom(); + if (_cachedIsInSlideShow) { OnSlideShowBegin(PPTApplication.SlideShowWindows[1]); } @@ -382,6 +359,7 @@ namespace Ink_Canvas.Helpers catch (Exception ex) { LogHelper.WriteLogToFile($"连接PPT应用程序失败: {ex}", LogHelper.LogType.Error); + _cachedIsConnected = false; PPTApplication = null; } } @@ -456,6 +434,8 @@ namespace Ink_Canvas.Helpers } } + _cachedIsConnected = false; + _cachedIsInSlideShow = false; PPTApplication = null; CurrentPresentation = null; CurrentSlides = null; @@ -734,6 +714,7 @@ namespace Ink_Canvas.Helpers private void OnSlideShowBegin(SlideShowWindow wn) { + _cachedIsInSlideShow = true; try { UpdateCurrentPresentationInfo(); @@ -760,6 +741,7 @@ namespace Ink_Canvas.Helpers private void OnSlideShowEnd(Presentation pres) { + _cachedIsInSlideShow = false; try { // 记录WPS进程用于后续管理 diff --git a/Ink Canvas/MainWindow_cs/MW_PPT.cs b/Ink Canvas/MainWindow_cs/MW_PPT.cs index 7e6e5759..207983b8 100644 --- a/Ink Canvas/MainWindow_cs/MW_PPT.cs +++ b/Ink Canvas/MainWindow_cs/MW_PPT.cs @@ -1927,38 +1927,45 @@ namespace Ink_Canvas /// 路由事件参数。 private void BtnPPTSlidesUp_Click(object sender, RoutedEventArgs e) { - Application.Current.Dispatcher.Invoke(() => + int strokeCount = inkCanvas?.Strokes?.Count ?? 0; + bool needScreenshot = strokeCount > Settings.Automation.MinimumAutomationStrokeNumber && + Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint; + + Task.Run(() => { try { - var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0; - if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber && - Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint && currentSlide > 0) + if (needScreenshot) { - var presentationName = _pptManager?.GetPresentationName() ?? ""; - SaveScreenShot(true, $"{presentationName}/{currentSlide}"); + var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0; + if (currentSlide > 0) + { + var presentationName = _pptManager?.GetPresentationName() ?? ""; + Application.Current.Dispatcher.BeginInvoke(new Action(() => SaveScreenShot(true, $"{presentationName}/{currentSlide}"))); + } } - - // 执行翻页 - if (_pptManager?.TryNavigatePrevious() == true) + return _pptManager?.TryNavigatePrevious() ?? false; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"PPT上一页操作异常: {ex}", LogHelper.LogType.Error); + return false; + } + }).ContinueWith(t => + { + Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + if (t.IsFaulted) { _pptUIManager?.UpdateConnectionStatus(false); return; } + if (t.Result) { - // 若启用了“翻页时跳过PPT动画”,显示导航后把焦点拉回本窗口 - if (Settings.PowerPointSettings.SkipAnimationsWhenGoNext) - { - try { this.Activate(); } catch { } - } + if (Settings.PowerPointSettings.SkipAnimationsWhenGoNext) try { this.Activate(); } catch { } } else { LogHelper.WriteLogToFile("切换到上一页失败", LogHelper.LogType.Warning); _pptUIManager?.UpdateConnectionStatus(false); } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"PPT上一页操作异常: {ex}", LogHelper.LogType.Error); - _pptUIManager?.UpdateConnectionStatus(false); - } + })); }); } @@ -1970,44 +1977,45 @@ namespace Ink_Canvas /// private void BtnPPTSlidesDown_Click(object sender, RoutedEventArgs e) { - Application.Current.Dispatcher.Invoke(() => + int strokeCount = inkCanvas?.Strokes?.Count ?? 0; + bool needScreenshot = strokeCount > Settings.Automation.MinimumAutomationStrokeNumber && + Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint; + + Task.Run(() => { try { - var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0; - if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber && - Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint && currentSlide > 0) + if (needScreenshot) { - var presentationName = _pptManager?.GetPresentationName() ?? ""; - SaveScreenShot(true, $"{presentationName}/{currentSlide}"); - } - - // 执行翻页 - if (_pptManager?.TryNavigateNext() == true) - { - // 若启用了“翻页时跳过PPT动画”,翻页后主动把焦点拉回本窗口,避免 PPT 抢焦点 - if (Settings.PowerPointSettings.SkipAnimationsWhenGoNext) + var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0; + if (currentSlide > 0) { - try - { - this.Activate(); - } - catch - { - } + var presentationName = _pptManager?.GetPresentationName() ?? ""; + Application.Current.Dispatcher.BeginInvoke(new Action(() => SaveScreenShot(true, $"{presentationName}/{currentSlide}"))); } } + return _pptManager?.TryNavigateNext() ?? false; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"PPT下一页操作异常: {ex}", LogHelper.LogType.Error); + return false; + } + }).ContinueWith(t => + { + Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + if (t.IsFaulted) { _pptUIManager?.UpdateConnectionStatus(false); return; } + if (t.Result) + { + if (Settings.PowerPointSettings.SkipAnimationsWhenGoNext) try { this.Activate(); } catch { } + } else { LogHelper.WriteLogToFile("切换到下一页失败", LogHelper.LogType.Warning); _pptUIManager?.UpdateConnectionStatus(false); } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"PPT下一页操作异常: {ex}", LogHelper.LogType.Error); - _pptUIManager?.UpdateConnectionStatus(false); - } + })); }); }