Skip to content

Commit

Permalink
新增 支持用户直接通过截图框选位置
Browse files Browse the repository at this point in the history
重构 截图2/n
修复 搜索框激活后未取得焦点
  • Loading branch information
MakesYT committed May 18, 2024
1 parent 8009698 commit 29e16aa
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 135 deletions.
12 changes: 0 additions & 12 deletions Core/SDKs/Services/IScreenCapture.cs

This file was deleted.

5 changes: 4 additions & 1 deletion Core/SDKs/Services/IScreenCaptureWindow.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
namespace Core.SDKs.Services;
using PluginCore;

namespace Core.SDKs.Services;

public interface IScreenCaptureWindow
{
public void CaptureScreen();
public Task<ScreenCaptureInfo> GetScreenCaptureInfo();
}
82 changes: 13 additions & 69 deletions Core/SDKs/Tools/ScreenCapture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Avalonia;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using PluginCore;
using ScreenCapture.NET;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Bmp;
Expand All @@ -15,7 +16,7 @@
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using IScreenCapture = Core.SDKs.Services.IScreenCapture;
using IScreenCapture = PluginCore.IScreenCapture;

namespace Core.SDKs.Tools;

Expand Down Expand Up @@ -100,20 +101,25 @@ private static Configuration CreateDefaultInstance()
return (bitmaps, mosaics);
}

public (Bitmap?, Bitmap?)? CaptureScreen(int index, bool withMosaic = false)
public (Bitmap?, Bitmap?)? CaptureScreen(ScreenCaptureInfo screenCaptureInfo, bool withMosaic = false)
{
using var screenCaptureService = new DX11ScreenCaptureService();
var graphicsCards = screenCaptureService.GetGraphicsCards();

var enumerable = screenCaptureService.GetDisplays(graphicsCards.First());
if (index + 1 > enumerable.Count())
if (screenCaptureInfo.Index + 1 > enumerable.Count())
{
return (null, null);
}

var display = enumerable.ElementAtOrDefault(index);
var display = enumerable.ElementAtOrDefault(screenCaptureInfo.Index);
var x = System.Math.Max(screenCaptureInfo.X, 0);
var y = System.Math.Max(screenCaptureInfo.Y, 0);
var width = System.Math.Max(screenCaptureInfo.Width, display.Width);
var height = System.Math.Max(screenCaptureInfo.Height, display.Height);

using var screenCapture = screenCaptureService.GetScreenCapture(display);
var captureZone = screenCapture.RegisterCaptureZone(0, 0, display.Width, display.Height);
var captureZone = screenCapture.RegisterCaptureZone(x, y, width, height);

while (!screenCapture.CaptureScreen()) ;
using var loadPixelData = Image.LoadPixelData<Bgra32>(Lazy.Value,
Expand Down Expand Up @@ -167,70 +173,8 @@ private static Configuration CreateDefaultInstance()
return (bitmap, mosaic);
}

public (Bitmap?, Bitmap?)? CaptureScreen(int index, int x, int y, int width, int height, bool withMosaic = false)
public ScreenCaptureInfo GetScreenCaptureInfoByUserManual()
{
using var screenCaptureService = new DX11ScreenCaptureService();
var graphicsCards = screenCaptureService.GetGraphicsCards();

var enumerable = screenCaptureService.GetDisplays(graphicsCards.First());
if (index + 1 > enumerable.Count())
{
return (null, null);
}

var display = enumerable.ElementAtOrDefault(index);
using var screenCapture = screenCaptureService.GetScreenCapture(display);
var captureZone = screenCapture.RegisterCaptureZone(x, y, width, height);

while (!screenCapture.CaptureScreen()) ;
using var loadPixelData = Image.LoadPixelData<Bgra32>(Lazy.Value,
captureZone.RawBuffer,
captureZone.Width, captureZone.Height);
Bitmap? mosaic = null;
if (withMosaic)
{
var clone = loadPixelData.Clone();
using (clone)
{
clone.Mutate(x => x.BoxBlur(10));
if (!clone.DangerousTryGetSinglePixelMemory(out Memory<Bgra32> memory1))
{
throw new Exception(
"This can only happen with multi-GB images or when PreferContiguousImageBuffers is not set to true.");
}

using (MemoryHandle pinHandle = memory1.Pin())
{
unsafe
{
var bitmap1 = new Bitmap(PixelFormat.Bgra8888, AlphaFormat.Unpremul, (IntPtr)pinHandle.Pointer,
new PixelSize(captureZone.Width, captureZone.Height), new Vector(96, 96),
(captureZone.Height * PixelFormat.Bgra8888.BitsPerPixel + 7) / 8);
mosaic = bitmap1;
}
}
}
}

if (!loadPixelData.DangerousTryGetSinglePixelMemory(out Memory<Bgra32> memory))
{
throw new Exception(
"This can only happen with multi-GB images or when PreferContiguousImageBuffers is not set to true.");
}

Bitmap? bitmap = null;
using (MemoryHandle pinHandle = memory.Pin())
{
unsafe
{
var bitmap1 = new Bitmap(PixelFormat.Bgra8888, AlphaFormat.Unpremul, (IntPtr)pinHandle.Pointer,
new PixelSize(captureZone.Width, captureZone.Height), new Vector(96, 96),
(captureZone.Height * PixelFormat.Bgra8888.BitsPerPixel + 7) / 8);
bitmap = bitmap1;
}
}


return (bitmap, mosaic);
throw new NotImplementedException();
}
}
1 change: 1 addition & 0 deletions KitopiaAvalonia/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ private static IServiceProvider ConfigureServices()
services.AddTransient<ISearchWindowService, SearchWindowService>();
services.AddTransient<IErrorWindow, ErrorWindow>();
services.AddTransient<IScreenCaptureWindow, Services.ScreenCaptureWindow>();
services.AddTransient<IScreenCapture, Core.SDKs.Tools.ScreenCapture>();
services.AddTransient<IPluginToolService, PluginToolService>();

