diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml
index 13acc9ef..19b38b3f 100644
--- a/Ink Canvas/MainWindow.xaml
+++ b/Ink Canvas/MainWindow.xaml
@@ -60,6 +60,7 @@
+
@@ -148,6 +149,7 @@
+
@@ -175,6 +177,8 @@
Executed="KeyHide" />
+
@@ -4916,7 +4920,7 @@
@@ -5244,6 +5248,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ ShowNotification("检测到剪贴板中有图片,右键点击白板可粘贴");
+ });
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"显示粘贴提示失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ // 处理右键菜单显示
+ private void ShowPasteContextMenu(Point position)
+ {
+ try
+ {
+ if (!Clipboard.ContainsImage()) return;
+
+ // 创建右键菜单
+ var contextMenu = new ContextMenu();
+
+ var pasteMenuItem = new MenuItem
+ {
+ Header = "粘贴图片"
+ };
+
+ pasteMenuItem.Click += async (s, e) => await PasteImageFromClipboard(position);
+ contextMenu.Items.Add(pasteMenuItem);
+
+ // 显示菜单
+ contextMenu.IsOpen = true;
+ contextMenu.PlacementTarget = inkCanvas;
+ contextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.MousePoint;
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"显示粘贴菜单失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ // 从剪贴板粘贴图片
+ private async Task PasteImageFromClipboard(Point? position = null)
+ {
+ try
+ {
+ if (!Clipboard.ContainsImage())
+ {
+ ShowNotification("剪贴板中没有图片");
+ return;
+ }
+
+ var clipboardImage = Clipboard.GetImage();
+ if (clipboardImage == null)
+ {
+ ShowNotification("无法获取剪贴板图片");
+ return;
+ }
+
+ // 创建Image控件
+ var image = new Image
+ {
+ Source = clipboardImage,
+ Width = clipboardImage.PixelWidth,
+ Height = clipboardImage.PixelHeight,
+ Stretch = System.Windows.Media.Stretch.Fill
+ };
+
+ // 生成唯一名称
+ string timestamp = "img_clipboard_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
+ image.Name = timestamp;
+
+ // 设置位置
+ if (position.HasValue)
+ {
+ // 在指定位置居中显示
+ InkCanvas.SetLeft(image, position.Value.X - image.Width / 2);
+ InkCanvas.SetTop(image, position.Value.Y - image.Height / 2);
+ }
+ else
+ {
+ // 使用与文件选择相同的居中和缩放逻辑
+ CenterAndScaleElement(image);
+ }
+
+ // 添加到画布
+ inkCanvas.Children.Add(image);
+
+ // 添加鼠标事件处理
+ image.MouseDown += UIElement_MouseDown;
+ image.IsManipulationEnabled = true;
+
+ // 提交到历史记录
+ timeMachine.CommitElementInsertHistory(image);
+
+ ShowNotification("图片已从剪贴板粘贴");
+ }
+ catch (Exception ex)
+ {
+ ShowNotification($"粘贴图片失败: {ex.Message}");
+ LogHelper.WriteLogToFile($"粘贴图片失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+
+
+ // 处理白板右键事件
+ private void InkCanvas_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ try
+ {
+ // 只在白板模式下处理
+ if (currentMode != 1) return;
+
+ // 检查是否有图片在剪贴板中
+ if (Clipboard.ContainsImage())
+ {
+ var position = e.GetPosition(inkCanvas);
+ ShowPasteContextMenu(position);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"处理右键事件失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ // 处理全局粘贴快捷键
+ private async void HandleGlobalPaste(object sender, ExecutedRoutedEventArgs e)
+ {
+ try
+ {
+ // 只在白板模式下处理
+ if (currentMode != 1) return;
+
+ if (Clipboard.ContainsImage())
+ {
+ await PasteImageFromClipboard();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"处理全局粘贴失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ // 清理剪贴板监控
+ private void CleanupClipboardMonitoring()
+ {
+ try
+ {
+ if (isClipboardMonitoringEnabled)
+ {
+ ClipboardNotification.ClipboardUpdate -= OnClipboardUpdate;
+ isClipboardMonitoringEnabled = false;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WriteLogToFile($"清理剪贴板监控失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+ }
+
+ // 剪贴板通知类
+ public static class ClipboardNotification
+ {
+ public static event Action ClipboardUpdate;
+
+ private static System.Windows.Forms.Timer clipboardTimer;
+ private static string lastClipboardText = "";
+ private static bool lastHadImage = false;
+
+ static ClipboardNotification()
+ {
+ clipboardTimer = new System.Windows.Forms.Timer();
+ clipboardTimer.Interval = 500; // 每500ms检查一次
+ clipboardTimer.Tick += CheckClipboard;
+ clipboardTimer.Start();
+ }
+
+ private static void CheckClipboard(object sender, EventArgs e)
+ {
+ try
+ {
+ bool currentHasImage = Clipboard.ContainsImage();
+ string currentText = Clipboard.ContainsText() ? Clipboard.GetText() : "";
+
+ if (currentHasImage != lastHadImage || currentText != lastClipboardText)
+ {
+ lastHadImage = currentHasImage;
+ lastClipboardText = currentText;
+ ClipboardUpdate?.Invoke();
+ }
+ }
+ catch
+ {
+ // 忽略剪贴板访问错误
+ }
+ }
+
+ public static void Stop()
+ {
+ clipboardTimer?.Stop();
+ clipboardTimer?.Dispose();
+ }
+ }
+}
diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs
index 500039ce..9a7194bb 100644
--- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs
+++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs
@@ -208,6 +208,7 @@ namespace Ink_Canvas {
BorderSettings.Visibility = Visibility.Collapsed;
BoardBorderLeftPageListView.Visibility = Visibility.Collapsed;
BoardBorderRightPageListView.Visibility = Visibility.Collapsed;
+ BoardImageOptionsPanel.Visibility = Visibility.Collapsed;
}
///
@@ -279,7 +280,8 @@ namespace Ink_Canvas {
AnimationsHelper.HideWithSlideAndFade(BorderDrawShape);
AnimationsHelper.HideWithSlideAndFade(BoardBorderLeftPageListView);
AnimationsHelper.HideWithSlideAndFade(BoardBorderRightPageListView);
-
+ AnimationsHelper.HideWithSlideAndFade(BoardImageOptionsPanel);
+
// 隐藏背景设置面板
var bgPalette = LogicalTreeHelper.FindLogicalNode(this, "BackgroundPalette") as Border;
if (bgPalette != null)
@@ -2065,6 +2067,71 @@ namespace Ink_Canvas {
#endregion
+ private void InsertImageOptions_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+ // Hide other sub-panels first
+ HideSubPanelsImmediately();
+
+ // Show the image options panel
+ if (BoardImageOptionsPanel.Visibility == Visibility.Collapsed)
+ {
+ AnimationsHelper.ShowWithSlideFromBottomAndFade(BoardImageOptionsPanel);
+ }
+ else
+ {
+ AnimationsHelper.HideWithSlideAndFade(BoardImageOptionsPanel);
+ }
+ }
+
+ private void CloseImageOptionsPanel_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+ AnimationsHelper.HideWithSlideAndFade(BoardImageOptionsPanel);
+ }
+
+ private async void ImageOptionScreenshot_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+ // Hide the options panel
+ AnimationsHelper.HideWithSlideAndFade(BoardImageOptionsPanel);
+
+ // Wait a bit for the panel to hide
+ await Task.Delay(100);
+
+ // Capture screenshot and copy to clipboard
+ await CaptureScreenshotToClipboard();
+ }
+
+ private async void ImageOptionSelectFile_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+ // Hide the options panel
+ AnimationsHelper.HideWithSlideAndFade(BoardImageOptionsPanel);
+
+ // Open file dialog to select image
+ var dialog = new OpenFileDialog
+ {
+ Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif"
+ };
+ if (dialog.ShowDialog() == true)
+ {
+ string filePath = dialog.FileName;
+ Image image = await CreateAndCompressImageAsync(filePath);
+ if (image != null)
+ {
+ string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
+ image.Name = timestamp;
+
+ CenterAndScaleElement(image);
+ inkCanvas.Children.Add(image);
+
+ // 添加鼠标事件处理,使图片可以被选择
+ image.MouseDown += UIElement_MouseDown;
+ image.IsManipulationEnabled = true;
+
+ timeMachine.CommitElementInsertHistory(image);
+ }
+ }
+ }
+
+ // Keep the old method for backward compatibility
private async void InsertImage_MouseUp(object sender, MouseButtonEventArgs e)
{
var dialog = new OpenFileDialog
diff --git a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs
index 43e93d76..4f76e6bf 100644
--- a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs
+++ b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs
@@ -2,8 +2,12 @@ using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
+using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
+using System.Windows.Media.Imaging;
+using Ink_Canvas.Helpers;
+using Clipboard = System.Windows.Clipboard;
namespace Ink_Canvas {
public partial class MainWindow : Window {
@@ -71,14 +75,94 @@ namespace Ink_Canvas {
private string GetDefaultFolderPath() {
var basePath = Settings.Automation.AutoSavedStrokesLocation;
var screenshotsFolder = Path.Combine(basePath, "Auto Saved - Screenshots");
-
+
if (!Directory.Exists(screenshotsFolder)) {
Directory.CreateDirectory(screenshotsFolder);
}
-
+
return Path.Combine(
- screenshotsFolder,
+ screenshotsFolder,
$"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png");
}
+
+ // 截图并复制到剪贴板
+ private async Task CaptureScreenshotToClipboard() {
+ try {
+ // 隐藏主窗口以避免截图包含窗口本身
+ var originalVisibility = this.Visibility;
+ this.Visibility = Visibility.Hidden;
+
+ // 等待窗口隐藏
+ await Task.Delay(200);
+
+ var rc = SystemInformation.VirtualScreen;
+ using (var bitmap = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb))
+ using (var memoryGraphics = Graphics.FromImage(bitmap)) {
+ memoryGraphics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy);
+
+ // 将截图复制到剪贴板
+ CopyBitmapToClipboard(bitmap);
+
+ // 恢复窗口显示
+ this.Visibility = originalVisibility;
+
+ // 等待窗口完全显示后自动粘贴
+ await Task.Delay(100);
+ await AutoPasteScreenshot();
+ }
+ }
+ catch (Exception ex) {
+ ShowNotification($"截图失败: {ex.Message}");
+ this.Visibility = Visibility.Visible;
+ }
+ }
+
+ // 自动粘贴截图到画布
+ private async Task AutoPasteScreenshot() {
+ try {
+ // 只在白板模式下自动粘贴
+ if (currentMode == 1) {
+ await PasteImageFromClipboard();
+ ShowNotification("截图已自动插入到画布");
+ } else {
+ ShowNotification("截图已复制到剪贴板,可在白板模式下粘贴");
+ }
+ }
+ catch (Exception ex) {
+ ShowNotification($"自动粘贴截图失败: {ex.Message}");
+ LogHelper.WriteLogToFile($"自动粘贴截图失败: {ex.Message}", LogHelper.LogType.Error);
+ }
+ }
+
+ // 将Bitmap复制到剪贴板
+ private void CopyBitmapToClipboard(Bitmap bitmap) {
+ try {
+ // 将System.Drawing.Bitmap转换为WPF BitmapSource
+ var bitmapSource = ConvertBitmapToBitmapSource(bitmap);
+
+ // 复制到剪贴板
+ Clipboard.SetImage(bitmapSource);
+ }
+ catch (Exception ex) {
+ ShowNotification($"复制到剪贴板失败: {ex.Message}");
+ }
+ }
+
+ // 将System.Drawing.Bitmap转换为WPF BitmapSource
+ private BitmapSource ConvertBitmapToBitmapSource(Bitmap bitmap) {
+ using (var memory = new MemoryStream()) {
+ bitmap.Save(memory, ImageFormat.Png);
+ memory.Position = 0;
+
+ var bitmapImage = new BitmapImage();
+ bitmapImage.BeginInit();
+ bitmapImage.StreamSource = memory;
+ bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
+ bitmapImage.EndInit();
+ bitmapImage.Freeze();
+
+ return bitmapImage;
+ }
+ }
}
}