improve:PPT联动
This commit is contained in:
@@ -29,7 +29,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
public object PPTApplication { get; private set; }
|
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; }
|
||||||
@@ -44,8 +44,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
if (!Marshal.IsComObject(PPTApplication)) return false;
|
if (!Marshal.IsComObject(PPTApplication)) return false;
|
||||||
|
|
||||||
// 尝试访问一个简单的属性来验证连接是否有效
|
// 尝试访问一个简单的属性来验证连接是否有效
|
||||||
dynamic app = PPTApplication;
|
var _ = PPTApplication.Name;
|
||||||
var _ = app.Name;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (COMException comEx)
|
catch (COMException comEx)
|
||||||
@@ -75,8 +74,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
if (PPTApplication == null || !Marshal.IsComObject(PPTApplication)) return false;
|
if (PPTApplication == null || !Marshal.IsComObject(PPTApplication)) return false;
|
||||||
|
|
||||||
dynamic app = PPTApplication;
|
slideShowWindows = PPTApplication.SlideShowWindows;
|
||||||
slideShowWindows = app.SlideShowWindows;
|
|
||||||
if (slideShowWindows == null) return false;
|
if (slideShowWindows == null) return false;
|
||||||
|
|
||||||
dynamic ssw = slideShowWindows;
|
dynamic ssw = slideShowWindows;
|
||||||
@@ -130,9 +128,9 @@ namespace Ink_Canvas.Helpers
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
private Timer _connectionCheckTimer;
|
private Thread _monitoringThread;
|
||||||
private Timer _slideShowStateCheckTimer;
|
private bool _shouldStop = false;
|
||||||
private Timer _wpsProcessCheckTimer;
|
private readonly object _monitoringLock = new object();
|
||||||
private Process _wpsProcess;
|
private Process _wpsProcess;
|
||||||
private bool _isModuleUnloading = false;
|
private bool _isModuleUnloading = false;
|
||||||
private bool _hasWpsProcessId;
|
private bool _hasWpsProcessId;
|
||||||
@@ -147,7 +145,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
private dynamic _pptActivePresentation;
|
private dynamic _pptActivePresentation;
|
||||||
private dynamic _pptSlideShowWindow;
|
private dynamic _pptSlideShowWindow;
|
||||||
private int _polling = 0;
|
private int _polling = 0;
|
||||||
private bool _forcePolling = false;
|
private bool _forcePolling = true;
|
||||||
private bool _bindingEvents = false;
|
private bool _bindingEvents = false;
|
||||||
private DateTime _updateTime;
|
private DateTime _updateTime;
|
||||||
private int _lastPolledSlideNumber = -1;
|
private int _lastPolledSlideNumber = -1;
|
||||||
@@ -156,36 +154,48 @@ namespace Ink_Canvas.Helpers
|
|||||||
#region Constructor & Initialization
|
#region Constructor & Initialization
|
||||||
public PPTManager()
|
public PPTManager()
|
||||||
{
|
{
|
||||||
InitializeConnectionTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeConnectionTimer()
|
|
||||||
{
|
|
||||||
_connectionCheckTimer = new Timer(500);
|
|
||||||
_connectionCheckTimer.Elapsed += OnConnectionCheckTimerElapsed;
|
|
||||||
_connectionCheckTimer.AutoReset = true;
|
|
||||||
|
|
||||||
_slideShowStateCheckTimer = new Timer(1000);
|
|
||||||
_slideShowStateCheckTimer.Elapsed += OnSlideShowStateCheckTimerElapsed;
|
|
||||||
_slideShowStateCheckTimer.AutoReset = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartMonitoring()
|
public void StartMonitoring()
|
||||||
{
|
{
|
||||||
if (!_disposed)
|
if (_disposed) return;
|
||||||
|
|
||||||
|
lock (_monitoringLock)
|
||||||
{
|
{
|
||||||
_connectionCheckTimer?.Start();
|
if (_monitoringThread != null && _monitoringThread.IsAlive)
|
||||||
_slideShowStateCheckTimer?.Start();
|
{
|
||||||
|
return; // 已经在运行
|
||||||
|
}
|
||||||
|
|
||||||
|
_shouldStop = false;
|
||||||
|
_monitoringThread = new Thread(PptComService)
|
||||||
|
{
|
||||||
|
IsBackground = true,
|
||||||
|
Name = "PPTMonitoringThread"
|
||||||
|
};
|
||||||
|
_monitoringThread.Start();
|
||||||
LogHelper.WriteLogToFile("PPT监控已启动", LogHelper.LogType.Trace);
|
LogHelper.WriteLogToFile("PPT监控已启动", LogHelper.LogType.Trace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopMonitoring()
|
public void StopMonitoring()
|
||||||
{
|
{
|
||||||
_connectionCheckTimer?.Stop();
|
lock (_monitoringLock)
|
||||||
_slideShowStateCheckTimer?.Stop();
|
{
|
||||||
DisconnectFromPPT();
|
_shouldStop = true;
|
||||||
LogHelper.WriteLogToFile("PPT监控已停止", LogHelper.LogType.Trace);
|
|
||||||
|
if (_monitoringThread != null && _monitoringThread.IsAlive)
|
||||||
|
{
|
||||||
|
// 等待线程退出,最多等待2秒
|
||||||
|
if (!_monitoringThread.Join(2000))
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile("等待监控线程退出超时", LogHelper.LogType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DisconnectFromPPT();
|
||||||
|
LogHelper.WriteLogToFile("PPT监控已停止", LogHelper.LogType.Trace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -287,8 +297,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dynamic app = PPTApplication;
|
_pptActivePresentation = PPTApplication.ActivePresentation;
|
||||||
_pptActivePresentation = app.ActivePresentation;
|
|
||||||
if (_pptActivePresentation != null)
|
if (_pptActivePresentation != null)
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile("轮询模式:初始化_pptActivePresentation", LogHelper.LogType.Trace);
|
LogHelper.WriteLogToFile("轮询模式:初始化_pptActivePresentation", LogHelper.LogType.Trace);
|
||||||
@@ -326,8 +335,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dynamic app = PPTApplication;
|
activePresentation = PPTApplication.ActivePresentation;
|
||||||
activePresentation = app.ActivePresentation;
|
|
||||||
|
|
||||||
if (activePresentation != null && _pptActivePresentation != null && !PPTROTConnectionHelper.AreComObjectsEqual(_pptActivePresentation, activePresentation))
|
if (activePresentation != null && _pptActivePresentation != null && !PPTROTConnectionHelper.AreComObjectsEqual(_pptActivePresentation, activePresentation))
|
||||||
{
|
{
|
||||||
@@ -357,12 +365,11 @@ namespace Ink_Canvas.Helpers
|
|||||||
bool isSlideShowActive = false;
|
bool isSlideShowActive = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dynamic app = PPTApplication;
|
|
||||||
if (activePresentation == null)
|
if (activePresentation == null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
activePresentation = app.ActivePresentation;
|
activePresentation = PPTApplication.ActivePresentation;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -374,7 +381,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dynamic slideShowWindows = app.SlideShowWindows;
|
dynamic slideShowWindows = PPTApplication.SlideShowWindows;
|
||||||
if (slideShowWindows != null && slideShowWindows.Count > 0)
|
if (slideShowWindows != null && slideShowWindows.Count > 0)
|
||||||
{
|
{
|
||||||
isSlideShowActive = true;
|
isSlideShowActive = true;
|
||||||
@@ -424,13 +431,9 @@ namespace Ink_Canvas.Helpers
|
|||||||
|
|
||||||
if (isSlideShowActive)
|
if (isSlideShowActive)
|
||||||
{
|
{
|
||||||
// 在轮询模式下,更频繁地检查(每500ms,与定时器同步)
|
if ((DateTime.Now - _updateTime).TotalMilliseconds > 3000 || _forcePolling)
|
||||||
// 否则每3秒检查一次
|
|
||||||
bool shouldPoll = _forcePolling || (DateTime.Now - _updateTime).TotalMilliseconds > 3000;
|
|
||||||
|
|
||||||
if (shouldPoll)
|
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"开始轮询检查: forcePolling={_forcePolling}, 距离上次更新={(DateTime.Now - _updateTime).TotalMilliseconds}ms", LogHelper.LogType.Trace);
|
LogHelper.WriteLogToFile($"轮询", LogHelper.LogType.Trace);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -453,7 +456,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
SlidesCount = 0;
|
SlidesCount = 0;
|
||||||
_polling = 0;
|
_polling = 0;
|
||||||
LogHelper.WriteLogToFile("轮询: 无法获取总页数", LogHelper.LogType.Trace);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -470,10 +472,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
if (currentPage >= tempTotalPage) _polling = 1;
|
if (currentPage >= tempTotalPage) _polling = 1;
|
||||||
else _polling = 0;
|
else _polling = 0;
|
||||||
|
|
||||||
LogHelper.WriteLogToFile($"轮询: 当前页={currentPage}, 总页={tempTotalPage}, 上次页={_lastPolledSlideNumber}, forcePolling={_forcePolling}", LogHelper.LogType.Trace);
|
if (_lastPolledSlideNumber != -1 && currentPage != _lastPolledSlideNumber)
|
||||||
|
|
||||||
// 在轮询模式下,检测页码变化并触发事件
|
|
||||||
if (_forcePolling && _lastPolledSlideNumber != -1 && currentPage != _lastPolledSlideNumber)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -501,7 +500,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
SlidesCount = 0;
|
SlidesCount = 0;
|
||||||
LogHelper.WriteLogToFile($"轮询检查异常: {ex.Message}", LogHelper.LogType.Warning);
|
LogHelper.WriteLogToFile($"获取总页数失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -517,17 +516,16 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
int currentPage = GetCurrentSlideIndex(_pptSlideShowWindow);
|
int currentPage = GetCurrentSlideIndex(_pptSlideShowWindow);
|
||||||
|
|
||||||
// 在轮询模式下,检测页码变化并触发事件
|
if (_lastPolledSlideNumber != -1 && currentPage != _lastPolledSlideNumber)
|
||||||
if (_forcePolling && _lastPolledSlideNumber != -1 && currentPage != _lastPolledSlideNumber)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"轮询模式检测到页码变化: {_lastPolledSlideNumber} -> {currentPage}", LogHelper.LogType.Trace);
|
LogHelper.WriteLogToFile($"轮询模式检测到页码变化: {_lastPolledSlideNumber} -> {currentPage},触发事件", LogHelper.LogType.Trace);
|
||||||
SlideShowNextSlide?.Invoke(_pptSlideShowWindow);
|
SlideShowNextSlide?.Invoke(_pptSlideShowWindow);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LogHelper.WriteLogToFile($"触发轮询模式幻灯片切换事件失败: {ex.Message}", LogHelper.LogType.Trace);
|
LogHelper.WriteLogToFile($"触发轮询模式幻灯片切换事件失败: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,10 +681,11 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Type appType = typeof(Microsoft.Office.Interop.PowerPoint.Application);
|
// 使用 as 操作符进行类型转换,与 inkeys 保持一致
|
||||||
if (appType.IsInstanceOfType(PPTApplication))
|
Microsoft.Office.Interop.PowerPoint.Application pptAppForEvents = PPTApplication as Microsoft.Office.Interop.PowerPoint.Application;
|
||||||
|
|
||||||
|
if (pptAppForEvents != null)
|
||||||
{
|
{
|
||||||
Microsoft.Office.Interop.PowerPoint.Application pptAppForEvents = (Microsoft.Office.Interop.PowerPoint.Application)PPTApplication;
|
|
||||||
pptAppForEvents.SlideShowNextSlide += new EApplication_SlideShowNextSlideEventHandler(OnSlideShowNextSlide);
|
pptAppForEvents.SlideShowNextSlide += new EApplication_SlideShowNextSlideEventHandler(OnSlideShowNextSlide);
|
||||||
pptAppForEvents.SlideShowBegin += new EApplication_SlideShowBeginEventHandler(OnSlideShowBegin);
|
pptAppForEvents.SlideShowBegin += new EApplication_SlideShowBeginEventHandler(OnSlideShowBegin);
|
||||||
pptAppForEvents.SlideShowEnd += new EApplication_SlideShowEndEventHandler(OnSlideShowEnd);
|
pptAppForEvents.SlideShowEnd += new EApplication_SlideShowEndEventHandler(OnSlideShowEnd);
|
||||||
@@ -701,7 +700,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
_bindingEvents = true;
|
_bindingEvents = true;
|
||||||
_forcePolling = false;
|
|
||||||
|
|
||||||
LogHelper.WriteLogToFile("PPT事件注册成功", LogHelper.LogType.Trace);
|
LogHelper.WriteLogToFile("PPT事件注册成功", LogHelper.LogType.Trace);
|
||||||
}
|
}
|
||||||
@@ -732,6 +730,9 @@ namespace Ink_Canvas.Helpers
|
|||||||
LogHelper.WriteLogToFile($"无法注册事件: {ex.Message}", LogHelper.LogType.Warning);
|
LogHelper.WriteLogToFile($"无法注册事件: {ex.Message}", LogHelper.LogType.Warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_bindingEvents = false;
|
||||||
|
_forcePolling = true;
|
||||||
|
|
||||||
if (_pptActivePresentation != null)
|
if (_pptActivePresentation != null)
|
||||||
{
|
{
|
||||||
UpdateCurrentPresentationInfo();
|
UpdateCurrentPresentationInfo();
|
||||||
@@ -773,10 +774,11 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Type appType = typeof(Microsoft.Office.Interop.PowerPoint.Application);
|
// 使用 as 操作符进行类型转换,与 inkeys 保持一致
|
||||||
if (appType.IsInstanceOfType(PPTApplication))
|
Microsoft.Office.Interop.PowerPoint.Application app = PPTApplication as Microsoft.Office.Interop.PowerPoint.Application;
|
||||||
|
|
||||||
|
if (app != null)
|
||||||
{
|
{
|
||||||
Microsoft.Office.Interop.PowerPoint.Application app = (Microsoft.Office.Interop.PowerPoint.Application)PPTApplication;
|
|
||||||
app.SlideShowNextSlide -= new EApplication_SlideShowNextSlideEventHandler(OnSlideShowNextSlide);
|
app.SlideShowNextSlide -= new EApplication_SlideShowNextSlideEventHandler(OnSlideShowNextSlide);
|
||||||
app.SlideShowBegin -= new EApplication_SlideShowBeginEventHandler(OnSlideShowBegin);
|
app.SlideShowBegin -= new EApplication_SlideShowBeginEventHandler(OnSlideShowBegin);
|
||||||
app.SlideShowEnd -= new EApplication_SlideShowEndEventHandler(OnSlideShowEnd);
|
app.SlideShowEnd -= new EApplication_SlideShowEndEventHandler(OnSlideShowEnd);
|
||||||
@@ -789,7 +791,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
_bindingEvents = false;
|
_bindingEvents = false;
|
||||||
_forcePolling = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
@@ -840,7 +841,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
CurrentSlide = null;
|
CurrentSlide = null;
|
||||||
SlidesCount = 0;
|
SlidesCount = 0;
|
||||||
_polling = 0;
|
_polling = 0;
|
||||||
_forcePolling = false;
|
_forcePolling = true;
|
||||||
_bindingEvents = false;
|
_bindingEvents = false;
|
||||||
|
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
@@ -993,8 +994,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dynamic app = PPTApplication;
|
activeWindow = PPTApplication.ActiveWindow;
|
||||||
activeWindow = app.ActiveWindow;
|
|
||||||
if (activeWindow != null)
|
if (activeWindow != null)
|
||||||
{
|
{
|
||||||
dynamic aw = activeWindow;
|
dynamic aw = activeWindow;
|
||||||
@@ -1095,8 +1095,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dynamic app = PPTApplication;
|
_pptActivePresentation = PPTApplication.ActivePresentation;
|
||||||
_pptActivePresentation = app.ActivePresentation;
|
|
||||||
_updateTime = DateTime.Now;
|
_updateTime = DateTime.Now;
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
@@ -1122,10 +1121,11 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Type appType = typeof(Microsoft.Office.Interop.PowerPoint.Application);
|
// 使用 as 操作符进行类型转换,与 inkeys 保持一致
|
||||||
if (appType.IsInstanceOfType(PPTApplication))
|
Microsoft.Office.Interop.PowerPoint.Application app = PPTApplication as Microsoft.Office.Interop.PowerPoint.Application;
|
||||||
|
|
||||||
|
if (app != null)
|
||||||
{
|
{
|
||||||
Microsoft.Office.Interop.PowerPoint.Application app = (Microsoft.Office.Interop.PowerPoint.Application)PPTApplication;
|
|
||||||
app.SlideShowNextSlide -= new EApplication_SlideShowNextSlideEventHandler(OnSlideShowNextSlide);
|
app.SlideShowNextSlide -= new EApplication_SlideShowNextSlideEventHandler(OnSlideShowNextSlide);
|
||||||
app.SlideShowBegin -= new EApplication_SlideShowBeginEventHandler(OnSlideShowBegin);
|
app.SlideShowBegin -= new EApplication_SlideShowBeginEventHandler(OnSlideShowBegin);
|
||||||
app.SlideShowEnd -= new EApplication_SlideShowEndEventHandler(OnSlideShowEnd);
|
app.SlideShowEnd -= new EApplication_SlideShowEndEventHandler(OnSlideShowEnd);
|
||||||
@@ -1138,7 +1138,6 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
_bindingEvents = false;
|
_bindingEvents = false;
|
||||||
_forcePolling = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DisconnectFromPPT();
|
DisconnectFromPPT();
|
||||||
@@ -1258,8 +1257,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
|
|
||||||
if (IsInSlideShow)
|
if (IsInSlideShow)
|
||||||
{
|
{
|
||||||
dynamic app = PPTApplication;
|
slideShowWindows = PPTApplication.SlideShowWindows;
|
||||||
slideShowWindows = app.SlideShowWindows;
|
|
||||||
if (slideShowWindows != null)
|
if (slideShowWindows != null)
|
||||||
{
|
{
|
||||||
dynamic ssw = slideShowWindows;
|
dynamic ssw = slideShowWindows;
|
||||||
@@ -1343,8 +1341,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dynamic app = PPTApplication;
|
object slideShowWindows = PPTApplication.SlideShowWindows;
|
||||||
object slideShowWindows = app.SlideShowWindows;
|
|
||||||
if (slideShowWindows != null)
|
if (slideShowWindows != null)
|
||||||
{
|
{
|
||||||
dynamic ssw = slideShowWindows;
|
dynamic ssw = slideShowWindows;
|
||||||
@@ -1407,8 +1404,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dynamic app = PPTApplication;
|
object slideShowWindows = PPTApplication.SlideShowWindows;
|
||||||
object slideShowWindows = app.SlideShowWindows;
|
|
||||||
if (slideShowWindows != null)
|
if (slideShowWindows != null)
|
||||||
{
|
{
|
||||||
dynamic ssw = slideShowWindows;
|
dynamic ssw = slideShowWindows;
|
||||||
@@ -1469,8 +1465,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
if (!IsConnected || !IsInSlideShow || PPTApplication == null) return false;
|
if (!IsConnected || !IsInSlideShow || PPTApplication == null) return false;
|
||||||
if (!Marshal.IsComObject(PPTApplication)) return false;
|
if (!Marshal.IsComObject(PPTApplication)) return false;
|
||||||
|
|
||||||
dynamic app = PPTApplication;
|
slideShowWindows = PPTApplication.SlideShowWindows;
|
||||||
slideShowWindows = app.SlideShowWindows;
|
|
||||||
if (slideShowWindows != null)
|
if (slideShowWindows != null)
|
||||||
{
|
{
|
||||||
dynamic ssw = slideShowWindows;
|
dynamic ssw = slideShowWindows;
|
||||||
@@ -1586,8 +1581,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic app = PPTApplication;
|
activeWindow = PPTApplication.ActiveWindow;
|
||||||
activeWindow = app.ActiveWindow;
|
|
||||||
if (activeWindow != null)
|
if (activeWindow != null)
|
||||||
{
|
{
|
||||||
dynamic aw = activeWindow;
|
dynamic aw = activeWindow;
|
||||||
@@ -1701,8 +1695,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic app = PPTApplication;
|
activeWindow = PPTApplication.ActiveWindow;
|
||||||
activeWindow = app.ActiveWindow;
|
|
||||||
if (activeWindow != null)
|
if (activeWindow != null)
|
||||||
{
|
{
|
||||||
dynamic aw = activeWindow;
|
dynamic aw = activeWindow;
|
||||||
@@ -1824,8 +1817,7 @@ namespace Ink_Canvas.Helpers
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic app = PPTApplication;
|
slideShowWindows = PPTApplication.SlideShowWindows;
|
||||||
slideShowWindows = app.SlideShowWindows;
|
|
||||||
if (slideShowWindows != null)
|
if (slideShowWindows != null)
|
||||||
{
|
{
|
||||||
dynamic ssw = slideShowWindows;
|
dynamic ssw = slideShowWindows;
|
||||||
@@ -1898,12 +1890,11 @@ namespace Ink_Canvas.Helpers
|
|||||||
Process wpsProcess = null;
|
Process wpsProcess = null;
|
||||||
|
|
||||||
// 方法1:通过应用程序路径检测
|
// 方法1:通过应用程序路径检测
|
||||||
dynamic app = PPTApplication;
|
if (PPTApplication.Path.Contains("Kingsoft\\WPS Office\\") ||
|
||||||
if (app.Path.Contains("Kingsoft\\WPS Office\\") ||
|
PPTApplication.Path.Contains("WPS Office\\"))
|
||||||
app.Path.Contains("WPS Office\\"))
|
|
||||||
{
|
{
|
||||||
uint processId;
|
uint processId;
|
||||||
GetWindowThreadProcessId((IntPtr)app.HWND, out processId);
|
GetWindowThreadProcessId((IntPtr)PPTApplication.HWND, out processId);
|
||||||
wpsProcess = Process.GetProcessById((int)processId);
|
wpsProcess = Process.GetProcessById((int)processId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2159,10 +2150,9 @@ namespace Ink_Canvas.Helpers
|
|||||||
{
|
{
|
||||||
if (PPTApplication != null && Marshal.IsComObject(PPTApplication))
|
if (PPTApplication != null && Marshal.IsComObject(PPTApplication))
|
||||||
{
|
{
|
||||||
dynamic app = PPTApplication;
|
if (PPTApplication.SlideShowWindows?.Count > 0)
|
||||||
if (app.SlideShowWindows?.Count > 0)
|
|
||||||
{
|
{
|
||||||
pptActWindow = app.SlideShowWindows[1];
|
pptActWindow = PPTApplication.SlideShowWindows[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2332,6 +2322,9 @@ namespace Ink_Canvas.Helpers
|
|||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
|
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern int GetWindowTextLength(IntPtr hWnd);
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
private static extern bool IsWindowVisible(IntPtr hWnd);
|
private static extern bool IsWindowVisible(IntPtr hWnd);
|
||||||
@@ -2634,6 +2627,185 @@ namespace Ink_Canvas.Helpers
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Window Handle Methods
|
||||||
|
/// <summary>
|
||||||
|
/// 获取PPT窗口句柄
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>窗口句柄,如果获取失败返回 IntPtr.Zero</returns>
|
||||||
|
public IntPtr GetPptHwnd()
|
||||||
|
{
|
||||||
|
IntPtr ret = IntPtr.Zero;
|
||||||
|
|
||||||
|
// 方法1: 尝试从 SlideShowWindow 获取
|
||||||
|
ret = GetPptHwndFromSlideShowWindow(_pptSlideShowWindow);
|
||||||
|
|
||||||
|
if (ret == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
// 方法2: 通过窗口标题匹配获取(备用方法)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_pptActivePresentation != null && PPTApplication != null)
|
||||||
|
{
|
||||||
|
dynamic pres = _pptActivePresentation;
|
||||||
|
string fullName = pres.FullName;
|
||||||
|
string appName = PPTApplication.Name;
|
||||||
|
ret = GetPptHwndWin32(fullName, appName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"获取PPT窗口句柄失败: {ex.Message}", LogHelper.LogType.Trace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从 SlideShowWindow 对象获取窗口句柄
|
||||||
|
/// </summary>
|
||||||
|
private IntPtr GetPptHwndFromSlideShowWindow(object pptSlideShowWindowObj)
|
||||||
|
{
|
||||||
|
IntPtr hwnd = IntPtr.Zero;
|
||||||
|
if (pptSlideShowWindowObj == null) return IntPtr.Zero;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 尝试强类型转换
|
||||||
|
Microsoft.Office.Interop.PowerPoint.SlideShowWindow slideWindow =
|
||||||
|
pptSlideShowWindowObj as Microsoft.Office.Interop.PowerPoint.SlideShowWindow;
|
||||||
|
|
||||||
|
if (slideWindow != null)
|
||||||
|
{
|
||||||
|
int hwndVal = slideWindow.HWND;
|
||||||
|
hwnd = new IntPtr(hwndVal);
|
||||||
|
LogHelper.WriteLogToFile($"从SlideShowWindow获取窗口句柄成功: {hwnd}", LogHelper.LogType.Trace);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 如果强类型转换失败,尝试使用dynamic
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dynamic ssw = pptSlideShowWindowObj;
|
||||||
|
int hwndVal = ssw.HWND;
|
||||||
|
hwnd = new IntPtr(hwndVal);
|
||||||
|
LogHelper.WriteLogToFile($"从SlideShowWindow获取窗口句柄成功(dynamic): {hwnd}", LogHelper.LogType.Trace);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"从SlideShowWindow获取窗口句柄失败: {ex.Message}", LogHelper.LogType.Trace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"从SlideShowWindow获取窗口句柄异常: {ex.Message}", LogHelper.LogType.Trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hwnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过窗口标题匹配获取PPT窗口句柄(备用方法)
|
||||||
|
/// </summary>
|
||||||
|
private IntPtr GetPptHwndWin32(string presFullName, string appName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 步骤 A: 基础参数校验
|
||||||
|
if (string.IsNullOrWhiteSpace(presFullName) || string.IsNullOrWhiteSpace(appName))
|
||||||
|
{
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤 B: 提取关键信息 (应用类型 & 文件名)
|
||||||
|
string targetAppKeyword;
|
||||||
|
if (appName.IndexOf("WPS", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||||
|
{
|
||||||
|
targetAppKeyword = "WPS";
|
||||||
|
}
|
||||||
|
else if (appName.IndexOf("PowerPoint", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||||
|
{
|
||||||
|
targetAppKeyword = "PowerPoint";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 既不是 WPS 也不是 PowerPoint,视为不支持
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从路径中安全提取文件名(包含扩展名),如 "myppt.pptx"
|
||||||
|
string targetFileName = System.IO.Path.GetFileName(presFullName);
|
||||||
|
if (string.IsNullOrWhiteSpace(targetFileName))
|
||||||
|
{
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤 C: 枚举窗口并查找匹配项
|
||||||
|
List<IntPtr> candidates = new List<IntPtr>();
|
||||||
|
|
||||||
|
// 调用 EnumWindows,使用 Lambda 表达式直接嵌入回调逻辑
|
||||||
|
EnumWindows((hWnd, lParam) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// [安全过滤] 1. 忽略不可见窗口
|
||||||
|
if (!IsWindowVisible(hWnd)) return true;
|
||||||
|
|
||||||
|
// [安全获取] 2. 获取窗口标题长度
|
||||||
|
int length = GetWindowTextLength(hWnd);
|
||||||
|
if (length == 0) return true;
|
||||||
|
|
||||||
|
// [安全获取] 3. 获取窗口标题文本
|
||||||
|
StringBuilder sb = new StringBuilder(length + 1);
|
||||||
|
GetWindowText(hWnd, sb, sb.Capacity);
|
||||||
|
string title = sb.ToString();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(title)) return true;
|
||||||
|
|
||||||
|
// [核心匹配] 4. 判断标题是否同时包含 "文件名" 和 "应用关键字"
|
||||||
|
bool hasFileName = title.IndexOf(targetFileName, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||||
|
bool hasAppKey = title.IndexOf(targetAppKeyword, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||||
|
|
||||||
|
if (hasFileName && hasAppKey)
|
||||||
|
{
|
||||||
|
candidates.Add(hWnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 继续枚举其他窗口
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// 回调内部容错,忽略单个窗口获取信息的错误,继续枚举
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}, IntPtr.Zero);
|
||||||
|
|
||||||
|
// 步骤 D: 结果判定
|
||||||
|
// 只有当匹配到的窗口数量 唯一 (Count == 1) 时才返回句柄
|
||||||
|
// 0 个表示没找到,>1 个表示有歧义(无法确定是哪一个),均视为失败
|
||||||
|
if (candidates.Count == 1)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"通过窗口标题匹配获取窗口句柄成功: {candidates[0]}", LogHelper.LogType.Trace);
|
||||||
|
return candidates[0];
|
||||||
|
}
|
||||||
|
else if (candidates.Count > 1)
|
||||||
|
{
|
||||||
|
LogHelper.WriteLogToFile($"通过窗口标题匹配找到多个候选窗口({candidates.Count}个),无法确定唯一窗口", LogHelper.LogType.Trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// 发生任何不可预知的异常(如Path解析错误等),返回安全值
|
||||||
|
LogHelper.WriteLogToFile($"GetPptHwndWin32异常: {ex.Message}", LogHelper.LogType.Trace);
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Dispose
|
#region Dispose
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user