This commit is contained in:
2025-07-21 20:30:07 +08:00
parent bdc4af7cd4
commit 28fc53799a
2 changed files with 103 additions and 285 deletions
+20 -104
View File
@@ -2,6 +2,8 @@
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace Ink_Canvas.Helpers namespace Ink_Canvas.Helpers
{ {
@@ -23,44 +25,6 @@ namespace Ink_Canvas.Helpers
[DllImport("user32.dll")] [DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("shell32.dll")]
private static extern IntPtr SHAppBarMessage(uint dwMessage, ref APPBARDATA pData);
[DllImport("user32.dll")]
private static extern int SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);
[DllImport("user32.dll")]
private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);
[DllImport("user32.dll")]
private static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
private const uint ABM_GETTASKBARPOS = 0x00000005;
private const uint ABM_GETSTATE = 0x00000004;
private const int SPI_GETWORKAREA = 0x0030;
private const uint MONITOR_DEFAULTTOPRIMARY = 1;
private const int ABS_AUTOHIDE = 0x0000001;
[StructLayout(LayoutKind.Sequential)]
private struct MONITORINFO
{
public int cbSize;
public RECT rcMonitor;
public RECT rcWork;
public uint dwFlags;
}
[StructLayout(LayoutKind.Sequential)]
private struct APPBARDATA
{
public int cbSize;
public IntPtr hWnd;
public uint uCallbackMessage;
public uint uEdge;
public RECT rc;
public IntPtr lParam;
}
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct RECT { public struct RECT {
public int Left; public int Left;
@@ -72,72 +36,6 @@ namespace Ink_Canvas.Helpers
public int Height => Bottom - Top; public int Height => Bottom - Top;
} }
/// <summary>
/// 获取Windows任务栏的高度(仅计算任务栏,不包括其他应用的停靠栏)
/// </summary>
/// <param name="screen">当前屏幕</param>
/// <param name="dpiScaleY">DPI缩放Y值</param>
/// <returns>任务栏高度</returns>
public static double GetTaskbarHeight(System.Windows.Forms.Screen screen, double dpiScaleY)
{
try
{
// 创建APPBARDATA结构
var abd = new APPBARDATA();
abd.cbSize = Marshal.SizeOf(abd);
// 获取任务栏状态
IntPtr state = SHAppBarMessage(ABM_GETSTATE, ref abd);
bool isAutoHide = (state.ToInt32() & ABS_AUTOHIDE) == ABS_AUTOHIDE;
// 如果任务栏是自动隐藏的,返回0
if (isAutoHide)
{
LogHelper.WriteLogToFile("任务栏处于自动隐藏状态", LogHelper.LogType.Info);
return 0;
}
// 获取任务栏信息
IntPtr result = SHAppBarMessage(ABM_GETTASKBARPOS, ref abd);
if (result != IntPtr.Zero)
{
RECT taskbarRect = abd.rc;
System.Drawing.Rectangle screenRect = screen.Bounds;
System.Drawing.Rectangle taskbarRectangle = new System.Drawing.Rectangle(taskbarRect.Left, taskbarRect.Top, taskbarRect.Width, taskbarRect.Height);
// 根据任务栏位置计算高度
int taskbarHeight = 0;
// 任务栏的uEdge: 0=左, 1=上, 2=右, 3=下
switch (abd.uEdge)
{
case 1: // 上
taskbarHeight = abd.rc.Height;
break;
case 3: // 下
taskbarHeight = abd.rc.Height;
break;
case 0: // 左
case 2: // 右
// 水平任务栏不影响高度
taskbarHeight = 0;
break;
}
// 考虑DPI缩放
return taskbarHeight / dpiScaleY;
}
}
catch (Exception ex)
{
Debug.WriteLine($"获取任务栏高度出错: {ex.Message}");
LogHelper.WriteLogToFile($"获取任务栏高度出错: {ex.Message}", LogHelper.LogType.Error);
}
// 如果获取失败,回退到通用方法
return (screen.Bounds.Height - screen.WorkingArea.Height) / dpiScaleY;
}
public static string WindowTitle() { public static string WindowTitle() {
IntPtr foregroundWindowHandle = GetForegroundWindow(); IntPtr foregroundWindowHandle = GetForegroundWindow();
@@ -197,5 +95,23 @@ namespace Ink_Canvas.Helpers
return "Unknown"; return "Unknown";
} }
} }
public static int GetTaskbarHeight(Screen screen, double dpiScaleY)
{
// 优先用工作区和屏幕区的差值法,兼容多屏
int height = 0;
if (screen.Bounds.Height > screen.WorkingArea.Height)
{
// 任务栏在上下
height = screen.Bounds.Height - screen.WorkingArea.Height;
}
else if (screen.Bounds.Width > screen.WorkingArea.Width)
{
// 任务栏在左右
height = screen.Bounds.Width - screen.WorkingArea.Width;
}
// 考虑DPI缩放
return (int)(height / dpiScaleY);
}
} }
} }
+12 -110
View File
@@ -949,41 +949,27 @@ namespace Ink_Canvas {
LogHelper.WriteLogToFile("幻灯片放映窗口或视图为空", LogHelper.LogType.Warning); LogHelper.WriteLogToFile("幻灯片放映窗口或视图为空", LogHelper.LogType.Warning);
return; return;
} }
LogHelper.WriteLogToFile($"PowerPoint Next Slide (Slide {Wn.View.CurrentShowPosition})", LogHelper.WriteLogToFile($"PowerPoint Next Slide (Slide {Wn.View.CurrentShowPosition})",
LogHelper.LogType.Event); LogHelper.LogType.Event);
if (Wn.View.CurrentShowPosition == previousSlideID) return; // 先保存旧页墨迹
Application.Current.Dispatcher.Invoke(() => { Application.Current.Dispatcher.Invoke(() => {
try {
var ms = new MemoryStream(); var ms = new MemoryStream();
inkCanvas.Strokes.Save(ms); inkCanvas.Strokes.Save(ms);
ms.Position = 0; ms.Position = 0;
if (previousSlideID > 0 && previousSlideID < memoryStreams.Length)
memoryStreams[previousSlideID] = ms; memoryStreams[previousSlideID] = ms;
if (inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber &&
Settings.PowerPointSettings.IsAutoSaveScreenShotInPowerPoint && !_isPptClickingBtnTurned)
SaveScreenShot(true, Wn.Presentation.Name + "/" + Wn.View.CurrentShowPosition);
_isPptClickingBtnTurned = false;
ClearStrokes(true); ClearStrokes(true);
timeMachine.ClearStrokeHistory(); timeMachine.ClearStrokeHistory();
int newPage = Wn.View.CurrentShowPosition;
if (memoryStreams[Wn.View.CurrentShowPosition] != null && if (newPage > 0 && newPage < memoryStreams.Length &&
memoryStreams[Wn.View.CurrentShowPosition].Length > 0) { memoryStreams[newPage] != null && memoryStreams[newPage].Length > 0) {
memoryStreams[Wn.View.CurrentShowPosition].Position = 0; memoryStreams[newPage].Position = 0;
inkCanvas.Strokes.Add(new StrokeCollection(memoryStreams[Wn.View.CurrentShowPosition])); inkCanvas.Strokes.Add(new StrokeCollection(memoryStreams[newPage]));
} }
PPTBtnPageNow.Text = $"{Wn.View.CurrentShowPosition}"; PPTBtnPageNow.Text = $"{Wn.View.CurrentShowPosition}";
PPTBtnPageTotal.Text = $"/ {Wn.Presentation.Slides.Count}"; PPTBtnPageTotal.Text = $"/ {Wn.Presentation.Slides.Count}";
} previousSlideID = newPage; // 最后赋值,确保索引同步
catch (Exception ex) {
LogHelper.WriteLogToFile($"处理幻灯片切换时出错: {ex.ToString()}", LogHelper.LogType.Error);
}
}); });
previousSlideID = Wn.View.CurrentShowPosition;
} }
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"幻灯片切换事件处理失败: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"幻灯片切换事件处理失败: {ex.ToString()}", LogHelper.LogType.Error);
@@ -993,28 +979,16 @@ namespace Ink_Canvas {
private bool _isPptClickingBtnTurned = false; private bool _isPptClickingBtnTurned = false;
private void BtnPPTSlidesUp_Click(object sender, RoutedEventArgs e) { private void BtnPPTSlidesUp_Click(object sender, RoutedEventArgs e) {
if (currentMode == 1) {
GridBackgroundCover.Visibility = Visibility.Collapsed;
AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
currentMode = 0;
}
// 切换前同步保存墨迹
Application.Current.Dispatcher.Invoke(() => { Application.Current.Dispatcher.Invoke(() => {
// 切换前同步保存墨迹
SaveCurrentSlideInkStrokes(); SaveCurrentSlideInkStrokes();
});
_isPptClickingBtnTurned = true; _isPptClickingBtnTurned = true;
// 添加安全检查 // 添加安全检查
if (pptApplication == null) if (pptApplication == null)
{ {
LogHelper.WriteLogToFile("PPT应用程序为空,无法执行上一页操作", LogHelper.LogType.Warning); LogHelper.WriteLogToFile("PPT应用程序为空,无法执行上一页操作", LogHelper.LogType.Warning);
return; return;
} }
try try
{ {
// 检查SlideShowWindows是否存在且有效 // 检查SlideShowWindows是否存在且有效
@@ -1023,7 +997,6 @@ namespace Ink_Canvas {
LogHelper.WriteLogToFile("PPT放映窗口不存在,无法执行上一页操作", LogHelper.LogType.Warning); LogHelper.WriteLogToFile("PPT放映窗口不存在,无法执行上一页操作", LogHelper.LogType.Warning);
return; return;
} }
// 安全访问当前幻灯片信息 // 安全访问当前幻灯片信息
if (pptApplication.SlideShowWindows.Count >= 1) if (pptApplication.SlideShowWindows.Count >= 1)
{ {
@@ -1035,41 +1008,11 @@ namespace Ink_Canvas {
SaveScreenShot(true, SaveScreenShot(true,
slideShowWindow.Presentation.Name + "/" + slideShowWindow.Presentation.Name + "/" +
slideShowWindow.View.CurrentShowPosition); slideShowWindow.View.CurrentShowPosition);
}
}
new Thread(new ThreadStart(() => {
try {
// 安全访问SlideShowWindows[1]
if (pptApplication.SlideShowWindows.Count >= 1)
{
var slideShowWindow = pptApplication.SlideShowWindows[1];
if (slideShowWindow != null)
{
slideShowWindow.Activate(); slideShowWindow.Activate();
}
}
}
catch (Exception ex) {
LogHelper.WriteLogToFile($"激活PPT放映窗口失败: {ex.ToString()}", LogHelper.LogType.Error);
}
try {
// 安全访问SlideShowWindows[1]
if (pptApplication.SlideShowWindows.Count >= 1)
{
var slideShowWindow = pptApplication.SlideShowWindows[1];
if (slideShowWindow != null && slideShowWindow.View != null)
{
slideShowWindow.View.Previous(); slideShowWindow.View.Previous();
} }
} }
} }
catch (Exception ex) {
LogHelper.WriteLogToFile($"PPT上一页操作失败: {ex.ToString()}", LogHelper.LogType.Error);
} // Without this catch{}, app will crash when click the pre-page button in the fir page in some special env.
})).Start();
}
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"PPT上一页操作异常: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"PPT上一页操作异常: {ex.ToString()}", LogHelper.LogType.Error);
StackPanelPPTControls.Visibility = Visibility.Collapsed; StackPanelPPTControls.Visibility = Visibility.Collapsed;
@@ -1078,31 +1021,20 @@ namespace Ink_Canvas {
LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed; LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed; RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
} }
});
} }
private void BtnPPTSlidesDown_Click(object sender, RoutedEventArgs e) { private void BtnPPTSlidesDown_Click(object sender, RoutedEventArgs e) {
if (currentMode == 1) {
GridBackgroundCover.Visibility = Visibility.Collapsed;
AnimationsHelper.HideWithSlideAndFade(BlackboardLeftSide);
AnimationsHelper.HideWithSlideAndFade(BlackboardCenterSide);
AnimationsHelper.HideWithSlideAndFade(BlackboardRightSide);
currentMode = 0;
}
// 切换前同步保存墨迹
Application.Current.Dispatcher.Invoke(() => { Application.Current.Dispatcher.Invoke(() => {
// 切换前同步保存墨迹
SaveCurrentSlideInkStrokes(); SaveCurrentSlideInkStrokes();
});
_isPptClickingBtnTurned = true; _isPptClickingBtnTurned = true;
// 添加安全检查 // 添加安全检查
if (pptApplication == null) if (pptApplication == null)
{ {
LogHelper.WriteLogToFile("PPT应用程序为空,无法执行下一页操作", LogHelper.LogType.Warning); LogHelper.WriteLogToFile("PPT应用程序为空,无法执行下一页操作", LogHelper.LogType.Warning);
return; return;
} }
try try
{ {
// 检查SlideShowWindows是否存在且有效 // 检查SlideShowWindows是否存在且有效
@@ -1111,7 +1043,6 @@ namespace Ink_Canvas {
LogHelper.WriteLogToFile("PPT放映窗口不存在,无法执行下一页操作", LogHelper.LogType.Warning); LogHelper.WriteLogToFile("PPT放映窗口不存在,无法执行下一页操作", LogHelper.LogType.Warning);
return; return;
} }
// 安全访问当前幻灯片信息 // 安全访问当前幻灯片信息
if (pptApplication.SlideShowWindows.Count >= 1) if (pptApplication.SlideShowWindows.Count >= 1)
{ {
@@ -1123,41 +1054,11 @@ namespace Ink_Canvas {
SaveScreenShot(true, SaveScreenShot(true,
slideShowWindow.Presentation.Name + "/" + slideShowWindow.Presentation.Name + "/" +
slideShowWindow.View.CurrentShowPosition); slideShowWindow.View.CurrentShowPosition);
}
}
new Thread(new ThreadStart(() => {
try {
// 安全访问SlideShowWindows[1]
if (pptApplication.SlideShowWindows.Count >= 1)
{
var slideShowWindow = pptApplication.SlideShowWindows[1];
if (slideShowWindow != null)
{
slideShowWindow.Activate(); slideShowWindow.Activate();
}
}
}
catch (Exception ex) {
LogHelper.WriteLogToFile($"激活PPT放映窗口失败: {ex.ToString()}", LogHelper.LogType.Error);
}
try {
// 安全访问SlideShowWindows[1]
if (pptApplication.SlideShowWindows.Count >= 1)
{
var slideShowWindow = pptApplication.SlideShowWindows[1];
if (slideShowWindow != null && slideShowWindow.View != null)
{
slideShowWindow.View.Next(); slideShowWindow.View.Next();
} }
} }
} }
catch (Exception ex) {
LogHelper.WriteLogToFile($"PPT下一页操作失败: {ex.ToString()}", LogHelper.LogType.Error);
}
})).Start();
}
catch (Exception ex) { catch (Exception ex) {
LogHelper.WriteLogToFile($"PPT下一页操作异常: {ex.ToString()}", LogHelper.LogType.Error); LogHelper.WriteLogToFile($"PPT下一页操作异常: {ex.ToString()}", LogHelper.LogType.Error);
StackPanelPPTControls.Visibility = Visibility.Collapsed; StackPanelPPTControls.Visibility = Visibility.Collapsed;
@@ -1166,6 +1067,7 @@ namespace Ink_Canvas {
LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed; LeftSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed; RightSidePanelForPPTNavigation.Visibility = Visibility.Collapsed;
} }
});
} }
private async void PPTNavigationBtn_MouseDown(object sender, MouseButtonEventArgs e) private async void PPTNavigationBtn_MouseDown(object sender, MouseButtonEventArgs e)