Files
better-genshin-impact/Fischless.WindowCapture/Graphics/GraphicsCapture.cs
2023-10-02 18:00:14 +08:00

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();
}
}