services.AddTransient<INavigationPageService, NavigationPageService>();
Expand Down
87 changes: 85 additions & 2 deletions KitopiaAvalonia/Services/ScreenCaptureWindow.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,94 @@
using Core.SDKs.Services;
using System;
using System.Threading;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Media;
using Core.SDKs.Services;
using Microsoft.Extensions.DependencyInjection;
using PluginCore;

namespace KitopiaAvalonia.Services;

public class ScreenCaptureWindow : IScreenCaptureWindow
{
public void CaptureScreen()
{
Tools.ScreenCapture.StartUserManualCapture();
var captureAllScreen = ServiceManager.Services.GetService<IScreenCapture>()!.CaptureAllScreen();
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
var screens = desktop.MainWindow.Screens;
for (var index = 0; index < screens.All.Count; index++)
{
var screen = screens.All[index];
var rect = screen.Bounds;
var window = new Windows.ScreenCaptureWindow(index)
{
Position = new PixelPoint(rect.X, rect.Y),
WindowState = WindowState.FullScreen,
SystemDecorations = SystemDecorations.None,
Background = new SolidColorBrush(Colors.Black),
ShowInTaskbar = false,
Topmost = false,
CanResize = false,
IsVisible = true,
};
window.MosaicImage.Source = captureAllScreen.Item2.Count > 0 ? captureAllScreen.Item2.Dequeue() : null;
window.Image.Source = captureAllScreen.Item1.Count > 0 ? captureAllScreen.Item1.Dequeue() : null;
window.Show();
}
}

captureAllScreen.Item2.Clear();
captureAllScreen.Item1.Clear();
GC.Collect(2, GCCollectionMode.Aggressive);
}

public async Task<ScreenCaptureInfo> GetScreenCaptureInfo()
{
ScreenCaptureInfo screenCaptureInfo = new ScreenCaptureInfo()
{
Index = -1
};
SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
Action<ScreenCaptureInfo> action = (info) => {
screenCaptureInfo = info;
semaphore.Release();
};
await semaphore.WaitAsync();
var captureAllScreen = ServiceManager.Services.GetService<IScreenCapture>()!.CaptureAllScreen();
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
var screens = desktop.MainWindow.Screens;
for (var index = 0; index < screens.All.Count; index++)
{
var screen = screens.All[index];
var rect = screen.Bounds;
var window = new Windows.ScreenCaptureWindow(index)
{
Position = new PixelPoint(rect.X, rect.Y),
WindowState = WindowState.FullScreen,
SystemDecorations = SystemDecorations.None,
Background = new SolidColorBrush(Colors.Black),
ShowInTaskbar = false,
Topmost = false,
CanResize = false,
IsVisible = true,
};
window.MosaicImage.Source = captureAllScreen.Item2.Count > 0 ? captureAllScreen.Item2.Dequeue() : null;
window.Image.Source = captureAllScreen.Item1.Count > 0 ? captureAllScreen.Item1.Dequeue() : null;
window.SetToSelectMode(action);
window.Show();
}
}

