add:截图功能

This commit is contained in:
2025-07-30 19:56:22 +08:00
parent 9f9775e585
commit 00554e066b
5 changed files with 522 additions and 5 deletions
@@ -0,0 +1,267 @@
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using Ink_Canvas.Helpers;
namespace Ink_Canvas
{
public partial class MainWindow : Window
{
private bool isClipboardMonitoringEnabled = false;
private BitmapSource lastClipboardImage = null;
// 初始化剪贴板监控
private void InitializeClipboardMonitoring()
{
try
{
// 监听剪贴板变化
ClipboardNotification.ClipboardUpdate += OnClipboardUpdate;
isClipboardMonitoringEnabled = true;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"初始化剪贴板监控失败: {ex.Message}", LogHelper.LogType.Error);
}
}
// 剪贴板内容变化事件处理
private void OnClipboardUpdate()
{
try
{
if (Clipboard.ContainsImage())
{
var clipboardImage = Clipboard.GetImage();
if (clipboardImage != null && clipboardImage != lastClipboardImage)
{
lastClipboardImage = clipboardImage;
// 在白板模式下显示粘贴提示
if (currentMode == 1) // 白板模式
{
ShowPasteNotification();
}
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理剪贴板更新失败: {ex.Message}", LogHelper.LogType.Error);
}
}
// 显示粘贴提示
private void ShowPasteNotification()
{
try
{
Dispatcher.Invoke(() =>
{
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();
}
}
}
@@ -208,6 +208,7 @@ namespace Ink_Canvas {
BorderSettings.Visibility = Visibility.Collapsed;
BoardBorderLeftPageListView.Visibility = Visibility.Collapsed;
BoardBorderRightPageListView.Visibility = Visibility.Collapsed;
BoardImageOptionsPanel.Visibility = Visibility.Collapsed;
}
/// <summary>
@@ -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
+87 -3
View File
@@ -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;
}
}
}
}