mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-03-26 09:39:49 +08:00
153 lines
4.1 KiB
C#
153 lines
4.1 KiB
C#
using System.Diagnostics;
|
|
using System.Windows;
|
|
using Vanara.PInvoke;
|
|
using Windows.Graphics.Capture;
|
|
using Windows.Graphics.DirectX;
|
|
|
|
namespace Fischless.WindowCapture.Graphics;
|
|
|
|
public class GraphicsCapture : IWindowCapture
|
|
{
|
|
private nint _hWnd;
|
|
|
|
private Direct3D11CaptureFramePool _captureFramePool = null!;
|
|
private GraphicsCaptureItem _captureItem = null!;
|
|
private GraphicsCaptureSession _captureSession = null!;
|
|
|
|
public bool IsCapturing { get; private set; }
|
|
public bool IsClientEnabled { get; set; } = false;
|
|
|
|
public void Dispose()
|
|
{
|
|
Stop();
|
|
}
|
|
|
|
public void Start(nint hWnd)
|
|
{
|
|
_hWnd = hWnd;
|
|
IsCapturing = true;
|
|
|
|
_captureItem = CaptureHelper.CreateItemForWindow(_hWnd);
|
|
|
|
if (_captureItem == null)
|
|
{
|
|
throw new InvalidOperationException("Failed to create capture item.");
|
|
}
|
|
|
|
_captureItem.Closed += CaptureItemOnClosed;
|
|
|
|
var device = Direct3D11Helper.CreateDevice();
|
|
|
|
_captureFramePool = Direct3D11CaptureFramePool.Create(device, DirectXPixelFormat.B8G8R8A8UIntNormalized, 2,
|
|
_captureItem.Size);
|
|
_captureSession = _captureFramePool.CreateCaptureSession(_captureItem);
|
|
_captureSession.IsCursorCaptureEnabled = false;
|
|
_captureSession.IsBorderRequired = false;
|
|
_captureSession.StartCapture();
|
|
IsCapturing = true;
|
|
}
|
|
|
|
public Bitmap? Capture()
|
|
{
|
|
if (_hWnd == IntPtr.Zero)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
try
|
|
{
|
|
using var frame = _captureFramePool?.TryGetNextFrame();
|
|
|
|
if (frame == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
Bitmap? bitmap = frame.ToBitmap();
|
|
|
|
if (bitmap == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (IsClientEnabled)
|
|
{
|
|
return bitmap;
|
|
}
|
|
else
|
|
{
|
|
_ = User32.GetClientRect(_hWnd, out var windowRect);
|
|
int border = Math.Max(SystemParameters.Border, 1);
|
|
int captionHeight = CaptionHelper.IsFullScreenMode(_hWnd)
|
|
? default
|
|
: Math.Max(CaptionHelper.GetSystemCaptionHeight(), frame.ContentSize.Height - windowRect.Height - border * 2);
|
|
|
|
using (bitmap)
|
|
{
|
|
return bitmap.Crop(
|
|
border,
|
|
border + captionHeight,
|
|
frame.ContentSize.Width - border * 2,
|
|
frame.ContentSize.Height - border * 2 - captionHeight
|
|
);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.WriteLine(e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public Bitmap? Capture(int x, int y, int width, int height)
|
|
{
|
|
if (_hWnd == IntPtr.Zero)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
try
|
|
{
|
|
using var frame = _captureFramePool?.TryGetNextFrame();
|
|
using Bitmap bitmap = frame?.ToBitmap();
|
|
_ = User32.GetClientRect(_hWnd, out var windowRect);
|
|
int border = Math.Max(SystemParameters.Border, 1);
|
|
int captionHeight = CaptionHelper.IsFullScreenMode(_hWnd)
|
|
? default
|
|
: Math.Max(CaptionHelper.GetSystemCaptionHeight()
|
|
, frame.ContentSize.Height - windowRect.Height - border * 2
|
|
);
|
|
|
|
return bitmap.Crop(
|
|
border + x,
|
|
border + y + captionHeight,
|
|
width - border * 2,
|
|
height - border * 2 - captionHeight
|
|
);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.WriteLine(e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
_captureSession?.Dispose();
|
|
_captureFramePool?.Dispose();
|
|
_captureSession = null!;
|
|
_captureFramePool = null!;
|
|
_captureItem = null!;
|
|
|
|
_hWnd = IntPtr.Zero;
|
|
IsCapturing = false;
|
|
}
|
|
|
|
private void CaptureItemOnClosed(GraphicsCaptureItem sender, object args)
|
|
{
|
|
Stop();
|
|
}
|
|
}
|