feat: 浮动栏截图修改为选区截图,添加“添加到白板”按钮 (#377)
* 调整截图按钮默认行为为选区/白板全屏 * 截图选择器新增添加到白板按钮并支持新建白板页插入 * 修复添加到白板不生效:改为剪贴板复制粘贴插入 * 修复添加到白板截图时序:先截到内存再进白板 * Fix screenshot insert flow honoring add-to-whiteboard option * Refine screenshot selector freehand confirm and blank double-click full select * Fix freehand whiteboard insert alpha transparency * Fix screenshot insert notification text for whiteboard flow * Adjust screenshot selection: right-click/double-click full-select and keep selector on single click * Show unmasked freehand selection area like rectangle mode * Remove freehand cutout mask rendering from screenshot selector * Restore freehand selected-area unmask behavior in selector
This commit is contained in:
@@ -1130,7 +1130,16 @@ namespace Ink_Canvas
|
||||
{
|
||||
HideSubPanelsImmediately();
|
||||
await Task.Delay(50);
|
||||
SaveScreenShotToDesktop();
|
||||
|
||||
// 白板模式下默认全屏截图到桌面;其余模式默认调用可选区截图
|
||||
if (currentMode == 1)
|
||||
{
|
||||
SaveScreenShotToDesktop();
|
||||
}
|
||||
else
|
||||
{
|
||||
await SaveAreaScreenShotToDesktop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -4309,4 +4318,4 @@ namespace Ink_Canvas
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,13 +29,16 @@ namespace Ink_Canvas
|
||||
public List<Point> Path;
|
||||
public Bitmap CameraImage;
|
||||
public BitmapSource CameraBitmapSource;
|
||||
public bool AddToWhiteboard;
|
||||
|
||||
public ScreenshotResult(Rectangle area, List<Point> path = null, Bitmap cameraImage = null, BitmapSource cameraBitmapSource = null)
|
||||
public ScreenshotResult(Rectangle area, List<Point> path = null, Bitmap cameraImage = null,
|
||||
BitmapSource cameraBitmapSource = null, bool addToWhiteboard = false)
|
||||
{
|
||||
Area = area;
|
||||
Path = path;
|
||||
CameraImage = cameraImage;
|
||||
CameraBitmapSource = cameraBitmapSource;
|
||||
AddToWhiteboard = addToWhiteboard;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,11 +75,17 @@ namespace Ink_Canvas
|
||||
|
||||
if (screenshotResult.HasValue)
|
||||
{
|
||||
if (screenshotResult.Value.AddToWhiteboard)
|
||||
{
|
||||
await AddScreenshotToNewWhiteboardPage(screenshotResult.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否是摄像头截图
|
||||
if (screenshotResult.Value.CameraBitmapSource != null)
|
||||
{
|
||||
// 摄像头截图(使用BitmapSource)
|
||||
await InsertBitmapSourceToCanvas(screenshotResult.Value.CameraBitmapSource);
|
||||
await InsertBitmapSourceToCanvas(screenshotResult.Value.CameraBitmapSource, "摄像头截图已插入到画布", "插入摄像头截图失败");
|
||||
}
|
||||
else if (screenshotResult.Value.CameraImage != null)
|
||||
{
|
||||
@@ -208,7 +217,8 @@ namespace Ink_Canvas
|
||||
Rectangle.Empty, // 摄像头截图不需要区域
|
||||
null, // 摄像头截图不需要路径
|
||||
null, // 不再使用Bitmap
|
||||
selectorWindow.CameraBitmapSource // 摄像头BitmapSource
|
||||
selectorWindow.CameraBitmapSource, // 摄像头BitmapSource
|
||||
selectorWindow.ShouldAddToWhiteboard
|
||||
);
|
||||
}
|
||||
else if (selectorWindow.CameraImage != null)
|
||||
@@ -216,14 +226,19 @@ namespace Ink_Canvas
|
||||
result = new ScreenshotResult(
|
||||
Rectangle.Empty, // 摄像头截图不需要区域
|
||||
null, // 摄像头截图不需要路径
|
||||
selectorWindow.CameraImage // 摄像头图像
|
||||
selectorWindow.CameraImage, // 摄像头图像
|
||||
null,
|
||||
selectorWindow.ShouldAddToWhiteboard
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new ScreenshotResult(
|
||||
selectorWindow.SelectedArea.Value,
|
||||
selectorWindow.SelectedPath
|
||||
selectorWindow.SelectedPath,
|
||||
null,
|
||||
null,
|
||||
selectorWindow.ShouldAddToWhiteboard
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -403,7 +418,7 @@ namespace Ink_Canvas
|
||||
/// 8. 提交历史记录
|
||||
/// 9. 插入图片后切换到选择模式并刷新浮动栏高光显示
|
||||
/// </remarks>
|
||||
private async Task InsertBitmapSourceToCanvas(BitmapSource bitmapSource)
|
||||
private async Task InsertBitmapSourceToCanvas(BitmapSource bitmapSource, string successMessage = "截图已插入到画布", string failureMessagePrefix = "插入截图失败")
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -452,11 +467,11 @@ namespace Ink_Canvas
|
||||
UpdateCurrentToolMode("select");
|
||||
HideSubPanels("select");
|
||||
|
||||
ShowNotification("摄像头截图已插入到画布");
|
||||
ShowNotification(successMessage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ShowNotification($"插入摄像头截图失败: {ex.Message}");
|
||||
ShowNotification($"{failureMessagePrefix}: {ex.Message}");
|
||||
LogHelper.WriteLogToFile($"插入摄像头截图失败: {ex.Message}", LogHelper.LogType.Error);
|
||||
}
|
||||
}
|
||||
@@ -841,11 +856,12 @@ namespace Ink_Canvas
|
||||
if (bitmap == null || bitmap.Width <= 0 || bitmap.Height <= 0)
|
||||
return null;
|
||||
|
||||
// 创建一个新的位图,确保格式正确
|
||||
using (var convertedBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format24bppRgb))
|
||||
// 创建一个新的位图,确保保留Alpha通道
|
||||
using (var convertedBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb))
|
||||
{
|
||||
using (var graphics = Graphics.FromImage(convertedBitmap))
|
||||
{
|
||||
graphics.CompositingMode = CompositingMode.SourceCopy;
|
||||
graphics.DrawImage(bitmap, 0, 0);
|
||||
}
|
||||
|
||||
@@ -951,4 +967,4 @@ namespace Ink_Canvas
|
||||
return 1.0; // 默认DPI
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Ink;
|
||||
using Ink_Canvas.Helpers;
|
||||
|
||||
@@ -159,6 +160,160 @@ namespace Ink_Canvas
|
||||
SaveInkCanvasStrokes(false);
|
||||
}
|
||||
|
||||
internal async Task SaveAreaScreenShotToDesktop()
|
||||
{
|
||||
try
|
||||
{
|
||||
var originalVisibility = Visibility;
|
||||
Visibility = Visibility.Hidden;
|
||||
await Task.Delay(200);
|
||||
|
||||
var screenshotResult = await ShowScreenshotSelector();
|
||||
Visibility = originalVisibility;
|
||||
|
||||
if (!screenshotResult.HasValue)
|
||||
{
|
||||
ShowNotification("截图已取消");
|
||||
return;
|
||||
}
|
||||
|
||||
if (screenshotResult.Value.AddToWhiteboard)
|
||||
{
|
||||
await AddScreenshotToNewWhiteboardPage(screenshotResult.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (screenshotResult.Value.Area.Width <= 0 || screenshotResult.Value.Area.Height <= 0)
|
||||
{
|
||||
ShowNotification("未选择有效截图区域");
|
||||
return;
|
||||
}
|
||||
|
||||
var desktopPath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),
|
||||
$"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png");
|
||||
|
||||
using (var originalBitmap = CaptureScreenArea(screenshotResult.Value.Area))
|
||||
{
|
||||
if (originalBitmap == null)
|
||||
{
|
||||
ShowNotification("截图失败");
|
||||
return;
|
||||
}
|
||||
|
||||
Bitmap finalBitmap = originalBitmap;
|
||||
bool needDisposeFinalBitmap = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (screenshotResult.Value.Path != null && screenshotResult.Value.Path.Count > 0)
|
||||
{
|
||||
finalBitmap = ApplyShapeMask(originalBitmap, screenshotResult.Value.Path, screenshotResult.Value.Area);
|
||||
needDisposeFinalBitmap = true;
|
||||
}
|
||||
|
||||
var directory = Path.GetDirectoryName(desktopPath);
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
finalBitmap.Save(desktopPath, ImageFormat.Png);
|
||||
ShowNotification($"截图成功保存至 {desktopPath}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (needDisposeFinalBitmap && finalBitmap != originalBitmap)
|
||||
{
|
||||
finalBitmap.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings.Automation.IsAutoSaveStrokesAtScreenshot)
|
||||
SaveInkCanvasStrokes(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Visibility = Visibility.Visible;
|
||||
ShowNotification($"截图失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task AddScreenshotToNewWhiteboardPage(ScreenshotResult screenshotResult)
|
||||
{
|
||||
// 先在当前场景准备截图数据,再进白板,避免误截到白板页面
|
||||
BitmapSource bitmapSourceForClipboard = null;
|
||||
|
||||
// 摄像头截图(BitmapSource)
|
||||
if (screenshotResult.CameraBitmapSource != null)
|
||||
{
|
||||
bitmapSourceForClipboard = screenshotResult.CameraBitmapSource;
|
||||
}
|
||||
// 摄像头截图(Bitmap)
|
||||
else if (screenshotResult.CameraImage != null)
|
||||
{
|
||||
bitmapSourceForClipboard = ConvertBitmapToBitmapSource(screenshotResult.CameraImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (screenshotResult.Area.Width <= 0 || screenshotResult.Area.Height <= 0)
|
||||
{
|
||||
ShowNotification("未选择有效截图区域");
|
||||
return;
|
||||
}
|
||||
|
||||
using (var originalBitmap = CaptureScreenArea(screenshotResult.Area))
|
||||
{
|
||||
if (originalBitmap == null)
|
||||
{
|
||||
ShowNotification("截图失败");
|
||||
return;
|
||||
}
|
||||
|
||||
Bitmap finalBitmap = originalBitmap;
|
||||
bool needDisposeFinalBitmap = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (screenshotResult.Path != null && screenshotResult.Path.Count > 0)
|
||||
{
|
||||
finalBitmap = ApplyShapeMask(originalBitmap, screenshotResult.Path, screenshotResult.Area);
|
||||
needDisposeFinalBitmap = true;
|
||||
}
|
||||
|
||||
bitmapSourceForClipboard = ConvertBitmapToBitmapSource(finalBitmap);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (needDisposeFinalBitmap && finalBitmap != originalBitmap)
|
||||
{
|
||||
finalBitmap.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bitmapSourceForClipboard == null)
|
||||
{
|
||||
ShowNotification("截图转换失败");
|
||||
return;
|
||||
}
|
||||
|
||||
// 图像已拷贝到内存后再进入白板
|
||||
bitmapSourceForClipboard.Freeze();
|
||||
|
||||
if (currentMode != 1)
|
||||
{
|
||||
SwitchToBoardMode();
|
||||
await Task.Delay(150);
|
||||
}
|
||||
|
||||
BtnWhiteBoardAdd_Click(null, EventArgs.Empty);
|
||||
|
||||
await InsertBitmapSourceToCanvas(bitmapSourceForClipboard);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提取公共的截图和保存逻辑
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user