From 2d9901791cf688a356d9e90547511dff08dd7a33 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sat, 2 May 2026 09:53:41 +0800 Subject: [PATCH] =?UTF-8?q?improve:PPT=E5=A2=9E=E5=BC=BA=E9=A2=84=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow_cs/MW_PPT.cs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Ink Canvas/MainWindow_cs/MW_PPT.cs b/Ink Canvas/MainWindow_cs/MW_PPT.cs index 0a354f6e..e2e9e1a3 100644 --- a/Ink Canvas/MainWindow_cs/MW_PPT.cs +++ b/Ink Canvas/MainWindow_cs/MW_PPT.cs @@ -2275,7 +2275,7 @@ namespace Ink_Canvas } else { - var slides = await Task.Run(BuildPptPreviewItems); + var slides = await RunOnStaAsync(BuildPptPreviewItems); if (slides == null || slides.Count == 0) { LogHelper.WriteLogToFile("PPT增强预览未生成可用缩略图,改用默认导航", LogHelper.LogType.Warning); @@ -2360,8 +2360,14 @@ namespace Ink_Canvas } /// 在 MainWindow 加载完成后调用,把 4 个 PptNavBar 的事件接到本类。 + private bool _pptNavBarsWired; + private void WirePptNavBars() { + // InitializePPTManagers 可能被多次调用(切换 COM/ROT、设置变更等)。 + // PptNavBar 事件若在同一控件上重复订阅,会导致翻页、长按、预览展开等逻辑成倍触发。 + if (_pptNavBarsWired) return; + var bars = new[] { LeftBottomPanelForPPTNavigation, @@ -2390,6 +2396,8 @@ namespace Ink_Canvas bar.SlideSelected += (s, slideNumber) => OnPptNavBarSlideSelected(captured, slideNumber); bar.PreviewExpandedChanged += (s, expanded) => OnPptNavBarPreviewExpandedChanged(captured, expanded); } + + _pptNavBarsWired = true; } private bool _suppressPreviewExpandedSync; @@ -2460,6 +2468,22 @@ namespace Ink_Canvas } } + private static Task RunOnStaAsync(Func func) + { + // Office interop 要求 STA + COM 单元;Task.Run 跑到 MTA 线程池里会触发 RPC_E_WRONG_THREAD + // 等随机 COM 失败,表现为增强预览空白或崩溃。显式创建 STA worker 在其中执行导出。 + var tcs = new TaskCompletionSource(); + var thread = new Thread(() => + { + try { tcs.SetResult(func()); } + catch (Exception ex) { tcs.SetException(ex); } + }); + thread.IsBackground = true; + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + return tcs.Task; + } + private List BuildPptPreviewItems() { var result = new List();