await semaphore.WaitAsync();
captureAllScreen.Item2.Clear();
captureAllScreen.Item1.Clear();
semaphore.Dispose();
GC.Collect(2, GCCollectionMode.Aggressive);

return screenCaptureInfo;
}
}
13 changes: 7 additions & 6 deletions KitopiaAvalonia/Services/SearchWindowService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ public class SearchWindowService : ISearchWindowService
{
public void ShowOrHiddenSearchWindow()
{
Dispatcher.UIThread.InvokeAsync(() =>
{
Dispatcher.UIThread.InvokeAsync(() => {
var searchWindow = ServiceManager.Services.GetService<SearchWindow>();
if (searchWindow!.IsVisible)
{
Expand All @@ -24,14 +23,16 @@ public void ShowOrHiddenSearchWindow()
ServiceManager.Services.GetService<SearchWindowViewModel>()!.CheckClipboard();
ServiceManager.Services.GetService<IWindowTool>()!.MoveWindowToMouseScreenCenter(searchWindow);
searchWindow.Show();
ServiceManager.Services.GetService<IWindowTool>()!.SetForegroundWindow(searchWindow!.TryGetPlatformHandle()!.Handle);
ServiceManager.Services.GetService<IWindowTool>()!.SetForegroundWindow(
searchWindow!.TryGetPlatformHandle()!.Handle);
searchWindow.Focus();
searchWindow.tx.Focus();
searchWindow.tx.SelectAll();
Task.Run(() =>
{
Task.Run(() => {
Thread.CurrentThread.Priority = ThreadPriority.Lowest;
ServiceManager.Services.GetService<IWindowTool>()!.SetForegroundWindow(
searchWindow!.TryGetPlatformHandle()!.Handle);
ServiceManager.Services.GetService<SearchWindowViewModel>()!.ReloadApps();
});
}
Expand Down
44 changes: 0 additions & 44 deletions KitopiaAvalonia/Tools/ScreenCapture.cs

This file was deleted.

29 changes: 28 additions & 1 deletion KitopiaAvalonia/Windows/ScreenCaptureWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using KitopiaAvalonia.Controls.Capture;
using KitopiaAvalonia.SDKs;
using Microsoft.Extensions.DependencyInjection;
using PluginCore;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Point = Avalonia.Point;
Expand All @@ -32,10 +33,14 @@ public partial class ScreenCaptureWindow : Window
private Point _startPoint;
public Stack<ScreenCaptureRedoInfo> redoStack = new();
private List<CaptureToolBase> tools = new();
private bool selectMode = false;
private Action<ScreenCaptureInfo> selectModeAction;
private int Index = 0;

public ScreenCaptureWindow()
public ScreenCaptureWindow(int index)
{
InitializeComponent();
Index = index;
WeakReferenceMessenger.Default.Register<string, string>(this, "ScreenCapture", (sender, message) => {
switch (message)
{
Expand Down Expand Up @@ -71,6 +76,12 @@ public ScreenCaptureWindow()
});
}

public void SetToSelectMode(Action<ScreenCaptureInfo> selectModeAction)
{
selectMode = true;
this.selectModeAction = selectModeAction;
}

bool ShowAlignLine => !IsSelected && PointerOver && !Selecting;


Expand Down Expand Up @@ -182,6 +193,22 @@ private void CompletedSelection()

WeakReferenceMessenger.Default.Send<string, string>("Selected", "ScreenCapture");
UpdateSelectBox();
if (selectMode)
{
selectModeAction?.Invoke(new ScreenCaptureInfo()
{
Index = Index,
X = (int)SelectBox._dragTransform.X,
Y = (int)SelectBox._dragTransform.Y,
Width = (int)SelectBox.Width,
Height = (int)SelectBox.Height
});
Image.Source = null;

WeakReferenceMessenger.Default.Send<string, string>("Close", "ScreenCapture");
this.Close();
}

if (ConfigManger.Config.截图直接复制到剪贴板)
{
if (Image.Source is Bitmap bitmap)
Expand Down

0 comments on commit 29e16aa

Please sign in to comment.