Compare commits

...

1 Commits

Author SHA1 Message Date
doudou0720 ab7905696d refactor(PPT)!: 重构PPT链接管理器,引入基类并优化代码结构
将ROTPPTManager重命名为ROTPPTLinkManager
新增BasePPTLinkManager抽象基类,提取公共逻辑
重构ComPPTLinkManager继承自基类,减少重复代码

Signed-off-by: doudou0720 <98651603+doudou0720@users.noreply.github.com>
2026-04-12 13:40:54 +08:00
4 changed files with 191 additions and 106 deletions
+117
View File
@@ -0,0 +1,117 @@
using System;
namespace Ink_Canvas.Helpers
{
public abstract class BasePPTLinkManager : IPPTLinkManager
{
#region IPPTLinkManager
public event Action<object> SlideShowBegin;
public event Action<object> SlideShowNextSlide;
public event Action<object> SlideShowEnd;
public event Action<object> PresentationOpen;
public event Action<object> PresentationClose;
public event Action<bool> PPTConnectionChanged;
public event Action<bool> SlideShowStateChanged;
#endregion
#region IPPTLinkManager
public virtual bool IsConnected => PPTApplication != null;
public virtual bool IsInSlideShow { get; protected set; }
public virtual bool IsSupportWPS { get; set; }
public virtual bool SkipAnimationsWhenNavigating { get; set; }
public virtual int SlidesCount { get; protected set; }
public abstract object PPTApplication { get; protected set; }
#endregion
#region
protected BasePPTLinkManager()
{
}
#endregion
#region
public abstract void StartMonitoring();
public abstract void StopMonitoring();
public virtual void ReloadConnection()
{
LogHelper.WriteLogToFile($"{GetType().Name} 执行热重载:强制断开并重新连接", LogHelper.LogType.Event);
StopMonitoring();
}
#endregion
#region
public abstract bool TryStartSlideShow();
public abstract bool TryEndSlideShow();
#endregion
#region
public abstract bool TryNavigateToSlide(int slideNumber);
public abstract bool TryNavigateNext();
public abstract bool TryNavigatePrevious();
#endregion
#region
public abstract int GetCurrentSlideNumber();
public abstract string GetPresentationName();
public abstract bool TryShowSlideNavigation();
public abstract object GetCurrentActivePresentation();
#endregion
#region
protected virtual void OnSlideShowBegin(object slideShowWindow)
{
SlideShowBegin?.Invoke(slideShowWindow);
}
protected virtual void OnSlideShowNextSlide(object slideShowWindow)
{
SlideShowNextSlide?.Invoke(slideShowWindow);
}
protected virtual void OnSlideShowEnd(object presentation)
{
SlideShowEnd?.Invoke(presentation);
}
protected virtual void OnPresentationOpen(object presentation)
{
PresentationOpen?.Invoke(presentation);
}
protected virtual void OnPresentationClose(object presentation)
{
PresentationClose?.Invoke(presentation);
}
protected virtual void OnPPTConnectionChanged(bool isConnected)
{
PPTConnectionChanged?.Invoke(isConnected);
}
protected virtual void OnSlideShowStateChanged(bool isInSlideShow)
{
SlideShowStateChanged?.Invoke(isInSlideShow);
}
#endregion
#region IDisposable
public virtual void Dispose()
{
StopMonitoring();
}
#endregion
}
}
+32 -50
View File
@@ -2,7 +2,7 @@ using System;
namespace Ink_Canvas.Helpers namespace Ink_Canvas.Helpers
{ {
public class ComPPTLinkManager : IPPTLinkManager public class ComPPTLinkManager : BasePPTLinkManager
{ {
private readonly PPTManager _inner; private readonly PPTManager _inner;
@@ -10,65 +10,47 @@ namespace Ink_Canvas.Helpers
{ {
_inner = new PPTManager(); _inner = new PPTManager();
_inner.SlideShowBegin += wn => SlideShowBegin?.Invoke(wn); _inner.SlideShowBegin += wn => OnSlideShowBegin(wn);
_inner.SlideShowNextSlide += wn => SlideShowNextSlide?.Invoke(wn); _inner.SlideShowNextSlide += wn => OnSlideShowNextSlide(wn);
_inner.SlideShowEnd += pres => SlideShowEnd?.Invoke(pres); _inner.SlideShowEnd += pres => OnSlideShowEnd(pres);
_inner.PresentationOpen += pres => PresentationOpen?.Invoke(pres); _inner.PresentationOpen += pres => OnPresentationOpen(pres);
_inner.PresentationClose += pres => PresentationClose?.Invoke(pres); _inner.PresentationClose += pres => OnPresentationClose(pres);
_inner.PPTConnectionChanged += connected => PPTConnectionChanged?.Invoke(connected); _inner.PPTConnectionChanged += connected => OnPPTConnectionChanged(connected);
_inner.SlideShowStateChanged += inSlideShow => SlideShowStateChanged?.Invoke(inSlideShow); _inner.SlideShowStateChanged += inSlideShow => OnSlideShowStateChanged(inSlideShow);
} }
#region IPPTLinkManager #region BasePPTLinkManager
public event Action<object> SlideShowBegin; public override bool IsConnected => _inner.IsConnected;
public event Action<object> SlideShowNextSlide;
public event Action<object> SlideShowEnd;
public event Action<object> PresentationOpen;
public event Action<object> PresentationClose;
public event Action<bool> PPTConnectionChanged;
public event Action<bool> SlideShowStateChanged;
#endregion
#region IPPTLinkManager public override bool IsInSlideShow => _inner.IsInSlideShow;
public bool IsConnected => _inner.IsConnected;
public bool IsInSlideShow => _inner.IsInSlideShow; public override bool IsSupportWPS
public bool IsSupportWPS
{ {
get => _inner.IsSupportWPS; get => _inner.IsSupportWPS;
set => _inner.IsSupportWPS = value; set => _inner.IsSupportWPS = value;
} }
public bool SkipAnimationsWhenNavigating public override bool SkipAnimationsWhenNavigating
{ {
get => _inner.SkipAnimationsWhenNavigating; get => _inner.SkipAnimationsWhenNavigating;
set => _inner.SkipAnimationsWhenNavigating = value; set => _inner.SkipAnimationsWhenNavigating = value;
} }
public int SlidesCount => _inner.SlidesCount; public override int SlidesCount => _inner.SlidesCount;
public object PPTApplication => _inner.PPTApplication; public override object PPTApplication
{
get => _inner.PPTApplication;
protected set { }
}
#endregion #endregion
#region #region
/// <summary> public override void StartMonitoring() => _inner.StartMonitoring();
/// 开始监控本地 PowerPoint 的连接与运行状态,并在状态变化时触发相应事件。
/// </summary>
public void StartMonitoring() => _inner.StartMonitoring();
/// <summary> public override void StopMonitoring() => _inner.StopMonitoring();
/// 停止对 PowerPoint 的监控,断开当前连接并停止触发相关事件。
/// </summary>
public void StopMonitoring() => _inner.StopMonitoring();
/// <summary> public override void ReloadConnection()
/// 强制断开当前 COM PPT 连接并停止对其监控,同时写入事件日志。
/// </summary>
/// <remarks>
/// 会向日志记录一条事件信息并调用内部管理器停止监控;该方法不会重新启动监控或重新初始化内部管理器实例。
/// </remarks>
public void ReloadConnection()
{ {
LogHelper.WriteLogToFile("COM PPT 执行热重载:强制断开并重新连接", LogHelper.LogType.Event); LogHelper.WriteLogToFile("COM PPT 执行热重载:强制断开并重新连接", LogHelper.LogType.Event);
_inner.StopMonitoring(); _inner.StopMonitoring();
@@ -76,31 +58,31 @@ namespace Ink_Canvas.Helpers
#endregion #endregion
#region #region
public bool TryStartSlideShow() => _inner.TryStartSlideShow(); public override bool TryStartSlideShow() => _inner.TryStartSlideShow();
public bool TryEndSlideShow() => _inner.TryEndSlideShow(); public override bool TryEndSlideShow() => _inner.TryEndSlideShow();
#endregion #endregion
#region #region
public bool TryNavigateToSlide(int slideNumber) => _inner.TryNavigateToSlide(slideNumber); public override bool TryNavigateToSlide(int slideNumber) => _inner.TryNavigateToSlide(slideNumber);
public bool TryNavigateNext() => _inner.TryNavigateNext(); public override bool TryNavigateNext() => _inner.TryNavigateNext();
public bool TryNavigatePrevious() => _inner.TryNavigatePrevious(); public override bool TryNavigatePrevious() => _inner.TryNavigatePrevious();
#endregion #endregion
#region #region
public int GetCurrentSlideNumber() => _inner.GetCurrentSlideNumber(); public override int GetCurrentSlideNumber() => _inner.GetCurrentSlideNumber();
public string GetPresentationName() => _inner.GetPresentationName(); public override string GetPresentationName() => _inner.GetPresentationName();
public bool TryShowSlideNavigation() => _inner.TryShowSlideNavigation(); public override bool TryShowSlideNavigation() => _inner.TryShowSlideNavigation();
public object GetCurrentActivePresentation() => _inner.GetCurrentActivePresentation(); public override object GetCurrentActivePresentation() => _inner.GetCurrentActivePresentation();
#endregion #endregion
#region IDisposable #region IDisposable
public void Dispose() public override void Dispose()
{ {
_inner?.Dispose(); _inner?.Dispose();
} }
@@ -11,25 +11,14 @@ using Timer = System.Timers.Timer;
namespace Ink_Canvas.Helpers namespace Ink_Canvas.Helpers
{ {
public class ROTPPTManager : IPPTLinkManager public class ROTPPTLinkManager : BasePPTLinkManager
{ {
#region Events public override dynamic PPTApplication { get; protected set; }
public event Action<object> SlideShowBegin;
public event Action<object> SlideShowNextSlide;
public event Action<object> SlideShowEnd;
public event Action<object> PresentationOpen;
public event Action<object> PresentationClose;
public event Action<bool> PPTConnectionChanged;
public event Action<bool> SlideShowStateChanged;
#endregion
#region Properties
public dynamic PPTApplication { get; private set; }
public dynamic CurrentPresentation { get; private set; } public dynamic CurrentPresentation { get; private set; }
public dynamic CurrentSlides { get; private set; } public dynamic CurrentSlides { get; private set; }
public dynamic CurrentSlide { get; private set; } public dynamic CurrentSlide { get; private set; }
public int SlidesCount { get; private set; } public override int SlidesCount { get; protected set; }
public bool IsConnected public override bool IsConnected
{ {
get get
{ {
@@ -38,14 +27,12 @@ namespace Ink_Canvas.Helpers
if (PPTApplication == null) return false; if (PPTApplication == null) return false;
if (!Marshal.IsComObject(PPTApplication)) return false; if (!Marshal.IsComObject(PPTApplication)) return false;
// 尝试访问一个简单的属性来验证连接是否有效
var _ = PPTApplication.Name; var _ = PPTApplication.Name;
return true; return true;
} }
catch (COMException comEx) catch (COMException comEx)
{ {
var hr = (uint)comEx.HResult; var hr = (uint)comEx.HResult;
// 如果COM对象已失效,返回false
if (hr == 0x8001010E || hr == 0x80004005 || hr == 0x800706B5) if (hr == 0x8001010E || hr == 0x80004005 || hr == 0x800706B5)
{ {
return false; return false;
@@ -58,7 +45,7 @@ namespace Ink_Canvas.Helpers
} }
} }
} }
public bool IsInSlideShow public override bool IsInSlideShow
{ {
get get
{ {
@@ -119,9 +106,8 @@ namespace Ink_Canvas.Helpers
} }
} }
} }
public bool IsSupportWPS { get; set; } = false; public override bool IsSupportWPS { get; set; } = false;
public bool SkipAnimationsWhenNavigating { get; set; } = false; public override bool SkipAnimationsWhenNavigating { get; set; } = false;
#endregion
#region Private Fields #region Private Fields
private Thread _monitoringThread; private Thread _monitoringThread;
@@ -149,11 +135,11 @@ namespace Ink_Canvas.Helpers
#endregion #endregion
#region Constructor & Initialization #region Constructor & Initialization
public ROTPPTManager() public ROTPPTLinkManager()
{ {
} }
public void StartMonitoring() public override void StartMonitoring()
{ {
if (_disposed) return; if (_disposed) return;
@@ -175,7 +161,7 @@ namespace Ink_Canvas.Helpers
} }
} }
public void StopMonitoring() public override void StopMonitoring()
{ {
lock (_monitoringLock) lock (_monitoringLock)
{ {
@@ -195,7 +181,7 @@ namespace Ink_Canvas.Helpers
} }
} }
public void ReloadConnection() public override void ReloadConnection()
{ {
if (_disposed) return; if (_disposed) return;
@@ -555,7 +541,7 @@ namespace Ink_Canvas.Helpers
{ {
try try
{ {
SlideShowNextSlide?.Invoke(_pptSlideShowWindow); OnSlideShowNextSlide(_pptSlideShowWindow);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -586,7 +572,7 @@ namespace Ink_Canvas.Helpers
{ {
try try
{ {
SlideShowNextSlide?.Invoke(_pptSlideShowWindow); OnSlideShowNextSlide(_pptSlideShowWindow);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -617,7 +603,7 @@ namespace Ink_Canvas.Helpers
SlidesCount = 0; SlidesCount = 0;
_lastSlideShowState = false; _lastSlideShowState = false;
SlideShowStateChanged?.Invoke(false); OnSlideShowStateChanged(false);
if (_pptActivePresentation != null) if (_pptActivePresentation != null)
{ {
@@ -964,7 +950,7 @@ namespace Ink_Canvas.Helpers
try try
{ {
LogHelper.WriteLogToFile($"轮询模式检测到页码变化: {_lastPolledSlideNumber} -> {currentPage},触发事件", LogHelper.LogType.Trace); LogHelper.WriteLogToFile($"轮询模式检测到页码变化: {_lastPolledSlideNumber} -> {currentPage},触发事件", LogHelper.LogType.Trace);
SlideShowNextSlide?.Invoke(_pptSlideShowWindow); OnSlideShowNextSlide(_pptSlideShowWindow);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -1008,7 +994,7 @@ namespace Ink_Canvas.Helpers
try try
{ {
LogHelper.WriteLogToFile($"轮询模式检测到页码变化: {_lastPolledSlideNumber} -> {currentPage},触发事件", LogHelper.LogType.Trace); LogHelper.WriteLogToFile($"轮询模式检测到页码变化: {_lastPolledSlideNumber} -> {currentPage},触发事件", LogHelper.LogType.Trace);
SlideShowNextSlide?.Invoke(_pptSlideShowWindow); OnSlideShowNextSlide(_pptSlideShowWindow);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -1038,7 +1024,7 @@ namespace Ink_Canvas.Helpers
SlidesCount = 0; SlidesCount = 0;
_lastSlideShowState = false; _lastSlideShowState = false;
SlideShowStateChanged?.Invoke(false); OnSlideShowStateChanged(false);
if (_pptActivePresentation != null) if (_pptActivePresentation != null)
{ {
@@ -1074,7 +1060,7 @@ namespace Ink_Canvas.Helpers
if (currentSlideShowState != _lastSlideShowState) if (currentSlideShowState != _lastSlideShowState)
{ {
_lastSlideShowState = currentSlideShowState; _lastSlideShowState = currentSlideShowState;
SlideShowStateChanged?.Invoke(currentSlideShowState); OnSlideShowStateChanged(currentSlideShowState);
if (!currentSlideShowState) if (!currentSlideShowState)
{ {
@@ -1252,7 +1238,7 @@ namespace Ink_Canvas.Helpers
UpdateCurrentPresentationInfo(); UpdateCurrentPresentationInfo();
} }
PPTConnectionChanged?.Invoke(true); OnPPTConnectionChanged(true);
try try
{ {
@@ -1301,7 +1287,7 @@ namespace Ink_Canvas.Helpers
if (slideShowWindow == null) if (slideShowWindow == null)
return; return;
SlideShowBegin?.Invoke(slideShowWindow); OnSlideShowBegin(slideShowWindow);
LogHelper.WriteLogToFile("检测到放映已在进行中,热重载", LogHelper.LogType.Trace); LogHelper.WriteLogToFile("检测到放映已在进行中,热重载", LogHelper.LogType.Trace);
} }
catch (COMException comEx) catch (COMException comEx)
@@ -1374,7 +1360,7 @@ namespace Ink_Canvas.Helpers
{ {
try try
{ {
PresentationClose?.Invoke(_pptActivePresentation); OnPresentationClose(_pptActivePresentation);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -1457,7 +1443,7 @@ namespace Ink_Canvas.Helpers
_forcePolling = true; _forcePolling = true;
_bindingEvents = false; _bindingEvents = false;
PPTConnectionChanged?.Invoke(false); OnPPTConnectionChanged(false);
LogHelper.WriteLogToFile("已断开PPT连接,并显式释放所有COM对象", LogHelper.LogType.Event); LogHelper.WriteLogToFile("已断开PPT连接,并显式释放所有COM对象", LogHelper.LogType.Event);
@@ -1776,7 +1762,7 @@ namespace Ink_Canvas.Helpers
} }
UpdateCurrentPresentationInfo(); UpdateCurrentPresentationInfo();
PresentationOpen?.Invoke(pres); OnPresentationOpen(pres);
LogHelper.WriteLogToFile($"演示文稿已打开: {pres?.Name}", LogHelper.LogType.Event); LogHelper.WriteLogToFile($"演示文稿已打开: {pres?.Name}", LogHelper.LogType.Event);
} }
catch (Exception ex) catch (Exception ex)
@@ -1821,7 +1807,7 @@ namespace Ink_Canvas.Helpers
} }
} }
private void OnSlideShowBegin(object wn) protected override void OnSlideShowBegin(object wn)
{ {
try try
{ {
@@ -1854,10 +1840,10 @@ namespace Ink_Canvas.Helpers
if (!_lastSlideShowState) if (!_lastSlideShowState)
{ {
_lastSlideShowState = true; _lastSlideShowState = true;
SlideShowStateChanged?.Invoke(true); OnSlideShowStateChanged(true);
} }
SlideShowBegin?.Invoke(wn); base.OnSlideShowBegin(wn);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -1890,7 +1876,7 @@ namespace Ink_Canvas.Helpers
} }
UpdateCurrentPresentationInfo(); UpdateCurrentPresentationInfo();
SlideShowNextSlide?.Invoke(wn); base.OnSlideShowNextSlide(wn);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -1898,7 +1884,7 @@ namespace Ink_Canvas.Helpers
} }
} }
private void OnSlideShowEnd(object pres) protected override void OnSlideShowEnd(object pres)
{ {
try try
{ {
@@ -1920,10 +1906,10 @@ namespace Ink_Canvas.Helpers
if (_lastSlideShowState) if (_lastSlideShowState)
{ {
_lastSlideShowState = false; _lastSlideShowState = false;
SlideShowStateChanged?.Invoke(false); OnSlideShowStateChanged(false);
} }
SlideShowEnd?.Invoke(pres); base.OnSlideShowEnd(pres);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -1938,7 +1924,7 @@ namespace Ink_Canvas.Helpers
#endregion #endregion
#region Public Methods #region Public Methods
public bool TryNavigateToSlide(int slideNumber) public override bool TryNavigateToSlide(int slideNumber)
{ {
object slideShowWindows = null; object slideShowWindows = null;
object slideShowWindow = null; object slideShowWindow = null;
@@ -2025,7 +2011,7 @@ namespace Ink_Canvas.Helpers
} }
} }
public bool TryNavigateNext() public override bool TryNavigateNext()
{ {
try try
{ {
@@ -2088,7 +2074,7 @@ namespace Ink_Canvas.Helpers
} }
} }
public bool TryNavigatePrevious() public override bool TryNavigatePrevious()
{ {
try try
{ {
@@ -2151,7 +2137,7 @@ namespace Ink_Canvas.Helpers
} }
} }
public bool TryEndSlideShow() public override bool TryEndSlideShow()
{ {
object slideShowWindows = null; object slideShowWindows = null;
object slideShowWindow = null; object slideShowWindow = null;
@@ -2203,7 +2189,7 @@ namespace Ink_Canvas.Helpers
} }
} }
public bool TryStartSlideShow() public override bool TryStartSlideShow()
{ {
try try
{ {
@@ -2234,7 +2220,7 @@ namespace Ink_Canvas.Helpers
/// <summary> /// <summary>
/// 获取当前活跃的演示文稿 /// 获取当前活跃的演示文稿
/// </summary> /// </summary>
public object GetCurrentActivePresentation() public override object GetCurrentActivePresentation()
{ {
object slideShowWindows = null; object slideShowWindows = null;
object slideShowWindow = null; object slideShowWindow = null;
@@ -2412,7 +2398,7 @@ namespace Ink_Canvas.Helpers
} }
} }
public int GetCurrentSlideNumber() public override int GetCurrentSlideNumber()
{ {
object activeWindow = null; object activeWindow = null;
object selection = null; object selection = null;
@@ -2483,7 +2469,7 @@ namespace Ink_Canvas.Helpers
} }
} }
public string GetPresentationName() public override string GetPresentationName()
{ {
try try
{ {
@@ -2535,7 +2521,7 @@ namespace Ink_Canvas.Helpers
} }
} }
public bool TryShowSlideNavigation() public override bool TryShowSlideNavigation()
{ {
object slideShowWindows = null; object slideShowWindows = null;
object slideShowWindow = null; object slideShowWindow = null;
@@ -3020,7 +3006,7 @@ namespace Ink_Canvas.Helpers
SlidesCount = 0; SlidesCount = 0;
StopWpsProcessCheckTimer(); StopWpsProcessCheckTimer();
PPTConnectionChanged?.Invoke(false); OnPPTConnectionChanged(false);
LogHelper.WriteLogToFile("WPS进程结束后已清理所有COM对象并重启连接检查", LogHelper.LogType.Event); LogHelper.WriteLogToFile("WPS进程结束后已清理所有COM对象并重启连接检查", LogHelper.LogType.Event);
} }
@@ -3542,7 +3528,7 @@ namespace Ink_Canvas.Helpers
#endregion #endregion
#region Dispose #region Dispose
public void Dispose() public override void Dispose()
{ {
if (!_disposed) if (!_disposed)
{ {
+1 -1
View File
@@ -248,7 +248,7 @@ namespace Ink_Canvas
// 根据设置选择 COM / ROT 架构 // 根据设置选择 COM / ROT 架构
if (Settings.PowerPointSettings.UseRotPptLink) if (Settings.PowerPointSettings.UseRotPptLink)
{ {
_pptManager = new ROTPPTManager(); _pptManager = new ROTPPTLinkManager();
} }
else else
{ {