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();