improve:PPT模块

This commit is contained in:
2026-02-22 17:52:33 +08:00
parent 8394c6d6d6
commit 17c020284d
2 changed files with 119 additions and 129 deletions
+65 -83
View File
@@ -38,89 +38,11 @@ namespace Ink_Canvas.Helpers
{ {
get get
{ {
try if (PPTApplication == null) return false;
{ return _cachedIsConnected;
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);
}
} }
} }
public bool IsInSlideShow => _cachedIsInSlideShow;
public bool IsSupportWPS { get; set; } = false; public bool IsSupportWPS { get; set; } = false;
public bool SkipAnimationsWhenNavigating { get; set; } = false; public bool SkipAnimationsWhenNavigating { get; set; } = false;
@@ -140,6 +62,8 @@ namespace Ink_Canvas.Helpers
private WpsWindowInfo _lastForegroundWpsWindow; private WpsWindowInfo _lastForegroundWpsWindow;
private DateTime _lastWindowCheckTime = DateTime.MinValue; private DateTime _lastWindowCheckTime = DateTime.MinValue;
private bool _lastSlideShowState; private bool _lastSlideShowState;
private volatile bool _cachedIsConnected;
private volatile bool _cachedIsInSlideShow;
private readonly object _lockObject = new object(); private readonly object _lockObject = new object();
private bool _disposed; private bool _disposed;
private static bool IsPptBusyHResult(uint hr) => hr == 0x80010001 || hr == 0x8001010A; 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() private void CheckSlideShowState()
{ {
try try
{ {
if (!IsConnected) return; if (!IsConnected) return;
var currentSlideShowState = IsInSlideShow; var currentSlideShowState = RefreshIsInSlideShowFromCom();
if (currentSlideShowState != _lastSlideShowState) if (currentSlideShowState != _lastSlideShowState)
{ {
_lastSlideShowState = currentSlideShowState; _lastSlideShowState = currentSlideShowState;
@@ -341,6 +316,7 @@ namespace Ink_Canvas.Helpers
try try
{ {
PPTApplication = pptApp; PPTApplication = pptApp;
_cachedIsConnected = true;
// 在主线程中注册事件,确保COM对象在正确的线程中 // 在主线程中注册事件,确保COM对象在正确的线程中
Application.Current?.Dispatcher?.Invoke(() => Application.Current?.Dispatcher?.Invoke(() =>
@@ -370,7 +346,8 @@ namespace Ink_Canvas.Helpers
LogHelper.WriteLogToFile("成功连接到PPT应用程序", LogHelper.LogType.Event); LogHelper.WriteLogToFile("成功连接到PPT应用程序", LogHelper.LogType.Event);
if (IsInSlideShow) RefreshIsInSlideShowFromCom();
if (_cachedIsInSlideShow)
{ {
OnSlideShowBegin(PPTApplication.SlideShowWindows[1]); OnSlideShowBegin(PPTApplication.SlideShowWindows[1]);
} }
@@ -382,6 +359,7 @@ namespace Ink_Canvas.Helpers
catch (Exception ex) catch (Exception ex)
{ {
LogHelper.WriteLogToFile($"连接PPT应用程序失败: {ex}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"连接PPT应用程序失败: {ex}", LogHelper.LogType.Error);
_cachedIsConnected = false;
PPTApplication = null; PPTApplication = null;
} }
} }
@@ -456,6 +434,8 @@ namespace Ink_Canvas.Helpers
} }
} }
_cachedIsConnected = false;
_cachedIsInSlideShow = false;
PPTApplication = null; PPTApplication = null;
CurrentPresentation = null; CurrentPresentation = null;
CurrentSlides = null; CurrentSlides = null;
@@ -734,6 +714,7 @@ namespace Ink_Canvas.Helpers
private void OnSlideShowBegin(SlideShowWindow wn) private void OnSlideShowBegin(SlideShowWindow wn)
{ {
_cachedIsInSlideShow = true;
try try
{ {
UpdateCurrentPresentationInfo(); UpdateCurrentPresentationInfo();
@@ -760,6 +741,7 @@ namespace Ink_Canvas.Helpers
private void OnSlideShowEnd(Presentation pres) private void OnSlideShowEnd(Presentation pres)
{ {
_cachedIsInSlideShow = false;
try try
{ {
// 记录WPS进程用于后续管理 // 记录WPS进程用于后续管理
+54 -46
View File
@@ -1927,38 +1927,45 @@ namespace Ink_Canvas
/// <param name="e">路由事件参数。</param> /// <param name="e">路由事件参数。</param>
private void BtnPPTSlidesUp_Click(object sender, RoutedEventArgs e) 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 try
{ {
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0; if (needScreenshot)
if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint && currentSlide > 0)
{ {
var presentationName = _pptManager?.GetPresentationName() ?? ""; var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
SaveScreenShot(true, $"{presentationName}/{currentSlide}"); if (currentSlide > 0)
{
var presentationName = _pptManager?.GetPresentationName() ?? "";
Application.Current.Dispatcher.BeginInvoke(new Action(() => SaveScreenShot(true, $"{presentationName}/{currentSlide}")));
}
} }
return _pptManager?.TryNavigatePrevious() ?? false;
// 执行翻页 }
if (_pptManager?.TryNavigatePrevious() == true) 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 else
{ {
LogHelper.WriteLogToFile("切换到上一页失败", LogHelper.LogType.Warning); LogHelper.WriteLogToFile("切换到上一页失败", LogHelper.LogType.Warning);
_pptUIManager?.UpdateConnectionStatus(false); _pptUIManager?.UpdateConnectionStatus(false);
} }
} }));
catch (Exception ex)
{
LogHelper.WriteLogToFile($"PPT上一页操作异常: {ex}", LogHelper.LogType.Error);
_pptUIManager?.UpdateConnectionStatus(false);
}
}); });
} }
@@ -1970,44 +1977,45 @@ namespace Ink_Canvas
/// </remarks> /// </remarks>
private void BtnPPTSlidesDown_Click(object sender, RoutedEventArgs e) 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 try
{ {
var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0; if (needScreenshot)
if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint && currentSlide > 0)
{ {
var presentationName = _pptManager?.GetPresentationName() ?? ""; var currentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
SaveScreenShot(true, $"{presentationName}/{currentSlide}"); if (currentSlide > 0)
}
// 执行翻页
if (_pptManager?.TryNavigateNext() == true)
{
// 若启用了“翻页时跳过PPT动画”,翻页后主动把焦点拉回本窗口,避免 PPT 抢焦点
if (Settings.PowerPointSettings.SkipAnimationsWhenGoNext)
{ {
try var presentationName = _pptManager?.GetPresentationName() ?? "";
{ Application.Current.Dispatcher.BeginInvoke(new Action(() => SaveScreenShot(true, $"{presentationName}/{currentSlide}")));
this.Activate();
}
catch
{
}
} }
} }
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 else
{ {
LogHelper.WriteLogToFile("切换到下一页失败", LogHelper.LogType.Warning); LogHelper.WriteLogToFile("切换到下一页失败", LogHelper.LogType.Warning);
_pptUIManager?.UpdateConnectionStatus(false); _pptUIManager?.UpdateConnectionStatus(false);
} }
} }));
catch (Exception ex)
{
LogHelper.WriteLogToFile($"PPT下一页操作异常: {ex}", LogHelper.LogType.Error);
_pptUIManager?.UpdateConnectionStatus(false);
}
}); });
} }