add:pdf插入

This commit is contained in:
2026-04-05 17:31:35 +08:00
parent 1165e5bbf2
commit c77beb662e
9 changed files with 701 additions and 207 deletions
+136
View File
@@ -0,0 +1,136 @@
using Ink_Canvas.Helpers;
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Ink_Canvas.Controls
{
/// <summary>
/// 画布上的多页 PDF:仅显示当前页;翻页与页码由主窗口 PDF 侧栏控制(无 XAML 文件)。
/// </summary>
public class PdfEmbeddedView : UserControl
{
private readonly Image _pageImage;
private string _pdfPath;
private uint _pageCount;
private uint _currentIndex;
private bool _compressLargePictures;
private bool _isPagingBusy;
private bool _layoutSizeLocked;
/// <summary>页码或可翻页状态变化(用于更新侧栏)。</summary>
public event EventHandler PageNavigationStateChanged;
public PdfEmbeddedView()
{
MinWidth = 80;
MinHeight = 60;
var grid = new Grid { ClipToBounds = true };
_pageImage = new Image
{
Stretch = Stretch.Uniform,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
grid.Children.Add(_pageImage);
Content = grid;
}
/// <summary>
/// 初始化并显示第一页;由 MainWindow 在 UI 线程创建后调用。
/// </summary>
public async Task InitializeAsync(string pdfFilePath, uint pageCount, bool compressLargePictures)
{
_pdfPath = pdfFilePath ?? throw new ArgumentNullException(nameof(pdfFilePath));
_pageCount = pageCount;
_compressLargePictures = compressLargePictures;
_currentIndex = 0;
await ShowPageAsync(_currentIndex);
}
public string PdfPath => _pdfPath;
public uint PageCount => _pageCount;
public uint CurrentPageIndex => _currentIndex;
public string PageLabelText => _pageCount == 0 ? "" : $"{_currentIndex + 1} / {_pageCount}";
public bool CanGoPrevious => !_isPagingBusy && _pageCount > 1 && _currentIndex > 0;
public bool CanGoNext => !_isPagingBusy && _pageCount > 1 && _currentIndex < _pageCount - 1;
public async Task GoToPreviousPageAsync()
{
await GoRelativeAsync(-1);
}
public async Task GoToNextPageAsync()
{
await GoRelativeAsync(1);
}
private void NotifyPageNavigationStateChanged()
{
PageNavigationStateChanged?.Invoke(this, EventArgs.Empty);
}
private async Task GoRelativeAsync(int delta)
{
if (_isPagingBusy || _pageCount <= 1)
return;
int next = (int)_currentIndex + delta;
if (next < 0 || next >= _pageCount)
return;
_currentIndex = (uint)next;
await ShowPageAsync(_currentIndex);
}
private async Task ShowPageAsync(uint pageIndex)
{
_isPagingBusy = true;
NotifyPageNavigationStateChanged();
try
{
BitmapSource raw = await PdfWinRtHelper.RenderPageToBitmapSourceAsync(_pdfPath, pageIndex);
if (raw == null)
return;
BitmapSource display = ApplyCompressionIfNeeded(raw);
_pageImage.Source = display;
if (!_layoutSizeLocked)
{
Width = display.PixelWidth;
Height = display.PixelHeight;
_layoutSizeLocked = true;
}
}
finally
{
_isPagingBusy = false;
NotifyPageNavigationStateChanged();
}
}
private BitmapSource ApplyCompressionIfNeeded(BitmapSource rendered)
{
int width = rendered.PixelWidth;
int height = rendered.PixelHeight;
if (_compressLargePictures && (width > 1920 || height > 1080))
{
double scaleX = 1920.0 / width;
double scaleY = 1080.0 / height;
double scale = Math.Min(scaleX, scaleY);
return new TransformedBitmap(rendered, new ScaleTransform(scale, scale));
}
return rendered;
}
}
}
+80
View File
@@ -0,0 +1,80 @@
using System;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using Windows.Data.Pdf;
using Windows.Storage;
using Windows.Storage.Streams;
namespace Ink_Canvas.Helpers
{
/// <summary>
/// 使用 Windows.Data.PdfWinRT)将 PDF 页渲染为 WPF 可用的位图。
/// </summary>
internal static class PdfWinRtHelper
{
public static async Task<uint> GetPageCountAsync(string pdfPath)
{
if (string.IsNullOrWhiteSpace(pdfPath) || !File.Exists(pdfPath))
return 0;
var file = await StorageFile.GetFileFromPathAsync(pdfPath).AsTask();
var doc = await PdfDocument.LoadFromFileAsync(file).AsTask();
if (doc.IsPasswordProtected)
return 0;
return doc.PageCount;
}
public static async Task<BitmapSource> RenderPageToBitmapSourceAsync(string pdfPath, uint pageIndex)
{
if (string.IsNullOrWhiteSpace(pdfPath) || !File.Exists(pdfPath))
return null;
var file = await StorageFile.GetFileFromPathAsync(pdfPath).AsTask();
var doc = await PdfDocument.LoadFromFileAsync(file).AsTask();
if (doc.IsPasswordProtected)
return null;
if (pageIndex >= doc.PageCount)
return null;
var page = doc.GetPage(pageIndex);
try
{
using (var ras = new InMemoryRandomAccessStream())
{
await page.RenderToStreamAsync(ras).AsTask();
ras.Seek(0);
var ms = new MemoryStream();
using (var netStream = ras.AsStreamForRead())
netStream.CopyTo(ms);
ms.Position = 0;
try
{
return await Application.Current.Dispatcher.InvokeAsync(() =>
{
var bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.EndInit();
bi.Freeze();
return (BitmapSource)bi;
});
}
finally
{
ms.Dispose();
}
}
}
finally
{
(page as IDisposable)?.Dispose();
}
}
}
}
+1
View File
@@ -141,6 +141,7 @@
<PackageReference Include="MdXaml" Version="1.27.0" />
<PackageReference Include="Microsoft.Office.Interop.PowerPoint" Version="15.0.4420.1018" />
<PackageReference Include="Microsoft.Windows.SDK.Contracts" Version="10.0.19041.2" />
<PackageReference Include="System.Runtime.WindowsRuntime" Version="4.7.0" />
<PackageReference Include="MicrosoftOfficeCore" Version="15.0.0" />
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
<PackageReference Include="Microsoft.International.Converters.PinYinConverter" Version="1.0.0" />
+103
View File
@@ -4948,6 +4948,109 @@
</Viewbox>
</Border>
<Border Name="BorderPdfPageSidebar"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0,0,0,0"
Width="58"
CornerRadius="10"
Background="{DynamicResource FloatBarBackground}"
BorderBrush="{DynamicResource FloatBarBorderBrush}"
BorderThickness="1"
SnapsToDevicePixels="True"
Visibility="Collapsed"
Panel.ZIndex="1001">
<Border.Resources>
<Style x:Key="PdfSidebarNavButtonStyle" TargetType="Border">
<Setter Property="Width" Value="42" />
<Setter Property="Height" Value="38" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{DynamicResource FloatBarForeground}" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="White" Opacity="0.10" />
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="White" Opacity="0.22" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Border.Resources>
<Grid>
<ikw:SimpleStackPanel VerticalAlignment="Center"
HorizontalAlignment="Center"
Spacing="10"
Margin="0,8,0,8">
<TextBlock Text="PDF"
FontSize="11"
FontWeight="SemiBold"
HorizontalAlignment="Center"
Foreground="{DynamicResource FloatBarForeground}"
Opacity="0.9" />
<Border CornerRadius="8"
Padding="6,8"
BorderThickness="1"
BorderBrush="{DynamicResource FloatBarForeground}"
SnapsToDevicePixels="True">
<Border.Background>
<SolidColorBrush Color="White" Opacity="0.08" />
</Border.Background>
<TextBlock Name="TextBlockPdfSidebarPageLabel"
Text="— / —"
FontSize="12"
FontWeight="SemiBold"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TextAlignment="Center"
Foreground="{DynamicResource FloatBarForeground}"
Opacity="0.55" />
</Border>
<Border Name="BorderPdfSidebarPagePrev"
Style="{StaticResource PdfSidebarNavButtonStyle}"
Opacity="0.35"
IsHitTestVisible="False"
MouseDown="Border_MouseDown"
MouseUp="BorderPdfSidebarPagePrev_MouseUp">
<TextBlock Text="&#x2039;"
FontSize="20"
FontWeight="SemiBold"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,-2,0,0"
Foreground="{DynamicResource FloatBarForeground}" />
</Border>
<Border Name="BorderPdfSidebarPageNext"
Style="{StaticResource PdfSidebarNavButtonStyle}"
Opacity="0.35"
IsHitTestVisible="False"
MouseDown="Border_MouseDown"
MouseUp="BorderPdfSidebarPageNext_MouseUp">
<TextBlock Text="&#x203A;"
FontSize="20"
FontWeight="SemiBold"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,-2,0,0"
Foreground="{DynamicResource FloatBarForeground}" />
</Border>
<TextBlock Text="翻页"
FontSize="9"
HorizontalAlignment="Center"
Foreground="{DynamicResource FloatBarForeground}"
Opacity="0.65" />
</ikw:SimpleStackPanel>
</Grid>
</Border>
<!-- 图片缩放选择点 -->
<Canvas Name="ImageResizeHandlesCanvas"
Visibility="Collapsed"
+251 -46
View File
@@ -1,3 +1,4 @@
using Ink_Canvas.Controls;
using Ink_Canvas.Helpers;
using Microsoft.Win32;
using System;
@@ -56,48 +57,48 @@ namespace Ink_Canvas
private async void BtnImageInsert_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Image files (*.jpg; *.jpeg; *.png; *.bmp)|*.jpg;*.jpeg;*.png;*.bmp";
openFileDialog.Filter = "图片与 PDF|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.pdf|图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|PDF|*.pdf";
if (openFileDialog.ShowDialog() == true)
{
string filePath = openFileDialog.FileName;
Image image = await CreateAndCompressImageAsync(filePath);
FrameworkElement element = await CreateAndCompressImageAsync(filePath);
if (image != null)
if (element != null)
{
string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
image.Name = timestamp;
element.Name = timestamp;
// 设置图片属性,避免被InkCanvas选择系统处理
image.IsHitTestVisible = true;
image.Focusable = false;
element.IsHitTestVisible = true;
element.Focusable = false;
// 初始化InkCanvas选择设置
InitializeInkCanvasSelectionSettings();
// 先添加到画布
inkCanvas.Children.Add(image);
inkCanvas.Children.Add(element);
// 等待图片加载完成后再进行后续处理
image.Loaded += (s, args) =>
element.Loaded += (s, args) =>
{
Dispatcher.BeginInvoke(new Action(() =>
{
// 初始化TransformGroup
InitializeElementTransform(image);
InitializeElementTransform(element);
// 居中缩放
CenterAndScaleElement(image);
CenterAndScaleElement(element);
// 最后绑定事件处理器
BindElementEvents(image);
BindElementEvents(element);
LogHelper.WriteLogToFile($"图片插入完成: {image.Name}");
LogHelper.WriteLogToFile($"图片插入完成: {element.Name}");
}), DispatcherPriority.Loaded);
};
timeMachine.CommitElementInsertHistory(image);
timeMachine.CommitElementInsertHistory(element);
// 插入图片后切换到选择模式并刷新浮动栏高光显示
SetCurrentToolMode(InkCanvasEditingMode.Select);
@@ -270,13 +271,13 @@ namespace Ink_Canvas
ApplyMouseDragTransform(element, currentPoint, dragStartPoint);
// 如果是图片元素,更新工具栏位置
if (element is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible)
if (IsBitmapLikeCanvasElement(element) && BorderImageSelectionControl?.Visibility == Visibility.Visible)
{
UpdateImageSelectionToolbarPosition(element);
}
// 如果是图片元素,更新选择点位置
if (element is Image && ImageResizeHandlesCanvas?.Visibility == Visibility.Visible)
if (IsBitmapLikeCanvasElement(element) && ImageResizeHandlesCanvas?.Visibility == Visibility.Visible)
{
UpdateImageResizeHandlesPosition(GetElementActualBounds(element));
}
@@ -306,13 +307,13 @@ namespace Ink_Canvas
ApplyWheelScaleTransform(element, e);
// 如果是图片元素,更新工具栏位置
if (element is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible)
if (IsBitmapLikeCanvasElement(element) && BorderImageSelectionControl?.Visibility == Visibility.Visible)
{
UpdateImageSelectionToolbarPosition(element);
}
// 如果是图片元素,更新选择点位置
if (element is Image && ImageResizeHandlesCanvas?.Visibility == Visibility.Visible)
if (IsBitmapLikeCanvasElement(element) && ImageResizeHandlesCanvas?.Visibility == Visibility.Visible)
{
UpdateImageResizeHandlesPosition(GetElementActualBounds(element));
}
@@ -396,13 +397,13 @@ namespace Ink_Canvas
ApplyTouchManipulationTransform(element, e);
// 如果是图片元素,更新工具栏位置
if (element is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible)
if (IsBitmapLikeCanvasElement(element) && BorderImageSelectionControl?.Visibility == Visibility.Visible)
{
UpdateImageSelectionToolbarPosition(element);
}
// 如果是图片元素,更新选择点位置
if (element is Image && ImageResizeHandlesCanvas?.Visibility == Visibility.Visible)
if (IsBitmapLikeCanvasElement(element) && ImageResizeHandlesCanvas?.Visibility == Visibility.Visible)
{
UpdateImageResizeHandlesPosition(GetElementActualBounds(element));
}
@@ -523,12 +524,15 @@ namespace Ink_Canvas
currentSelectedElement = element;
// 根据元素类型显示不同的选择工具栏
if (element is Image)
if (IsBitmapLikeCanvasElement(element))
{
if (BorderPdfPageSidebar != null)
BorderPdfPageSidebar.Visibility = element is PdfEmbeddedView ? Visibility.Visible : Visibility.Collapsed;
// 显示图片选择工具栏并设置位置
if (BorderImageSelectionControl != null)
{
// 计算工具栏位置
// 计算工具栏位置(内部会同步 PDF 右侧栏位置)
UpdateImageSelectionToolbarPosition(element);
BorderImageSelectionControl.Visibility = Visibility.Visible;
}
@@ -536,11 +540,25 @@ namespace Ink_Canvas
// 显示图片缩放选择点
ShowImageResizeHandles(element);
if (element is PdfEmbeddedView pdfView)
{
pdfView.PageNavigationStateChanged -= SelectedPdf_PageNavigationStateChanged;
pdfView.PageNavigationStateChanged += SelectedPdf_PageNavigationStateChanged;
UpdatePdfSidebarFromSelectedPdf();
UpdatePdfPageSidebarPosition(pdfView);
}
else
ResetPdfSidebarToIdle();
// 墨迹选择工具栏通过GridInkCanvasSelectionCover的可见性来控制
// 不需要直接设置BorderStrokeSelectionControl.Visibility
}
else
{
if (BorderPdfPageSidebar != null)
BorderPdfPageSidebar.Visibility = Visibility.Collapsed;
ResetPdfSidebarToIdle();
// 隐藏图片选择工具栏
if (BorderImageSelectionControl != null)
{
@@ -584,6 +602,15 @@ namespace Ink_Canvas
{
// 去除选中效果
if (element is PdfEmbeddedView pdfView)
{
pdfView.PageNavigationStateChanged -= SelectedPdf_PageNavigationStateChanged;
}
if (BorderPdfPageSidebar != null)
BorderPdfPageSidebar.Visibility = Visibility.Collapsed;
ResetPdfSidebarToIdle();
// 隐藏图片选择工具栏
if (BorderImageSelectionControl != null)
{
@@ -914,15 +941,24 @@ namespace Ink_Canvas
/// - 否则使用原始尺寸
/// - 返回创建的Image对象
/// </remarks>
private async Task<Image> CreateAndCompressImageAsync(string filePath)
/// <summary>与图片选择工具栏、缩放控制点联动的画布位图类元素(普通图片或多页 PDF 嵌入)。</summary>
private static bool IsBitmapLikeCanvasElement(FrameworkElement fe)
{
return fe is Image || fe is PdfEmbeddedView;
}
private async Task<FrameworkElement> CreateAndCompressImageAsync(string filePath)
{
string fileExtension = Path.GetExtension(filePath);
if (string.Equals(fileExtension, ".pdf", StringComparison.OrdinalIgnoreCase))
return await CreateAndCompressImageFromPdfAsync(filePath);
string savePath = Path.Combine(Settings.Automation.AutoSavedStrokesLocation, "File Dependency");
if (!Directory.Exists(savePath))
{
Directory.CreateDirectory(savePath);
}
string fileExtension = Path.GetExtension(filePath);
string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
string newFilePath = Path.Combine(savePath, timestamp + fileExtension);
@@ -965,6 +1001,43 @@ namespace Ink_Canvas
return image;
});
}
/// <summary>
/// 插入完整 PDF:嵌入控件内可翻页,右下角显示页码(类似希沃白板交互)。
/// </summary>
private async Task<PdfEmbeddedView> CreateAndCompressImageFromPdfAsync(string filePath)
{
try
{
string savePath = Path.Combine(Settings.Automation.AutoSavedStrokesLocation, "File Dependency");
if (!Directory.Exists(savePath))
Directory.CreateDirectory(savePath);
string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
string newFilePath = Path.Combine(savePath, timestamp + ".pdf");
await Task.Run(() => File.Copy(filePath, newFilePath, true));
uint pageCount = await PdfWinRtHelper.GetPageCountAsync(newFilePath);
if (pageCount == 0)
{
ShowNotification("无法打开 PDF(可能已加密、损坏或不支持)。");
return null;
}
bool compress = isLoaded && Settings.Canvas.IsCompressPicturesUploaded;
var view = new PdfEmbeddedView();
await view.InitializeAsync(newFilePath, pageCount, compress);
view.Tag = filePath;
return view;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"插入 PDF 失败: {ex.Message}", LogHelper.LogType.Error);
ShowNotification($"插入 PDF 失败: {ex.Message}");
return null;
}
}
#endregion
#region Media
@@ -1453,6 +1526,9 @@ namespace Ink_Canvas
// 设置工具栏位置
BorderImageSelectionControl.Margin = new Thickness(toolbarLeft, toolbarTop, 0, 0);
if (element is PdfEmbeddedView && BorderPdfPageSidebar?.Visibility == Visibility.Visible)
UpdatePdfPageSidebarPosition(element);
}
catch (Exception ex)
{
@@ -1460,6 +1536,54 @@ namespace Ink_Canvas
}
}
private const double PdfPageSidebarGap = 10;
/// <summary>
/// 将 PDF 专用页码栏贴在当前所选 PDF 的右侧(画布坐标,与底部选中栏一致)。
/// </summary>
private void UpdatePdfPageSidebarPosition(FrameworkElement element)
{
try
{
if (BorderPdfPageSidebar == null || inkCanvas == null || !(element is PdfEmbeddedView))
return;
Rect b = GetElementActualBounds(element);
BorderPdfPageSidebar.Measure(new Size(BorderPdfPageSidebar.Width, double.PositiveInfinity));
double sidebarW = BorderPdfPageSidebar.DesiredSize.Width;
double sidebarH = BorderPdfPageSidebar.DesiredSize.Height;
if (sidebarW <= 0)
sidebarW = BorderPdfPageSidebar.Width;
if (sidebarH <= 0)
sidebarH = BorderPdfPageSidebar.ActualHeight;
if (sidebarH <= 0)
sidebarH = 220;
double left = b.Right + PdfPageSidebarGap;
double top = b.Top + (b.Height * 0.5) - (sidebarH * 0.5);
double maxLeft = Math.Max(0, inkCanvas.ActualWidth - sidebarW);
double maxTop = Math.Max(0, inkCanvas.ActualHeight - sidebarH);
if (left > maxLeft)
{
double leftAlt = b.Left - PdfPageSidebarGap - sidebarW;
if (leftAlt >= 0)
left = leftAlt;
}
left = Math.Max(0, Math.Min(left, maxLeft));
top = Math.Max(0, Math.Min(top, maxTop));
BorderPdfPageSidebar.Margin = new Thickness(left, top, 0, 0);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"更新 PDF 右侧页码栏位置失败: {ex.Message}", LogHelper.LogType.Error);
}
}
/// <summary>
/// 获取元素的实际边界(考虑变换)
/// </summary>
@@ -1644,7 +1768,7 @@ namespace Ink_Canvas
ApplyRotateTransform(currentSelectedElement, -45);
// 更新工具栏位置
if (currentSelectedElement is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible)
if (IsBitmapLikeCanvasElement(currentSelectedElement) && BorderImageSelectionControl?.Visibility == Visibility.Visible)
{
UpdateImageSelectionToolbarPosition(currentSelectedElement);
}
@@ -1678,7 +1802,7 @@ namespace Ink_Canvas
ApplyRotateTransform(currentSelectedElement, 45);
// 更新工具栏位置
if (currentSelectedElement is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible)
if (IsBitmapLikeCanvasElement(currentSelectedElement) && BorderImageSelectionControl?.Visibility == Visibility.Visible)
{
UpdateImageSelectionToolbarPosition(currentSelectedElement);
}
@@ -1714,7 +1838,7 @@ namespace Ink_Canvas
ApplyScaleTransform(currentSelectedElement, 0.9, elementCenter);
// 更新工具栏位置
if (currentSelectedElement is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible)
if (IsBitmapLikeCanvasElement(currentSelectedElement) && BorderImageSelectionControl?.Visibility == Visibility.Visible)
{
UpdateImageSelectionToolbarPosition(currentSelectedElement);
}
@@ -1750,7 +1874,7 @@ namespace Ink_Canvas
ApplyScaleTransform(currentSelectedElement, 1.1, elementCenter);
// 更新工具栏位置
if (currentSelectedElement is Image && BorderImageSelectionControl?.Visibility == Visibility.Visible)
if (IsBitmapLikeCanvasElement(currentSelectedElement) && BorderImageSelectionControl?.Visibility == Visibility.Visible)
{
UpdateImageSelectionToolbarPosition(currentSelectedElement);
}
@@ -1764,19 +1888,96 @@ namespace Ink_Canvas
}
}
private void ResetPdfSidebarToIdle()
{
if (TextBlockPdfSidebarPageLabel != null)
{
TextBlockPdfSidebarPageLabel.Text = "— / —";
TextBlockPdfSidebarPageLabel.Opacity = 0.55;
}
if (BorderPdfSidebarPagePrev != null)
{
BorderPdfSidebarPagePrev.Opacity = 0.35;
BorderPdfSidebarPagePrev.IsHitTestVisible = false;
}
if (BorderPdfSidebarPageNext != null)
{
BorderPdfSidebarPageNext.Opacity = 0.35;
BorderPdfSidebarPageNext.IsHitTestVisible = false;
}
}
private void UpdatePdfSidebarFromSelectedPdf()
{
if (currentSelectedElement is PdfEmbeddedView pdf)
{
if (TextBlockPdfSidebarPageLabel != null)
{
TextBlockPdfSidebarPageLabel.Text = pdf.PageLabelText;
TextBlockPdfSidebarPageLabel.Opacity = 1.0;
}
bool prevOk = pdf.CanGoPrevious;
bool nextOk = pdf.CanGoNext;
if (BorderPdfSidebarPagePrev != null)
{
BorderPdfSidebarPagePrev.Opacity = prevOk ? 1.0 : 0.35;
BorderPdfSidebarPagePrev.IsHitTestVisible = prevOk;
}
if (BorderPdfSidebarPageNext != null)
{
BorderPdfSidebarPageNext.Opacity = nextOk ? 1.0 : 0.35;
BorderPdfSidebarPageNext.IsHitTestVisible = nextOk;
}
}
}
private void SelectedPdf_PageNavigationStateChanged(object sender, EventArgs e)
{
Dispatcher.BeginInvoke(new Action(() =>
{
UpdatePdfSidebarFromSelectedPdf();
if (currentSelectedElement != null && IsBitmapLikeCanvasElement(currentSelectedElement))
{
UpdateImageSelectionToolbarPosition(currentSelectedElement);
if (ImageResizeHandlesCanvas?.Visibility == Visibility.Visible)
UpdateImageResizeHandlesPosition(GetElementActualBounds(currentSelectedElement));
}
}), DispatcherPriority.Background);
}
private async void BorderPdfSidebarPagePrev_MouseUp(object sender, MouseButtonEventArgs e)
{
try
{
if (currentSelectedElement is PdfEmbeddedView pdf && pdf.CanGoPrevious)
await pdf.GoToPreviousPageAsync();
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"PDF 上一页失败: {ex.Message}", LogHelper.LogType.Error);
}
}
private async void BorderPdfSidebarPageNext_MouseUp(object sender, MouseButtonEventArgs e)
{
try
{
if (currentSelectedElement is PdfEmbeddedView pdf && pdf.CanGoNext)
await pdf.GoToNextPageAsync();
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"PDF 下一页失败: {ex.Message}", LogHelper.LogType.Error);
}
}
/// <summary>
/// 处理图片删除功能
/// </summary>
/// <param name="sender">事件发送者</param>
/// <param name="e">事件参数</param>
/// <remarks>
/// - 检查当前是否有选中元素
/// - 保存删除前的编辑模式
/// - 记录删除历史
/// - 从画布中移除
/// - 清除选中状态
/// - 包含异常处理
/// </remarks>
private void BorderImageDelete_MouseUp(object sender, MouseButtonEventArgs e)
{
try
@@ -1789,11 +1990,12 @@ namespace Ink_Canvas
// 记录删除历史
timeMachine.CommitElementRemoveHistory(currentSelectedElement);
var toRemove = currentSelectedElement;
// 从画布中移除
inkCanvas.Children.Remove(currentSelectedElement);
inkCanvas.Children.Remove(toRemove);
// 清除选中状态
UnselectElement(currentSelectedElement);
UnselectElement(toRemove);
currentSelectedElement = null;
// 恢复到删除前的编辑模式
@@ -2029,7 +2231,7 @@ namespace Ink_Canvas
{
try
{
if (currentSelectedElement is Image image && sender is Ellipse ellipse)
if (IsBitmapLikeCanvasElement(currentSelectedElement) && sender is Ellipse ellipse)
{
isResizingImage = true;
imageResizeStartPoint = e.GetPosition(inkCanvas);
@@ -2072,10 +2274,10 @@ namespace Ink_Canvas
{
try
{
if (isResizingImage && currentSelectedElement is Image image && sender is Ellipse ellipse)
if (isResizingImage && IsBitmapLikeCanvasElement(currentSelectedElement) && sender is Ellipse ellipse)
{
var currentPoint = e.GetPosition(inkCanvas);
ResizeImageByHandle(image, imageResizeStartPoint, currentPoint, activeResizeHandle);
ResizeImageByHandle(currentSelectedElement, imageResizeStartPoint, currentPoint, activeResizeHandle);
imageResizeStartPoint = currentPoint;
e.Handled = true;
}
@@ -2087,11 +2289,11 @@ namespace Ink_Canvas
}
// 根据控制点缩放图片
private void ResizeImageByHandle(Image image, Point startPoint, Point currentPoint, string handleName)
private void ResizeImageByHandle(FrameworkElement element, Point startPoint, Point currentPoint, string handleName)
{
try
{
if (image.RenderTransform is TransformGroup transformGroup)
if (element.RenderTransform is TransformGroup transformGroup)
{
var scaleTransform = transformGroup.Children.OfType<ScaleTransform>().FirstOrDefault();
var translateTransform = transformGroup.Children.OfType<TranslateTransform>().FirstOrDefault();
@@ -2099,7 +2301,7 @@ namespace Ink_Canvas
if (scaleTransform == null || translateTransform == null) return;
// 获取图片的当前边界
Rect currentBounds = GetElementActualBounds(image);
Rect currentBounds = GetElementActualBounds(element);
double deltaX = currentPoint.X - startPoint.X;
double deltaY = currentPoint.Y - startPoint.Y;
@@ -2160,7 +2362,10 @@ namespace Ink_Canvas
translateTransform.Y += translateY;
// 更新选择点位置
UpdateImageResizeHandlesPosition(GetElementActualBounds(image));
UpdateImageResizeHandlesPosition(GetElementActualBounds(element));
if (BorderImageSelectionControl?.Visibility == Visibility.Visible)
UpdateImageSelectionToolbarPosition(element);
}
}
catch (Exception ex)
+79 -99
View File
@@ -1,3 +1,4 @@
using Ink_Canvas.Controls;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Modern;
using System;
@@ -3774,32 +3775,29 @@ namespace Ink_Canvas
// Open file dialog to select image
var dialog = new OpenFileDialog
{
Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif"
Filter = "图片与 PDF|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.pdf|图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|PDF|*.pdf"
};
if (dialog.ShowDialog() == true)
{
string filePath = dialog.FileName;
Image image = await CreateAndCompressImageAsync(filePath);
if (image != null)
FrameworkElement element = await CreateAndCompressImageAsync(filePath);
if (element != null)
{
string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
image.Name = timestamp;
element.Name = timestamp;
// 初始化TransformGroup
if (image is FrameworkElement element)
{
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new ScaleTransform(1, 1));
transformGroup.Children.Add(new TranslateTransform(0, 0));
transformGroup.Children.Add(new RotateTransform(0));
element.RenderTransform = transformGroup;
}
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new ScaleTransform(1, 1));
transformGroup.Children.Add(new TranslateTransform(0, 0));
transformGroup.Children.Add(new RotateTransform(0));
element.RenderTransform = transformGroup;
CenterAndScaleElement(image);
CenterAndScaleElement(element);
// 设置图片属性,避免被InkCanvas选择系统处理
image.IsHitTestVisible = true;
image.Focusable = false;
element.IsHitTestVisible = true;
element.Focusable = false;
// 初始化InkCanvas选择设置
if (inkCanvas != null)
@@ -3810,29 +3808,25 @@ namespace Ink_Canvas
inkCanvas.EditingMode = InkCanvasEditingMode.None;
}
inkCanvas.Children.Add(image);
inkCanvas.Children.Add(element);
// 绑定事件处理器
if (image is FrameworkElement elementForEvents)
{
// 鼠标事件
elementForEvents.MouseLeftButtonDown += Element_MouseLeftButtonDown;
elementForEvents.MouseLeftButtonUp += Element_MouseLeftButtonUp;
elementForEvents.MouseMove += Element_MouseMove;
elementForEvents.MouseWheel += Element_MouseWheel;
element.MouseLeftButtonDown += Element_MouseLeftButtonDown;
element.MouseLeftButtonUp += Element_MouseLeftButtonUp;
element.MouseMove += Element_MouseMove;
element.MouseWheel += Element_MouseWheel;
// 触摸事件
elementForEvents.TouchDown += Element_TouchDown;
elementForEvents.TouchUp += Element_TouchUp;
elementForEvents.IsManipulationEnabled = true;
elementForEvents.ManipulationDelta += Element_ManipulationDelta;
elementForEvents.ManipulationCompleted += Element_ManipulationCompleted;
// 触摸事件
element.TouchDown += Element_TouchDown;
element.TouchUp += Element_TouchUp;
element.IsManipulationEnabled = true;
element.ManipulationDelta += Element_ManipulationDelta;
element.ManipulationCompleted += Element_ManipulationCompleted;
// 设置光标
elementForEvents.Cursor = Cursors.Hand;
}
// 设置光标
element.Cursor = Cursors.Hand;
timeMachine.CommitElementInsertHistory(image);
timeMachine.CommitElementInsertHistory(element);
// 插入图片后切换到选择模式并刷新浮动栏高光显示
SetCurrentToolMode(InkCanvasEditingMode.Select);
@@ -3847,32 +3841,29 @@ namespace Ink_Canvas
{
var dialog = new OpenFileDialog
{
Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif"
Filter = "图片与 PDF|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.pdf|图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|PDF|*.pdf"
};
if (dialog.ShowDialog() == true)
{
string filePath = dialog.FileName;
Image image = await CreateAndCompressImageAsync(filePath);
if (image != null)
FrameworkElement element = await CreateAndCompressImageAsync(filePath);
if (element != null)
{
string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
image.Name = timestamp;
element.Name = timestamp;
// 初始化TransformGroup
if (image is FrameworkElement element)
{
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new ScaleTransform(1, 1));
transformGroup.Children.Add(new TranslateTransform(0, 0));
transformGroup.Children.Add(new RotateTransform(0));
element.RenderTransform = transformGroup;
}
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new ScaleTransform(1, 1));
transformGroup.Children.Add(new TranslateTransform(0, 0));
transformGroup.Children.Add(new RotateTransform(0));
element.RenderTransform = transformGroup;
CenterAndScaleElement(image);
CenterAndScaleElement(element);
// 设置图片属性,避免被InkCanvas选择系统处理
image.IsHitTestVisible = true;
image.Focusable = false;
element.IsHitTestVisible = true;
element.Focusable = false;
// 初始化InkCanvas选择设置
if (inkCanvas != null)
@@ -3883,29 +3874,25 @@ namespace Ink_Canvas
inkCanvas.EditingMode = InkCanvasEditingMode.None;
}
inkCanvas.Children.Add(image);
inkCanvas.Children.Add(element);
// 绑定事件处理器
if (image is FrameworkElement elementForEvents)
{
// 鼠标事件
elementForEvents.MouseLeftButtonDown += Element_MouseLeftButtonDown;
elementForEvents.MouseLeftButtonUp += Element_MouseLeftButtonUp;
elementForEvents.MouseMove += Element_MouseMove;
elementForEvents.MouseWheel += Element_MouseWheel;
element.MouseLeftButtonDown += Element_MouseLeftButtonDown;
element.MouseLeftButtonUp += Element_MouseLeftButtonUp;
element.MouseMove += Element_MouseMove;
element.MouseWheel += Element_MouseWheel;
// 触摸事件
elementForEvents.TouchDown += Element_TouchDown;
elementForEvents.TouchUp += Element_TouchUp;
elementForEvents.IsManipulationEnabled = true;
elementForEvents.ManipulationDelta += Element_ManipulationDelta;
elementForEvents.ManipulationCompleted += Element_ManipulationCompleted;
// 触摸事件
element.TouchDown += Element_TouchDown;
element.TouchUp += Element_TouchUp;
element.IsManipulationEnabled = true;
element.ManipulationDelta += Element_ManipulationDelta;
element.ManipulationCompleted += Element_ManipulationCompleted;
// 设置光标
elementForEvents.Cursor = Cursors.Hand;
}
// 设置光标
element.Cursor = Cursors.Hand;
timeMachine.CommitElementInsertHistory(image);
timeMachine.CommitElementInsertHistory(element);
// 插入图片后切换到选择模式并刷新浮动栏高光显示
SetCurrentToolMode(InkCanvasEditingMode.Select);
@@ -3920,32 +3907,29 @@ namespace Ink_Canvas
{
var dialog = new OpenFileDialog
{
Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif"
Filter = "图片与 PDF|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.pdf|图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|PDF|*.pdf"
};
if (dialog.ShowDialog() == true)
{
string filePath = dialog.FileName;
Image image = await CreateAndCompressImageAsync(filePath); // 补充image定义
if (image != null)
FrameworkElement element = await CreateAndCompressImageAsync(filePath);
if (element != null)
{
string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
image.Name = timestamp;
element.Name = timestamp;
// 初始化TransformGroup
if (image is FrameworkElement element)
{
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new ScaleTransform(1, 1));
transformGroup.Children.Add(new TranslateTransform(0, 0));
transformGroup.Children.Add(new RotateTransform(0));
element.RenderTransform = transformGroup;
}
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new ScaleTransform(1, 1));
transformGroup.Children.Add(new TranslateTransform(0, 0));
transformGroup.Children.Add(new RotateTransform(0));
element.RenderTransform = transformGroup;
CenterAndScaleElement(image);
CenterAndScaleElement(element);
// 设置图片属性,避免被InkCanvas选择系统处理
image.IsHitTestVisible = true;
image.Focusable = false;
element.IsHitTestVisible = true;
element.Focusable = false;
// 初始化InkCanvas选择设置
if (inkCanvas != null)
@@ -3956,29 +3940,25 @@ namespace Ink_Canvas
inkCanvas.EditingMode = InkCanvasEditingMode.None;
}
inkCanvas.Children.Add(image);
inkCanvas.Children.Add(element);
// 绑定事件处理器
if (image is FrameworkElement elementForEvents)
{
// 鼠标事件
elementForEvents.MouseLeftButtonDown += Element_MouseLeftButtonDown;
elementForEvents.MouseLeftButtonUp += Element_MouseLeftButtonUp;
elementForEvents.MouseMove += Element_MouseMove;
elementForEvents.MouseWheel += Element_MouseWheel;
element.MouseLeftButtonDown += Element_MouseLeftButtonDown;
element.MouseLeftButtonUp += Element_MouseLeftButtonUp;
element.MouseMove += Element_MouseMove;
element.MouseWheel += Element_MouseWheel;
// 触摸事件
elementForEvents.TouchDown += Element_TouchDown;
elementForEvents.TouchUp += Element_TouchUp;
elementForEvents.IsManipulationEnabled = true;
elementForEvents.ManipulationDelta += Element_ManipulationDelta;
elementForEvents.ManipulationCompleted += Element_ManipulationCompleted;
// 触摸事件
element.TouchDown += Element_TouchDown;
element.TouchUp += Element_TouchUp;
element.IsManipulationEnabled = true;
element.ManipulationDelta += Element_ManipulationDelta;
element.ManipulationCompleted += Element_ManipulationCompleted;
// 设置光标
elementForEvents.Cursor = Cursors.Hand;
}
// 设置光标
element.Cursor = Cursors.Hand;
timeMachine.CommitElementInsertHistory(image);
timeMachine.CommitElementInsertHistory(element);
// 插入图片后切换到选择模式并刷新浮动栏高光显示
SetCurrentToolMode(InkCanvasEditingMode.Select);
@@ -1,3 +1,4 @@
using Ink_Canvas.Controls;
using Ink_Canvas.Helpers;
using iNKORE.UI.WPF.Controls;
using System;
@@ -610,7 +611,7 @@ namespace Ink_Canvas
// 检查是否有图片元素被选中(通过InkCanvas的选中元素)
var selectedElements = inkCanvas.GetSelectedElements();
bool hasImageElement = selectedElements.Any(element => element is Image);
bool hasImageElement = selectedElements.Any(element => element is Image || element is PdfEmbeddedView);
// 如果有图片元素被选中,不显示选择框
if (hasImageElement)
@@ -621,7 +622,7 @@ namespace Ink_Canvas
}
// 检查是否有图片元素被选中(通过currentSelectedElement
if (currentSelectedElement != null && currentSelectedElement is Image)
if (currentSelectedElement != null && (currentSelectedElement is Image || currentSelectedElement is PdfEmbeddedView))
{
GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed;
HideSelectionDisplay();
+42 -37
View File
@@ -1,3 +1,4 @@
using Ink_Canvas.Controls;
using Ink_Canvas.Helpers;
using Microsoft.Win32;
using Newtonsoft.Json;
@@ -101,7 +102,7 @@ namespace Ink_Canvas.Windows
private double _collapsedOffset = 200; // 折叠时的偏移量(隐藏内容区域)
private MainWindow _mainWindow;
private Dictionary<System.Windows.Controls.Image, int> _pptImages = new Dictionary<System.Windows.Controls.Image, int>();
private Dictionary<FrameworkElement, int> _pptImages = new Dictionary<FrameworkElement, int>();
private Dictionary<int, List<string>> _pptImagePaths = new Dictionary<int, List<string>>();
@@ -183,9 +184,9 @@ namespace Ink_Canvas.Windows
{
foreach (var item in e.OldItems)
{
if (item is System.Windows.Controls.Image image)
if (item is FrameworkElement fe && _pptImages.ContainsKey(fe))
{
RemoveImageFromPPT(image);
RemoveImageFromPPT(fe);
}
}
}
@@ -196,20 +197,20 @@ namespace Ink_Canvas.Windows
}
}
private void RemoveImageFromPPT(System.Windows.Controls.Image image)
private void RemoveImageFromPPT(FrameworkElement element)
{
try
{
if (image == null) return;
if (element == null) return;
if (_pptImages.ContainsKey(image))
if (_pptImages.ContainsKey(element))
{
int slideNumber = _pptImages[image];
_pptImages.Remove(image);
int slideNumber = _pptImages[element];
_pptImages.Remove(element);
if (_pptImagePaths.ContainsKey(slideNumber))
{
string imagePath = image.Tag as string;
string imagePath = element.Tag as string;
if (!string.IsNullOrEmpty(imagePath) && _pptImagePaths[slideNumber].Contains(imagePath))
{
_pptImagePaths[slideNumber].Remove(imagePath);
@@ -929,7 +930,7 @@ namespace Ink_Canvas.Windows
{
var dialog = new OpenFileDialog
{
Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif"
Filter = "图片与 PDF|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.pdf|图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|PDF|*.pdf"
};
if (dialog.ShowDialog() == true)
@@ -941,14 +942,14 @@ namespace Ink_Canvas.Windows
if (createImageMethod != null)
{
var imageTask = createImageMethod.Invoke(_mainWindow, new object[] { filePath }) as System.Threading.Tasks.Task<System.Windows.Controls.Image>;
var imageTask = createImageMethod.Invoke(_mainWindow, new object[] { filePath }) as System.Threading.Tasks.Task<FrameworkElement>;
if (imageTask != null)
{
var image = await imageTask;
if (image != null)
var inserted = await imageTask;
if (inserted != null)
{
image.Tag = filePath;
await InsertImageToMainWindow(image, filePath);
inserted.Tag = filePath;
await InsertImageToMainWindow(inserted, filePath);
}
}
}
@@ -1185,9 +1186,9 @@ namespace Ink_Canvas.Windows
}, 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(FrameworkElement element, string originalFilePath = null, bool saveToJson = true)
{
if (_mainWindow == null || image == null) return;
if (_mainWindow == null || element == null) return;
// 确保在UI线程上执行
await Application.Current.Dispatcher.InvokeAsync(() =>
@@ -1196,11 +1197,11 @@ namespace Ink_Canvas.Windows
{
// 生成唯一名称
string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
image.Name = timestamp;
element.Name = timestamp;
// 设置图片属性
image.IsHitTestVisible = true;
image.Focusable = false;
element.IsHitTestVisible = true;
element.Focusable = false;
System.Windows.Controls.InkCanvas inkCanvas = null;
var inkCanvasField = _mainWindow.GetType().GetField("inkCanvas",
@@ -1274,7 +1275,7 @@ namespace Ink_Canvas.Windows
// 如果在PPT模式下,记录图片和页面编号的关联,并保存图片路径
if (currentSlideNumber > 0 && !string.IsNullOrEmpty(originalFilePath) && saveToJson)
{
_pptImages[image] = currentSlideNumber;
_pptImages[element] = currentSlideNumber;
// 添加到页面图片路径列表
if (!_pptImagePaths.ContainsKey(currentSlideNumber))
@@ -1289,14 +1290,14 @@ namespace Ink_Canvas.Windows
else if (currentSlideNumber > 0)
{
// 即使不保存到JSON,也要记录图片和页面编号的关联(用于翻页显示/隐藏)
_pptImages[image] = currentSlideNumber;
_pptImages[element] = currentSlideNumber;
}
// 先添加到画布(与MainWindow的实现保持一致)
inkCanvas.Children.Add(image);
inkCanvas.Children.Add(element);
// 等待图片加载完成后再进行后续处理
image.Loaded += (s, args) =>
element.Loaded += (s, args) =>
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
@@ -1305,19 +1306,19 @@ namespace Ink_Canvas.Windows
// 初始化TransformGroup
var initializeTransformMethod = _mainWindow.GetType().GetMethod("InitializeElementTransform",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
initializeTransformMethod?.Invoke(_mainWindow, new object[] { image });
initializeTransformMethod?.Invoke(_mainWindow, new object[] { element });
// 居中缩放
var centerMethod = _mainWindow.GetType().GetMethod("CenterAndScaleElement",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
centerMethod?.Invoke(_mainWindow, new object[] { image });
centerMethod?.Invoke(_mainWindow, new object[] { element });
// 绑定事件处理器
var bindEventsMethod = _mainWindow.GetType().GetMethod("BindElementEvents",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
bindEventsMethod?.Invoke(_mainWindow, new object[] { image });
bindEventsMethod?.Invoke(_mainWindow, new object[] { element });
LogHelper.WriteLogToFile($"图片插入完成: {image.Name}, PPT页面: {currentSlideNumber}");
LogHelper.WriteLogToFile($"图片插入完成: {element.Name}, PPT页面: {currentSlideNumber}");
}
catch (Exception ex)
{
@@ -1333,7 +1334,7 @@ namespace Ink_Canvas.Windows
if (timeMachine != null)
{
var commitMethod = timeMachine.GetType().GetMethod("CommitElementInsertHistory");
commitMethod?.Invoke(timeMachine, new object[] { image });
commitMethod?.Invoke(timeMachine, new object[] { element });
}
// 切换到选择模式
@@ -1699,12 +1700,16 @@ namespace Ink_Canvas.Windows
// 检查已存在的图片路径(通过Tag)
var existingImagePaths = new HashSet<string>();
foreach (System.Windows.Controls.Image existingImage in inkCanvas.Children.OfType<System.Windows.Controls.Image>())
foreach (var existingImage in inkCanvas.Children.OfType<System.Windows.Controls.Image>())
{
if (existingImage.Tag is string tagPath && !string.IsNullOrEmpty(tagPath))
{
existingImagePaths.Add(tagPath);
}
}
foreach (var existingPdf in inkCanvas.Children.OfType<PdfEmbeddedView>())
{
if (existingPdf.Tag is string tagPath && !string.IsNullOrEmpty(tagPath))
existingImagePaths.Add(tagPath);
}
// 使用反射调用MainWindow的CreateAndCompressImageAsync方法
@@ -1733,17 +1738,17 @@ namespace Ink_Canvas.Windows
continue;
}
var imageTask = createImageMethod.Invoke(_mainWindow, new object[] { imagePath }) as System.Threading.Tasks.Task<System.Windows.Controls.Image>;
var imageTask = createImageMethod.Invoke(_mainWindow, new object[] { imagePath }) as System.Threading.Tasks.Task<FrameworkElement>;
if (imageTask != null)
{
var image = await imageTask;
if (image != null)
var inserted = await imageTask;
if (inserted != null)
{
// 保存原始文件路径到Tag
image.Tag = imagePath;
inserted.Tag = imagePath;
// 插入图片(不保存路径,因为已经存在)
await InsertImageToMainWindow(image, imagePath, false);
await InsertImageToMainWindow(inserted, imagePath, false);
}
}
}
+6 -23
View File
@@ -168,6 +168,12 @@
"System.Text.Json": "8.0.5"
}
},
"System.Runtime.WindowsRuntime": {
"type": "Direct",
"requested": "[4.7.0, )",
"resolved": "4.7.0",
"contentHash": "RQxUkf37fp7MSWbOfKRjUjyudyfZb2u79YY5i1s+d7vuD80A7kmr2YfefO0JprQUhanxSm8bhXigCVfX2kEh+w=="
},
"WebDav.Client": {
"type": "Direct",
"requested": "[2.9.0, )",
@@ -247,11 +253,6 @@
"System.Memory": "4.5.4"
}
},
"System.ComponentModel.Annotations": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "dMkqfy2el8A8/I76n2Hi1oBFEbG1SfxD2l5nhwXV3XjlnOmwxJlQbYpJH4W51odnU9sARCSAgv7S3CyAFMkpYg=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.5",
@@ -290,11 +291,6 @@
"resolved": "4.3.0",
"contentHash": "J4GUi3xZQLUBasNwZnjrffN8i5wpHrBtZoLG+OhRyGo/+YunMRWWtwoMDlUAIdmX0uRfpHIBDSV6zyr3yf00TA=="
},
"System.Runtime.WindowsRuntime": {
"type": "Transitive",
"resolved": "4.6.0",
"contentHash": "IWrs1TmbxP65ZZjIglNyvDkFNoV5q2Pofg5WO7I8RKQOpLdFprQSh3xesOoClBqR4JHr4nEB1Xk1MqLPW1jPuQ=="
},
"System.Runtime.WindowsRuntime.UI.Xaml": {
"type": "Transitive",
"resolved": "4.6.0",
@@ -352,19 +348,6 @@
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
"inkcanvas.pluginhost": {
"type": "Project",
"dependencies": {
"InkCanvas.PluginSdk": "[1.0.0, )"
}
},
"inkcanvas.pluginsdk": {
"type": "Project",
"dependencies": {
"Newtonsoft.Json": "[13.0.3, )",
"System.ComponentModel.Annotations": "[5.0.0, )"
}
}
},
".NETFramework,Version=v4.7.2/win": {