improve:PPT侧边面板

This commit is contained in:
2026-01-10 20:09:20 +08:00
parent 221a0f8e85
commit be6eb73671
2 changed files with 418 additions and 33 deletions
+47 -21
View File
@@ -170,27 +170,52 @@
</Separator.Background> </Separator.Background>
</Separator> </Separator>
<!-- 图片插入按钮 --> <!-- 图片插入按钮区域 -->
<Button x:Name="InsertImageButton" <StackPanel Orientation="Vertical" Margin="0,0,0,8">
Content="插入图片" <!-- 选择文件按钮 -->
FontSize="11" <Button x:Name="InsertImageSelectFileButton"
Height="30" Content="选择文件"
Background="#3b82f6" FontSize="11"
Foreground="White" Height="30"
BorderThickness="0" Background="#3b82f6"
Cursor="Hand" Foreground="White"
Click="InsertImageButton_Click" BorderThickness="0"
Margin="0,0,0,8"> Cursor="Hand"
<Button.Template> Click="InsertImageSelectFileButton_Click"
<ControlTemplate TargetType="Button"> Margin="0,0,0,4">
<Border Background="{TemplateBinding Background}" <Button.Template>
CornerRadius="4" <ControlTemplate TargetType="Button">
Padding="{TemplateBinding Padding}"> <Border Background="{TemplateBinding Background}"
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> CornerRadius="4"
</Border> Padding="{TemplateBinding Padding}">
</ControlTemplate> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Button.Template> </Border>
</Button> </ControlTemplate>
</Button.Template>
</Button>
<!-- 截图插入按钮 -->
<Button x:Name="InsertImageScreenshotButton"
Content="截图插入"
FontSize="11"
Height="30"
Background="#3b82f6"
Foreground="White"
BorderThickness="0"
Cursor="Hand"
Click="InsertImageScreenshotButton_Click"
Margin="0,0,0,0">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="4"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
<!-- 聚焦放大镜(暂未设计)- 暂时隐藏 --> <!-- 聚焦放大镜(暂未设计)- 暂时隐藏 -->
<Border x:Name="MagnifierSection" Margin="0,0,0,8" Visibility="Collapsed"> <Border x:Name="MagnifierSection" Margin="0,0,0,8" Visibility="Collapsed">
@@ -216,3 +241,4 @@
</Grid> </Grid>
</UserControl> </UserControl>
+371 -12
View File
@@ -1,6 +1,7 @@
using Ink_Canvas.Helpers; using Ink_Canvas.Helpers;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -9,6 +10,7 @@ using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Animation; using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading; using System.Windows.Threading;
using Microsoft.Win32; using Microsoft.Win32;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -134,16 +136,128 @@ namespace Ink_Canvas.Windows
// 获取MainWindow引用 // 获取MainWindow引用
_mainWindow = Application.Current.MainWindow as MainWindow; _mainWindow = Application.Current.MainWindow as MainWindow;
// 订阅PPT事件
SubscribeToPPTEvents(); SubscribeToPPTEvents();
SubscribeToInkCanvasChildrenChanges();
// 延迟初始化音量显示,确保音频设备已初始化
Dispatcher.BeginInvoke(new Action(() => Dispatcher.BeginInvoke(new Action(() =>
{ {
UpdateVolumeDisplay(); UpdateVolumeDisplay();
}), DispatcherPriority.Loaded); }), DispatcherPriority.Loaded);
} }
private void SubscribeToInkCanvasChildrenChanges()
{
try
{
if (_mainWindow == null) return;
System.Windows.Controls.InkCanvas inkCanvas = null;
var inkCanvasField = _mainWindow.GetType().GetField("inkCanvas",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
if (inkCanvasField != null)
{
inkCanvas = inkCanvasField.GetValue(_mainWindow) as System.Windows.Controls.InkCanvas;
}
if (inkCanvas == null)
{
var inkCanvasProperty = _mainWindow.GetType().GetProperty("inkCanvas",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
inkCanvas = inkCanvasProperty?.GetValue(_mainWindow) as System.Windows.Controls.InkCanvas;
}
if (inkCanvas != null && inkCanvas.Children is INotifyCollectionChanged notifyCollection)
{
notifyCollection.CollectionChanged += InkCanvasChildren_CollectionChanged;
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"订阅inkCanvas.Children变化事件失败: {ex.Message}", LogHelper.LogType.Error);
}
}
private void InkCanvasChildren_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
try
{
if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (var item in e.OldItems)
{
if (item is System.Windows.Controls.Image image)
{
RemoveImageFromPPT(image);
}
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理inkCanvas.Children变化失败: {ex.Message}", LogHelper.LogType.Error);
}
}
private void RemoveImageFromPPT(System.Windows.Controls.Image image)
{
try
{
if (image == null) return;
if (_pptImages.ContainsKey(image))
{
int slideNumber = _pptImages[image];
_pptImages.Remove(image);
if (_pptImagePaths.ContainsKey(slideNumber))
{
string imagePath = image.Tag as string;
if (!string.IsNullOrEmpty(imagePath) && _pptImagePaths[slideNumber].Contains(imagePath))
{
_pptImagePaths[slideNumber].Remove(imagePath);
if (_pptImagePaths[slideNumber].Count == 0)
{
_pptImagePaths.Remove(slideNumber);
DeletePPTImagePathsFile(slideNumber);
}
else
{
SavePPTImagePaths(slideNumber);
}
LogHelper.WriteLogToFile($"已从PPT页面{slideNumber}移除图片: {imagePath}");
}
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"从PPT关联数据中移除图片失败: {ex.Message}", LogHelper.LogType.Error);
}
}
private void DeletePPTImagePathsFile(int slideIndex)
{
try
{
if (slideIndex <= 0) return;
var folderPath = GetPresentationFolderPath();
if (string.IsNullOrEmpty(folderPath) || !Directory.Exists(folderPath))
return;
var jsonFilePath = Path.Combine(folderPath, slideIndex.ToString("0000") + ".images.json");
if (File.Exists(jsonFilePath))
{
File.Delete(jsonFilePath);
LogHelper.WriteLogToFile($"已删除第{slideIndex}页图片路径JSON文件: {jsonFilePath}");
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"删除PPT图片路径JSON文件失败: {ex.Message}", LogHelper.LogType.Error);
}
}
private void SubscribeToPPTEvents() private void SubscribeToPPTEvents()
{ {
try try
@@ -359,6 +473,38 @@ namespace Ink_Canvas.Windows
private void PPTQuickPanel_Unloaded(object sender, RoutedEventArgs e) private void PPTQuickPanel_Unloaded(object sender, RoutedEventArgs e)
{ {
SystemEvents.UserPreferenceChanged -= SystemEvents_UserPreferenceChanged; SystemEvents.UserPreferenceChanged -= SystemEvents_UserPreferenceChanged;
UnsubscribeFromInkCanvasChildrenChanges();
}
private void UnsubscribeFromInkCanvasChildrenChanges()
{
try
{
if (_mainWindow == null) return;
System.Windows.Controls.InkCanvas inkCanvas = null;
var inkCanvasField = _mainWindow.GetType().GetField("inkCanvas",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
if (inkCanvasField != null)
{
inkCanvas = inkCanvasField.GetValue(_mainWindow) as System.Windows.Controls.InkCanvas;
}
if (inkCanvas == null)
{
var inkCanvasProperty = _mainWindow.GetType().GetProperty("inkCanvas",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
inkCanvas = inkCanvasProperty?.GetValue(_mainWindow) as System.Windows.Controls.InkCanvas;
}
if (inkCanvas != null && inkCanvas.Children is INotifyCollectionChanged notifyCollection)
{
notifyCollection.CollectionChanged -= InkCanvasChildren_CollectionChanged;
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"取消订阅inkCanvas.Children变化事件失败: {ex.Message}", LogHelper.LogType.Error);
}
} }
private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
@@ -775,13 +921,12 @@ namespace Ink_Canvas.Windows
#region #region
private async void InsertImageButton_Click(object sender, RoutedEventArgs e) private async void InsertImageSelectFileButton_Click(object sender, RoutedEventArgs e)
{ {
if (_mainWindow == null) return; if (_mainWindow == null) return;
try try
{ {
// 调用MainWindow的图片插入功能
var dialog = new OpenFileDialog var dialog = new OpenFileDialog
{ {
Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif" Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif"
@@ -791,7 +936,6 @@ namespace Ink_Canvas.Windows
{ {
string filePath = dialog.FileName; string filePath = dialog.FileName;
// 使用反射调用MainWindow的CreateAndCompressImageAsync方法
var createImageMethod = _mainWindow.GetType().GetMethod("CreateAndCompressImageAsync", var createImageMethod = _mainWindow.GetType().GetMethod("CreateAndCompressImageAsync",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
@@ -804,8 +948,6 @@ namespace Ink_Canvas.Windows
if (image != null) if (image != null)
{ {
image.Tag = filePath; image.Tag = filePath;
// 使用反射调用MainWindow的图片插入相关方法
await InsertImageToMainWindow(image, filePath); await InsertImageToMainWindow(image, filePath);
} }
} }
@@ -822,6 +964,227 @@ namespace Ink_Canvas.Windows
} }
} }
private async void InsertImageScreenshotButton_Click(object sender, RoutedEventArgs e)
{
if (_mainWindow == null) return;
try
{
var captureScreenshotMethod = _mainWindow.GetType().GetMethod("CaptureScreenshotAndInsert",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (captureScreenshotMethod != null)
{
var task = captureScreenshotMethod.Invoke(_mainWindow, null) as System.Threading.Tasks.Task;
if (task != null)
{
await task;
await SaveScreenshotToPPT();
}
}
else
{
LogHelper.WriteLogToFile("无法找到CaptureScreenshotAndInsert方法", LogHelper.LogType.Warning);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"截图插入失败: {ex.Message}", LogHelper.LogType.Error);
}
}
private async System.Threading.Tasks.Task SaveScreenshotToPPT()
{
try
{
if (_mainWindow == null) return;
System.Windows.Controls.InkCanvas inkCanvas = null;
var inkCanvasField = _mainWindow.GetType().GetField("inkCanvas",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
if (inkCanvasField != null)
{
inkCanvas = inkCanvasField.GetValue(_mainWindow) as System.Windows.Controls.InkCanvas;
}
if (inkCanvas == null)
{
var inkCanvasProperty = _mainWindow.GetType().GetProperty("inkCanvas",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
inkCanvas = inkCanvasProperty?.GetValue(_mainWindow) as System.Windows.Controls.InkCanvas;
}
if (inkCanvas == null) return;
System.Windows.Controls.Image lastScreenshot = null;
foreach (System.Windows.Controls.Image img in inkCanvas.Children.OfType<System.Windows.Controls.Image>())
{
if (img.Name != null && (img.Name.StartsWith("screenshot_") || img.Name.StartsWith("camera_")) && img.Tag == null)
{
lastScreenshot = img;
}
}
if (lastScreenshot == null) return;
string screenshotFilePath = await SaveScreenshotToFile(lastScreenshot);
if (string.IsNullOrEmpty(screenshotFilePath))
{
LogHelper.WriteLogToFile("保存截图文件失败", LogHelper.LogType.Warning);
return;
}
lastScreenshot.Tag = screenshotFilePath;
await ManageScreenshotInPPT(lastScreenshot, screenshotFilePath);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"保存截图到PPT失败: {ex.Message}", LogHelper.LogType.Error);
}
}
private async System.Threading.Tasks.Task<string> SaveScreenshotToFile(System.Windows.Controls.Image image)
{
try
{
if (image?.Source == null) return null;
string savePath = null;
var settingsProperty = _mainWindow.GetType().GetProperty("Settings");
if (settingsProperty != null)
{
var settings = settingsProperty.GetValue(_mainWindow);
if (settings != null)
{
var autoSavedStrokesLocationProperty = settings.GetType().GetProperty("Automation");
if (autoSavedStrokesLocationProperty != null)
{
var automation = autoSavedStrokesLocationProperty.GetValue(settings);
if (automation != null)
{
var locationProperty = automation.GetType().GetProperty("AutoSavedStrokesLocation");
if (locationProperty != null)
{
var location = locationProperty.GetValue(automation) as string;
if (!string.IsNullOrEmpty(location))
{
savePath = Path.Combine(location, "File Dependency");
}
}
}
}
}
}
if (string.IsNullOrEmpty(savePath))
{
LogHelper.WriteLogToFile("无法获取AutoSavedStrokesLocation", LogHelper.LogType.Warning);
return null;
}
if (!Directory.Exists(savePath))
{
Directory.CreateDirectory(savePath);
}
string timestamp = image.Name;
string filePath = Path.Combine(savePath, timestamp + ".png");
await Application.Current.Dispatcher.InvokeAsync(() =>
{
if (image.Source is BitmapSource bitmapSource)
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
encoder.Save(fileStream);
}
}
});
return filePath;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"保存截图到文件失败: {ex.Message}", LogHelper.LogType.Error);
return null;
}
}
private async System.Threading.Tasks.Task ManageScreenshotInPPT(System.Windows.Controls.Image image, string filePath)
{
if (_mainWindow == null || image == null || string.IsNullOrEmpty(filePath)) return;
await Application.Current.Dispatcher.InvokeAsync(() =>
{
try
{
int currentSlideNumber = 0;
try
{
var pptManagerProperty = _mainWindow.GetType().GetProperty("PPTManager",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
var pptManager = pptManagerProperty?.GetValue(_mainWindow);
if (pptManager != null)
{
var isInSlideShowProperty = pptManager.GetType().GetProperty("IsInSlideShow");
bool isInSlideShow = false;
if (isInSlideShowProperty != null)
{
var result = isInSlideShowProperty.GetValue(pptManager);
if (result != null)
{
isInSlideShow = (bool)result;
}
}
if (isInSlideShow)
{
var getCurrentSlideNumberMethod = pptManager.GetType().GetMethod("GetCurrentSlideNumber");
if (getCurrentSlideNumberMethod != null)
{
var result = getCurrentSlideNumberMethod.Invoke(pptManager, null);
if (result != null)
{
currentSlideNumber = (int)result;
}
}
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"获取当前PPT页面编号失败: {ex.Message}", LogHelper.LogType.Warning);
}
if (currentSlideNumber > 0 && !string.IsNullOrEmpty(filePath))
{
_pptImages[image] = currentSlideNumber;
if (!_pptImagePaths.ContainsKey(currentSlideNumber))
{
_pptImagePaths[currentSlideNumber] = new List<string>();
}
_pptImagePaths[currentSlideNumber].Add(filePath);
SavePPTImagePaths(currentSlideNumber);
LogHelper.WriteLogToFile($"截图已关联到PPT页面{currentSlideNumber}: {filePath}");
}
else if (currentSlideNumber > 0)
{
_pptImages[image] = currentSlideNumber;
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"管理截图在PPT中的关联失败: {ex.Message}", LogHelper.LogType.Error);
}
}, DispatcherPriority.Normal);
}
private async System.Threading.Tasks.Task InsertImageToMainWindow(System.Windows.Controls.Image image, string originalFilePath = null, bool saveToJson = true) private async System.Threading.Tasks.Task InsertImageToMainWindow(System.Windows.Controls.Image image, string originalFilePath = null, bool saveToJson = true)
{ {
if (_mainWindow == null || image == null) return; if (_mainWindow == null || image == null) return;
@@ -839,10 +1202,7 @@ namespace Ink_Canvas.Windows
image.IsHitTestVisible = true; image.IsHitTestVisible = true;
image.Focusable = false; image.Focusable = false;
// 获取inkCanvas - 尝试字段和属性两种方式
System.Windows.Controls.InkCanvas inkCanvas = null; System.Windows.Controls.InkCanvas inkCanvas = null;
// 先尝试字段
var inkCanvasField = _mainWindow.GetType().GetField("inkCanvas", var inkCanvasField = _mainWindow.GetType().GetField("inkCanvas",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
if (inkCanvasField != null) if (inkCanvasField != null)
@@ -850,7 +1210,6 @@ namespace Ink_Canvas.Windows
inkCanvas = inkCanvasField.GetValue(_mainWindow) as System.Windows.Controls.InkCanvas; inkCanvas = inkCanvasField.GetValue(_mainWindow) as System.Windows.Controls.InkCanvas;
} }
// 如果字段获取失败,尝试属性
if (inkCanvas == null) if (inkCanvas == null)
{ {
var inkCanvasProperty = _mainWindow.GetType().GetProperty("inkCanvas", var inkCanvasProperty = _mainWindow.GetType().GetProperty("inkCanvas",