improve:仅PPT模式

This commit is contained in:
2026-04-05 14:58:32 +08:00
parent 4835e3db50
commit 8f3b65c6d4
2 changed files with 129 additions and 2 deletions
+7 -2
View File
@@ -1407,6 +1407,7 @@ namespace Ink_Canvas
// 检查模式设置并应用 // 检查模式设置并应用
CheckMainWindowVisibility(); CheckMainWindowVisibility();
EnsurePptOnlyVisibilityProbeTimer();
// 检查是否通过--board参数启动,如果是则自动切换到白板模式 // 检查是否通过--board参数启动,如果是则自动切换到白板模式
if (App.StartWithBoardMode) if (App.StartWithBoardMode)
@@ -4377,9 +4378,11 @@ namespace Ink_Canvas
{ {
Hide(); Hide();
LogHelper.WriteLogToFile("已切换到仅PPT模式,主窗口已隐藏", LogHelper.LogType.Event); LogHelper.WriteLogToFile("已切换到仅PPT模式,主窗口已隐藏", LogHelper.LogType.Event);
EnsurePptOnlyVisibilityProbeTimer();
} }
else else
{ {
StopPptOnlyVisibilityProbeTimer();
// 如果切换到正常模式,显示主窗口 // 如果切换到正常模式,显示主窗口
Show(); Show();
LogHelper.WriteLogToFile("已切换到正常模式,主窗口已显示", LogHelper.LogType.Event); LogHelper.WriteLogToFile("已切换到正常模式,主窗口已显示", LogHelper.LogType.Event);
@@ -4401,8 +4404,10 @@ namespace Ink_Canvas
{ {
if (Settings.ModeSettings.IsPPTOnlyMode) if (Settings.ModeSettings.IsPPTOnlyMode)
{ {
// 仅PPT模式下,只有在PPT放映时才显示 // 仅PPT模式:以 COM/UI 状态为主,Win32 检测全屏放映窗口(screenClass)作兜底,避免 COM 异常时无法唤出
bool isInSlideShow = BtnPPTSlideShowEnd.Visibility == Visibility.Visible; bool comUiSlideShow = BtnPPTSlideShowEnd.Visibility == Visibility.Visible;
bool win32SlideShow = IsPowerPointSlideshowSurfacePresentWin32();
bool isInSlideShow = comUiSlideShow || win32SlideShow;
if (isInSlideShow && !IsVisible) if (isInSlideShow && !IsVisible)
{ {
Show(); Show();
+122
View File
@@ -4,6 +4,7 @@ using Microsoft.Office.Core;
using Microsoft.Office.Interop.PowerPoint; using Microsoft.Office.Interop.PowerPoint;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@@ -167,6 +168,18 @@ namespace Ink_Canvas
/// 断开连接后退出PPT模式的延迟时间(毫秒),即连接断开后多长时间才退出PPT模式。 /// 断开连接后退出PPT模式的延迟时间(毫秒),即连接断开后多长时间才退出PPT模式。
/// </summary> /// </summary>
private const int ExitPPTModeAfterDisconnectDelayMs = 1200; private const int ExitPPTModeAfterDisconnectDelayMs = 1200;
/// <summary>
/// 仅PPT模式下周期性探测放映界面(COM 失效时依赖 Win32),间隔不宜过小以免多余开销。
/// </summary>
private DispatcherTimer _pptOnlyVisibilityProbeTimer;
private const int PptOnlyVisibilityProbeIntervalMs = 800;
/// <summary>
/// PowerPoint 全屏放映顶层窗口类名(与编辑态 PPTFrameClass 区分)。
/// </summary>
private const string PowerPointSlideShowWindowClassName = "screenClass";
#endregion #endregion
#region PPT Managers #region PPT Managers
@@ -638,6 +651,8 @@ namespace Ink_Canvas
ClosePowerPointApplication(); ClosePowerPointApplication();
ClearStaticInteropState(); ClearStaticInteropState();
StopPptOnlyVisibilityProbeTimer();
LogHelper.WriteLogToFile("PPT管理器已释放", LogHelper.LogType.Event); LogHelper.WriteLogToFile("PPT管理器已释放", LogHelper.LogType.Event);
} }
catch (Exception ex) catch (Exception ex)
@@ -700,6 +715,104 @@ namespace Ink_Canvas
} }
#endregion #endregion
#region PPT模式可见性COM + Win32
/// <summary>
/// 在启用「仅PPT模式」时启动轻量探测,COM 事件延迟或失效时仍可根据全屏放映窗口显示主窗口。
/// </summary>
internal void EnsurePptOnlyVisibilityProbeTimer()
{
try
{
if (!Settings.ModeSettings.IsPPTOnlyMode)
{
StopPptOnlyVisibilityProbeTimer();
return;
}
if (_pptOnlyVisibilityProbeTimer == null)
{
_pptOnlyVisibilityProbeTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(PptOnlyVisibilityProbeIntervalMs)
};
_pptOnlyVisibilityProbeTimer.Tick += (_, __) => CheckMainWindowVisibility();
}
if (!_pptOnlyVisibilityProbeTimer.IsEnabled)
_pptOnlyVisibilityProbeTimer.Start();
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"仅PPT可见性探测计时器启动失败: {ex.Message}", LogHelper.LogType.Warning);
}
}
internal void StopPptOnlyVisibilityProbeTimer()
{
try
{
_pptOnlyVisibilityProbeTimer?.Stop();
}
catch
{
}
}
/// <summary>
/// 检测是否存在 PowerPoint 全屏放映顶层窗口(类名 screenClass,进程 powerpnt),用于 COM 不可用时的兜底。
/// </summary>
internal bool IsPowerPointSlideshowSurfacePresentWin32()
{
if (!Settings.ModeSettings.IsPPTOnlyMode)
return false;
try
{
bool found = false;
EnumWindows((hWnd, _) =>
{
if (!IsWindow(hWnd) || !IsWindowVisible(hWnd))
return true;
var cls = new StringBuilder(256);
if (GetClassName(hWnd, cls, cls.Capacity) == 0)
return true;
if (!string.Equals(cls.ToString(), PowerPointSlideShowWindowClassName, StringComparison.OrdinalIgnoreCase))
return true;
try
{
GetWindowThreadProcessId(hWnd, out uint pid);
using (var proc = Process.GetProcessById((int)pid))
{
var name = proc.ProcessName;
if (string.Equals(name, "POWERPNT", StringComparison.OrdinalIgnoreCase))
{
found = true;
return false;
}
}
}
catch
{
}
return true;
}, IntPtr.Zero);
return found;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"Win32 检测 PPT 放映窗口失败: {ex.Message}", LogHelper.LogType.Trace);
return false;
}
}
#endregion
#region New PPT Event Handlers #region New PPT Event Handlers
/// <summary> /// <summary>
/// 处理 PowerPoint 连接状态的变更:更新界面连接/放映状态,并在断开时启动一个短延迟以安全退出 PPT 模式。 /// 处理 PowerPoint 连接状态的变更:更新界面连接/放映状态,并在断开时启动一个短延迟以安全退出 PPT 模式。
@@ -731,6 +844,8 @@ namespace Ink_Canvas
_ = HandleManualSlideShowEnd(); _ = HandleManualSlideShowEnd();
if (Settings.PowerPointSettings.UseRotPptLink) if (Settings.PowerPointSettings.UseRotPptLink)
_pptManager?.ReloadConnection(); _pptManager?.ReloadConnection();
CheckMainWindowVisibility();
} }
}); });
} }
@@ -1114,6 +1229,9 @@ namespace Ink_Canvas
// 加载当前页墨迹 // 加载当前页墨迹
LoadCurrentSlideInk(currentSlide); LoadCurrentSlideInk(currentSlide);
// 仅PPT模式:放映开始立即同步主窗口可见性(勿仅依赖 SlideShowStateChanged 定时器)
CheckMainWindowVisibility();
}); });
if (!isFloatingBarFolded) if (!isFloatingBarFolded)
@@ -1435,6 +1553,8 @@ namespace Ink_Canvas
UpdateCurrentToolMode("cursor"); UpdateCurrentToolMode("cursor");
SetFloatingBarHighlightPosition("cursor"); SetFloatingBarHighlightPosition("cursor");
CheckMainWindowVisibility();
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -2291,6 +2411,7 @@ namespace Ink_Canvas
_pptUIManager?.UpdateSlideShowStatus(false); _pptUIManager?.UpdateSlideShowStatus(false);
_pptUIManager?.UpdateSidebarExitButtons(false); _pptUIManager?.UpdateSidebarExitButtons(false);
LogHelper.WriteLogToFile("手动更新放映结束UI状态", LogHelper.LogType.Trace); LogHelper.WriteLogToFile("手动更新放映结束UI状态", LogHelper.LogType.Trace);
CheckMainWindowVisibility();
}); });
// 手动处理自动收纳,因为OnPPTSlideShowEnd事件可能未触发 // 手动处理自动收纳,因为OnPPTSlideShowEnd事件可能未触发
@@ -2323,6 +2444,7 @@ namespace Ink_Canvas
{ {
_pptUIManager?.UpdateSlideShowStatus(false); _pptUIManager?.UpdateSlideShowStatus(false);
_pptUIManager?.UpdateSidebarExitButtons(false); _pptUIManager?.UpdateSidebarExitButtons(false);
CheckMainWindowVisibility();
}); });
// 异常情况下也手动处理自动收纳 // 异常情况下也手动处理自动收纳