diff --git a/BetterGenshinImpact.sln b/BetterGenshinImpact.sln
index bff2c958..ea739f1a 100644
--- a/BetterGenshinImpact.sln
+++ b/BetterGenshinImpact.sln
@@ -9,9 +9,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vision.WindowCapture", "Vis
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterGenshinImpact.Win32", "BetterGenshinImpact.Win32\BetterGenshinImpact.Win32.csproj", "{75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fischless.WindowCapture", "Fischless.WindowCapture\Fischless.WindowCapture.csproj", "{6B0A3D96-D88D-48DD-8112-4CD5BA5D27CE}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fischless.GameCapture", "Fischless.GameCapture\Fischless.GameCapture.csproj", "{6B0A3D96-D88D-48DD-8112-4CD5BA5D27CE}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vision.WindowCapture.Test", "Vision.WindowCapture.Test\Vision.WindowCapture.Test.csproj", "{D35CB953-C666-4E57-9A9A-3AAE5BF78402}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vision.WindowCapture.Test", "Vision.WindowCapture.Test\Vision.WindowCapture.Test.csproj", "{D35CB953-C666-4E57-9A9A-3AAE5BF78402}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj
index cbd430f2..09640c5f 100644
--- a/BetterGenshinImpact/BetterGenshinImpact.csproj
+++ b/BetterGenshinImpact/BetterGenshinImpact.csproj
@@ -38,7 +38,7 @@
-
+
diff --git a/BetterGenshinImpact/Core/Config/AllConfig.cs b/BetterGenshinImpact/Core/Config/AllConfig.cs
index 4c74aaa8..7b34ee78 100644
--- a/BetterGenshinImpact/Core/Config/AllConfig.cs
+++ b/BetterGenshinImpact/Core/Config/AllConfig.cs
@@ -1,10 +1,10 @@
-using BetterGenshinImpact.GameTask.AutoFishing;
-using BetterGenshinImpact.GameTask.AutoSkip;
-using System;
-using BetterGenshinImpact.GameTask;
+using BetterGenshinImpact.GameTask;
+using BetterGenshinImpact.GameTask.AutoFishing;
using BetterGenshinImpact.GameTask.AutoPick;
+using BetterGenshinImpact.GameTask.AutoSkip;
using CommunityToolkit.Mvvm.ComponentModel;
-using Fischless.WindowCapture;
+using Fischless.GameCapture;
+using System;
using System.Text.Json.Serialization;
namespace BetterGenshinImpact.Core.Config
diff --git a/BetterGenshinImpact/GameTask/TaskDispatcher.cs b/BetterGenshinImpact/GameTask/TaskDispatcher.cs
index 3dfc738a..bf039568 100644
--- a/BetterGenshinImpact/GameTask/TaskDispatcher.cs
+++ b/BetterGenshinImpact/GameTask/TaskDispatcher.cs
@@ -1,16 +1,12 @@
-using Fischless.WindowCapture;
+using BetterGenshinImpact.View;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
-using System.Drawing;
using System.Linq;
-using System.Text.RegularExpressions;
using System.Threading;
-using System.Windows;
-using BetterGenshinImpact.View;
+using Fischless.GameCapture;
using Vanara.PInvoke;
-using System.Windows.Threading;
namespace BetterGenshinImpact.GameTask
{
@@ -21,7 +17,7 @@ namespace BetterGenshinImpact.GameTask
private readonly System.Timers.Timer _timer = new();
private List? _triggers;
- private IWindowCapture? _capture;
+ private IGameCapture? _capture;
private static readonly object _locker = new();
private int _frameIndex = 0;
@@ -49,7 +45,7 @@ namespace BetterGenshinImpact.GameTask
_triggers = GameTaskManager.LoadTriggers();
// 初始化截图器
- _capture = WindowCaptureFactory.Create(mode);
+ _capture = GameCaptureFactory.Create(mode);
//_capture.IsClientEnabled = true;
_capture.Start(hWnd);
diff --git a/BetterGenshinImpact/View/CaptureTestWindow.xaml.cs b/BetterGenshinImpact/View/CaptureTestWindow.xaml.cs
index 7c0a545d..0e02f8a9 100644
--- a/BetterGenshinImpact/View/CaptureTestWindow.xaml.cs
+++ b/BetterGenshinImpact/View/CaptureTestWindow.xaml.cs
@@ -1,9 +1,9 @@
-using System;
+using BetterGenshinImpact.Helpers.Extensions;
+using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
-using BetterGenshinImpact.Helpers.Extensions;
-using Fischless.WindowCapture;
+using Fischless.GameCapture;
namespace BetterGenshinImpact.View
{
@@ -12,7 +12,7 @@ namespace BetterGenshinImpact.View
///
public partial class CaptureTestWindow : Window
{
- private IWindowCapture? _capture;
+ private IGameCapture? _capture;
private long _captureTime;
@@ -45,7 +45,7 @@ namespace BetterGenshinImpact.View
}
- _capture = WindowCaptureFactory.Create(captureMode);
+ _capture = GameCaptureFactory.Create(captureMode);
//_capture.IsClientEnabled = true;
_capture.Start(hWnd);
diff --git a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs
index 7bac2ee6..29696719 100644
--- a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs
+++ b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs
@@ -1,23 +1,12 @@
-using BetterGenshinImpact.GameTask;
-using BetterGenshinImpact.Helpers;
-using BetterGenshinImpact.View;
+using BetterGenshinImpact.Service.Interface;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
-using Fischless.WindowCapture;
+using CommunityToolkit.Mvvm.Messaging.Messages;
using Microsoft.Extensions.Logging;
-using System;
using System.Diagnostics;
using System.Windows;
-using BetterGenshinImpact.Core;
-using CommunityToolkit.Mvvm.Messaging.Messages;
-using Vanara.PInvoke;
-using System.Collections.ObjectModel;
-using BetterGenshinImpact.View.Pages;
using Wpf.Ui;
-using Wpf.Ui.Controls;
-using BetterGenshinImpact.Service.Interface;
-using BetterGenshinImpact.Service;
namespace BetterGenshinImpact.ViewModel
{
diff --git a/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs
index ec0920f3..c572d57d 100644
--- a/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs
+++ b/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs
@@ -1,34 +1,28 @@
using BetterGenshinImpact.Core;
+using BetterGenshinImpact.Core.Config;
+using BetterGenshinImpact.Core.Recognition.ONNX.SVTR;
using BetterGenshinImpact.GameTask;
+using BetterGenshinImpact.Helpers;
+using BetterGenshinImpact.Service.Interface;
using BetterGenshinImpact.View;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
-using Fischless.WindowCapture;
-using Microsoft.Extensions.Logging;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Net.Sockets;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows;
-using CommunityToolkit.Mvvm.Messaging.Messages;
using CommunityToolkit.Mvvm.Messaging;
-using Wpf.Ui.Controls;
-using BetterGenshinImpact.Service.Interface;
-using BetterGenshinImpact.Core.Config;
-using BetterGenshinImpact.Core.Recognition.ONNX.SVTR;
+using CommunityToolkit.Mvvm.Messaging.Messages;
+using Microsoft.Extensions.Logging;
using OpenCvSharp;
+using System;
+using System.Diagnostics;
+using System.Windows;
using System.Windows.Interop;
-using BetterGenshinImpact.Helpers;
+using Fischless.GameCapture;
+using Wpf.Ui.Controls;
namespace BetterGenshinImpact.ViewModel.Pages;
public partial class HomePageViewModel : ObservableObject, INavigationAware
{
- [ObservableProperty] private string[] _modeNames = WindowCaptureFactory.ModeNames();
+ [ObservableProperty] private string[] _modeNames = GameCaptureFactory.ModeNames();
[ObservableProperty] private string? _selectedMode = CaptureModes.BitBlt.ToString();
diff --git a/Fischless.GameCapture/BitBlt/BitBltCapture.cs b/Fischless.GameCapture/BitBlt/BitBltCapture.cs
new file mode 100644
index 00000000..7c8b5943
--- /dev/null
+++ b/Fischless.GameCapture/BitBlt/BitBltCapture.cs
@@ -0,0 +1,56 @@
+using System.Diagnostics;
+using Vanara.PInvoke;
+
+namespace Fischless.GameCapture.BitBlt;
+
+public class BitBltCapture : IGameCapture
+{
+ private nint _hWnd;
+ public bool IsCapturing { get; private set; }
+
+ public void Dispose() => Stop();
+
+ public void Start(nint hWnd)
+ {
+ _hWnd = hWnd;
+ IsCapturing = true;
+ }
+
+ public Bitmap? Capture()
+ {
+ if (_hWnd == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ try
+ {
+ User32.GetClientRect(_hWnd, out var windowRect);
+ int x = default, y = default;
+ var width = windowRect.right - windowRect.left;
+ var height = windowRect.bottom - windowRect.top;
+
+ Bitmap bitmap = new(width, height);
+ using System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap);
+ var hdcDest = g.GetHdc();
+ Gdi32.SafeHDC hdcSrc = User32.GetDC(_hWnd == IntPtr.Zero ? User32.GetDesktopWindow() : _hWnd);
+ Gdi32.StretchBlt(hdcDest, 0, 0, width, height, hdcSrc, x, y, width, height, Gdi32.RasterOperationMode.SRCCOPY);
+ g.ReleaseHdc();
+ Gdi32.DeleteDC(hdcDest);
+ Gdi32.DeleteDC(hdcSrc);
+ return bitmap;
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine(e);
+ }
+
+ return null!;
+ }
+
+ public void Stop()
+ {
+ _hWnd = IntPtr.Zero;
+ IsCapturing = false;
+ }
+}
\ No newline at end of file
diff --git a/Fischless.WindowCapture/CaptureModeExtensions.cs b/Fischless.GameCapture/CaptureModeExtensions.cs
similarity index 83%
rename from Fischless.WindowCapture/CaptureModeExtensions.cs
rename to Fischless.GameCapture/CaptureModeExtensions.cs
index d54c60c2..b2140dda 100644
--- a/Fischless.WindowCapture/CaptureModeExtensions.cs
+++ b/Fischless.GameCapture/CaptureModeExtensions.cs
@@ -1,4 +1,4 @@
-namespace Fischless.WindowCapture;
+namespace Fischless.GameCapture;
public static class CaptureModeExtensions
{
diff --git a/Fischless.WindowCapture/CaptureModes.cs b/Fischless.GameCapture/CaptureModes.cs
similarity index 53%
rename from Fischless.WindowCapture/CaptureModes.cs
rename to Fischless.GameCapture/CaptureModes.cs
index bf0e1f9a..c6c6834b 100644
--- a/Fischless.WindowCapture/CaptureModes.cs
+++ b/Fischless.GameCapture/CaptureModes.cs
@@ -1,7 +1,8 @@
-namespace Fischless.WindowCapture;
+namespace Fischless.GameCapture;
public enum CaptureModes
{
BitBlt,
WindowsGraphicsCapture,
+ DwmGetDxSharedSurface
}
diff --git a/Fischless.GameCapture/DwmSharedSurface/Helpers/NativeMethods.cs b/Fischless.GameCapture/DwmSharedSurface/Helpers/NativeMethods.cs
new file mode 100644
index 00000000..c0fe0a89
--- /dev/null
+++ b/Fischless.GameCapture/DwmSharedSurface/Helpers/NativeMethods.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Vanara.PInvoke;
+
+namespace Fischless.GameCapture.DwmSharedSurface.Helpers;
+
+internal class NativeMethods
+{
+
+ public delegate bool DwmGetDxSharedSurfaceDelegate(IntPtr hWnd, out IntPtr phSurface, out long pAdapterLuid, out long pFmtWindow, out long pPresentFlags, out long pWin32KUpdateId);
+
+ public static DwmGetDxSharedSurfaceDelegate DwmGetDxSharedSurface;
+
+ static NativeMethods()
+ {
+ var ptr = Kernel32.GetProcAddress(Kernel32.GetModuleHandle("user32"), "DwmGetDxSharedSurface");
+ DwmGetDxSharedSurface = Marshal.GetDelegateForFunctionPointer(ptr);
+ }
+}
\ No newline at end of file
diff --git a/Fischless.GameCapture/DwmSharedSurface/SharedSurfaceCapture.cs b/Fischless.GameCapture/DwmSharedSurface/SharedSurfaceCapture.cs
new file mode 100644
index 00000000..dfdcbaac
--- /dev/null
+++ b/Fischless.GameCapture/DwmSharedSurface/SharedSurfaceCapture.cs
@@ -0,0 +1,115 @@
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Windows.Controls;
+using System.Windows.Forms;
+using Fischless.GameCapture.DwmSharedSurface.Helpers;
+using Fischless.GameCapture.Graphics.Helpers;
+using SharpDX;
+using SharpDX.Direct3D;
+using SharpDX.Direct3D11;
+using SharpDX.DXGI;
+using Vanara.PInvoke;
+using Windows.Devices.HumanInterfaceDevice;
+using Device = SharpDX.Direct3D11.Device;
+
+namespace Fischless.GameCapture.DwmSharedSurface
+{
+ public class SharedSurfaceCapture : IGameCapture
+ {
+ private nint _hWnd;
+ private Device? _d3dDevice;
+
+ public void Dispose() => Stop();
+
+ public bool IsCapturing { get; private set; }
+
+ private ResourceRegion _region;
+
+ public void Start(nint hWnd)
+ {
+ _hWnd = hWnd;
+ _region = GetGameScreenRegion(hWnd);
+ _d3dDevice = new Device(SharpDX.Direct3D.DriverType.Hardware, DeviceCreationFlags.BgraSupport); // Software/Hardware
+
+ //var device = Direct3D11Helper.CreateDevice();
+ //_d3dDevice = Direct3D11Helper.CreateSharpDXDevice(device);
+
+ IsCapturing = true;
+ }
+
+ ///
+ /// 从 GetWindowRect 的带窗口阴影面积矩形 截取出 GetClientRect的矩形(游戏区域)
+ ///
+ ///
+ ///
+ private ResourceRegion GetGameScreenRegion(nint hWnd)
+ {
+ ResourceRegion region = new();
+ User32.GetWindowRect(hWnd, out var windowWithShadowRect);
+ DwmApi.DwmGetWindowAttribute(hWnd, DwmApi.DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, out var windowRect);
+ User32.GetClientRect(_hWnd, out var clientRect);
+
+ region.Left = windowRect.Left - windowWithShadowRect.Left;
+ // 标题栏 windowRect.Height - clientRect.Height 上阴影 windowRect.Top - windowWithShadowRect.Top
+ region.Top = windowRect.Height - clientRect.Height + windowRect.Top - windowWithShadowRect.Top;
+ region.Right = region.Left + clientRect.Width;
+ region.Bottom = region.Top + clientRect.Height;
+ region.Front = 0;
+ region.Back = 1;
+
+ return region;
+ }
+
+ public Bitmap? Capture()
+ {
+ if (_hWnd == nint.Zero)
+ {
+ return null;
+ }
+
+
+ NativeMethods.DwmGetDxSharedSurface(_hWnd, out var phSurface, out _, out _, out _, out _);
+ if (phSurface == nint.Zero)
+ {
+ return null;
+ }
+
+ return ToBitmap(phSurface);
+ }
+
+ private Bitmap? ToBitmap(nint phSurface)
+ {
+ if (_d3dDevice == null)
+ {
+ Debug.WriteLine("D3Device is null.");
+ return null;
+ }
+
+ using var surfaceTexture = _d3dDevice.OpenSharedResource(phSurface);
+
+ var staging = new Texture2D(_d3dDevice, new Texture2DDescription
+ {
+ Width = _region.Right - _region.Left,
+ Height = _region.Bottom - _region.Top,
+ MipLevels = 1,
+ ArraySize = 1,
+ Format = Format.B8G8R8A8_UNorm,
+ Usage = ResourceUsage.Staging,
+ SampleDescription = new SampleDescription(1, 0),
+ BindFlags = BindFlags.None,
+ CpuAccessFlags = CpuAccessFlags.Read,
+ OptionFlags = ResourceOptionFlags.None
+ });
+
+
+ return staging.CreateBitmap(_d3dDevice, surfaceTexture, _region);
+ }
+
+ public void Stop()
+ {
+ _hWnd = nint.Zero;
+ IsCapturing = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Fischless.WindowCapture/Fischless.WindowCapture.csproj b/Fischless.GameCapture/Fischless.GameCapture.csproj
similarity index 100%
rename from Fischless.WindowCapture/Fischless.WindowCapture.csproj
rename to Fischless.GameCapture/Fischless.GameCapture.csproj
diff --git a/Fischless.WindowCapture/WindowCaptureFactory.cs b/Fischless.GameCapture/GameCaptureFactory.cs
similarity index 64%
rename from Fischless.WindowCapture/WindowCaptureFactory.cs
rename to Fischless.GameCapture/GameCaptureFactory.cs
index 41179156..0bedc1d9 100644
--- a/Fischless.WindowCapture/WindowCaptureFactory.cs
+++ b/Fischless.GameCapture/GameCaptureFactory.cs
@@ -1,18 +1,19 @@
-namespace Fischless.WindowCapture;
+namespace Fischless.GameCapture;
-public class WindowCaptureFactory
+public class GameCaptureFactory
{
public static string[] ModeNames()
{
return Enum.GetNames(typeof(CaptureModes));
}
- public static IWindowCapture Create(CaptureModes mode)
+ public static IGameCapture Create(CaptureModes mode)
{
return mode switch
{
CaptureModes.BitBlt => new BitBlt.BitBltCapture(),
CaptureModes.WindowsGraphicsCapture => new Graphics.GraphicsCapture(),
+ CaptureModes.DwmGetDxSharedSurface => new DwmSharedSurface.SharedSurfaceCapture(),
_ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null),
};
}
diff --git a/Fischless.WindowCapture/Graphics/GraphicsCapture.cs b/Fischless.GameCapture/Graphics/GraphicsCapture.cs
similarity index 82%
rename from Fischless.WindowCapture/Graphics/GraphicsCapture.cs
rename to Fischless.GameCapture/Graphics/GraphicsCapture.cs
index afef2eb0..c1d770af 100644
--- a/Fischless.WindowCapture/Graphics/GraphicsCapture.cs
+++ b/Fischless.GameCapture/Graphics/GraphicsCapture.cs
@@ -1,18 +1,13 @@
-using System.Diagnostics;
-using System.Windows;
+using Fischless.GameCapture.Graphics.Helpers;
+using SharpDX.Direct3D11;
+using System.Diagnostics;
using Vanara.PInvoke;
using Windows.Graphics.Capture;
using Windows.Graphics.DirectX;
-using Fischless.WindowCapture.Graphics.Helpers;
-using SharpDX.Direct3D11;
-using System.Windows.Controls;
-using static System.Windows.Forms.VisualStyles.VisualStyleElement;
-using System.Drawing;
-using static Vanara.PInvoke.Gdi32;
-namespace Fischless.WindowCapture.Graphics;
+namespace Fischless.GameCapture.Graphics;
-public class GraphicsCapture : IWindowCapture
+public class GraphicsCapture : IGameCapture
{
private nint _hWnd;
@@ -21,7 +16,6 @@ public class GraphicsCapture : IWindowCapture
private GraphicsCaptureSession _captureSession = null!;
public bool IsCapturing { get; private set; }
- public bool IsClientEnabled { get; set; } = false;
private ResourceRegion _region;
@@ -31,10 +25,7 @@ public class GraphicsCapture : IWindowCapture
{
_hWnd = hWnd;
- if (!IsClientEnabled)
- {
- _region = GetGameScreenRegion(hWnd);
- }
+ _region = GetGameScreenRegion(hWnd);
IsCapturing = true;
@@ -58,6 +49,11 @@ public class GraphicsCapture : IWindowCapture
IsCapturing = true;
}
+ ///
+ /// 从 DwmGetWindowAttribute 的矩形 截取出 GetClientRect的矩形(游戏区域)
+ ///
+ ///
+ ///
private ResourceRegion GetGameScreenRegion(nint hWnd)
{
ResourceRegion region = new();
@@ -102,11 +98,6 @@ public class GraphicsCapture : IWindowCapture
return null;
}
- public Bitmap? Capture(int x, int y, int width, int height)
- {
- return null;
- }
-
public void Stop()
{
_captureSession?.Dispose();
diff --git a/Fischless.WindowCapture/Graphics/Helpers/CaptureHelper.cs b/Fischless.GameCapture/Graphics/Helpers/CaptureHelper.cs
similarity index 96%
rename from Fischless.WindowCapture/Graphics/Helpers/CaptureHelper.cs
rename to Fischless.GameCapture/Graphics/Helpers/CaptureHelper.cs
index 61707aa9..c3112de9 100644
--- a/Fischless.WindowCapture/Graphics/Helpers/CaptureHelper.cs
+++ b/Fischless.GameCapture/Graphics/Helpers/CaptureHelper.cs
@@ -2,7 +2,7 @@
using Windows.Graphics.Capture;
using WinRT;
-namespace Fischless.WindowCapture.Graphics;
+namespace Fischless.GameCapture.Graphics.Helpers;
public static class CaptureHelper
{
diff --git a/Fischless.WindowCapture/Graphics/Helpers/Direct3D11Helper.cs b/Fischless.GameCapture/Graphics/Helpers/Direct3D11Helper.cs
similarity index 97%
rename from Fischless.WindowCapture/Graphics/Helpers/Direct3D11Helper.cs
rename to Fischless.GameCapture/Graphics/Helpers/Direct3D11Helper.cs
index 6a5fc5ac..e312f8a6 100644
--- a/Fischless.WindowCapture/Graphics/Helpers/Direct3D11Helper.cs
+++ b/Fischless.GameCapture/Graphics/Helpers/Direct3D11Helper.cs
@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
using Windows.Graphics.DirectX.Direct3D11;
using WinRT;
-namespace Fischless.WindowCapture.Graphics;
+namespace Fischless.GameCapture.Graphics.Helpers;
[SuppressMessage("CodeQuality", "IDE0052:")]
public static class Direct3D11Helper
@@ -99,7 +99,7 @@ public static class Direct3D11Helper
public static SharpDX.Direct3D11.Device CreateSharpDXDevice(IDirect3DDevice device)
{
- var access = (IDirect3DDxgiInterfaceAccess)device;
+ var access = device.As();
var d3dPointer = access.GetInterface(ID3D11Device);
var d3dDevice = new SharpDX.Direct3D11.Device(d3dPointer);
return d3dDevice;
diff --git a/Fischless.WindowCapture/Graphics/Helpers/Texture2DExtensions.cs b/Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs
similarity index 81%
rename from Fischless.WindowCapture/Graphics/Helpers/Texture2DExtensions.cs
rename to Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs
index 81bb36cb..4301a7c1 100644
--- a/Fischless.WindowCapture/Graphics/Helpers/Texture2DExtensions.cs
+++ b/Fischless.GameCapture/Graphics/Helpers/Texture2DExtensions.cs
@@ -4,8 +4,9 @@ using Windows.Graphics.Capture;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
+using Windows.Devices.HumanInterfaceDevice;
-namespace Fischless.WindowCapture.Graphics.Helpers;
+namespace Fischless.GameCapture.Graphics.Helpers;
public static class Texture2DExtensions
{
@@ -30,16 +31,21 @@ public static class Texture2DExtensions
OptionFlags = ResourceOptionFlags.None
});
+ return staging.CreateBitmap(d3dDevice, texture2dBitmap, region);
+ }
+
+ public static Bitmap? CreateBitmap(this Texture2D staging, SharpDX.Direct3D11.Device d3dDevice, Texture2D surfaceTexture, ResourceRegion? region = null)
+ {
try
{
// Copy data
if (region != null)
{
- d3dDevice.ImmediateContext.CopySubresourceRegion(texture2dBitmap, 0, region, staging, 0);
+ d3dDevice.ImmediateContext.CopySubresourceRegion(surfaceTexture, 0, region, staging, 0);
}
else
{
- d3dDevice.ImmediateContext.CopyResource(texture2dBitmap, staging);
+ d3dDevice.ImmediateContext.CopyResource(surfaceTexture, staging);
}
var dataBox = d3dDevice.ImmediateContext.MapSubresource(staging, 0, 0, MapMode.Read,
diff --git a/Fischless.WindowCapture/Graphics/Helpers/WinRT.cs b/Fischless.GameCapture/Graphics/Helpers/WinRT.cs
similarity index 98%
rename from Fischless.WindowCapture/Graphics/Helpers/WinRT.cs
rename to Fischless.GameCapture/Graphics/Helpers/WinRT.cs
index 4b06d7f8..42df33f4 100644
--- a/Fischless.WindowCapture/Graphics/Helpers/WinRT.cs
+++ b/Fischless.GameCapture/Graphics/Helpers/WinRT.cs
@@ -3,7 +3,7 @@ using System.Reflection;
using System.Runtime.InteropServices;
using WinRT;
-namespace Fischless.WindowCapture.Graphics;
+namespace Fischless.GameCapture.Graphics;
#pragma warning disable CS0649
diff --git a/Fischless.GameCapture/IGameCapture.cs b/Fischless.GameCapture/IGameCapture.cs
new file mode 100644
index 00000000..b0c08df4
--- /dev/null
+++ b/Fischless.GameCapture/IGameCapture.cs
@@ -0,0 +1,12 @@
+namespace Fischless.GameCapture;
+
+public interface IGameCapture : IDisposable
+{
+ public bool IsCapturing { get; }
+
+ public void Start(nint hWnd);
+
+ public Bitmap? Capture();
+
+ public void Stop();
+}
diff --git a/Fischless.WindowCapture/BitBlt/BitBltCapture.cs b/Fischless.WindowCapture/BitBlt/BitBltCapture.cs
deleted file mode 100644
index 4c3bbf26..00000000
--- a/Fischless.WindowCapture/BitBlt/BitBltCapture.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-using System.Diagnostics;
-using Vanara.PInvoke;
-
-namespace Fischless.WindowCapture.BitBlt;
-
-public class BitBltCapture : IWindowCapture
-{
- private nint _hWnd;
- public bool IsCapturing { get; private set; }
- public bool IsClientEnabled { get; set; } = false;
- public bool IsCursorCaptureEnabled { get; set; } = false;
-
- public void Dispose()
- {
- Stop();
- }
-
- public void Start(nint hWnd)
- {
- _hWnd = hWnd;
- IsCapturing = true;
- }
-
- public Bitmap? Capture()
- {
- if (_hWnd == IntPtr.Zero)
- {
- return null;
- }
-
- try
- {
- if (IsClientEnabled)
- {
- _ = DwmApi.DwmGetWindowAttribute(_hWnd, DwmApi.DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, out var windowRect);
- var width = windowRect.right - windowRect.left;
- var height = windowRect.bottom - windowRect.top;
-
- var hdcSrc = User32.GetWindowDC(_hWnd);
- var hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);
- var hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height);
- var hOld = Gdi32.SelectObject(hdcDest, hBitmap);
- _ = Gdi32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, Gdi32.RasterOperationMode.SRCCOPY);
- _ = Gdi32.SelectObject(hdcDest, hOld);
- _ = Gdi32.DeleteDC(hdcDest);
- _ = User32.ReleaseDC(_hWnd, hdcSrc);
-
- var bitmap = hBitmap.ToBitmap();
- _ = Gdi32.DeleteObject(hBitmap);
- return bitmap;
- }
- else
- {
- _ = User32.GetClientRect(_hWnd, out var windowRect);
- int x = default, y = default;
- int width = windowRect.right - windowRect.left;
- int height = windowRect.bottom - windowRect.top;
-
- Bitmap bitmap = new(width, height);
- using System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap);
- nint hdcDest = g.GetHdc();
- Gdi32.SafeHDC hdcSrc = User32.GetDC(_hWnd == IntPtr.Zero ? User32.GetDesktopWindow() : _hWnd);
- _ = Gdi32.StretchBlt(hdcDest, 0, 0, width, height, hdcSrc, x, y, width, height, Gdi32.RasterOperationMode.SRCCOPY);
- g.ReleaseHdc();
- _ = Gdi32.DeleteDC(hdcDest);
- _ = Gdi32.DeleteDC(hdcSrc);
- return bitmap;
- }
- }
- 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;
- }
-
- if (IsClientEnabled)
- {
- throw new NotSupportedException();
- }
-
- try
- {
- Bitmap copied = new(width, height);
- using System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(copied);
- nint hdcDest = g.GetHdc();
- Gdi32.SafeHDC hdcSrc = User32.GetDC(_hWnd == IntPtr.Zero ? User32.GetDesktopWindow() : _hWnd);
- _ = Gdi32.StretchBlt(hdcDest, 0, 0, width, height, hdcSrc, x, y, width, height, Gdi32.RasterOperationMode.SRCCOPY);
- g.ReleaseHdc();
- _ = Gdi32.DeleteDC(hdcDest);
- _ = Gdi32.DeleteDC(hdcSrc);
- return copied;
- }
- catch (Exception e)
- {
- Debug.WriteLine(e);
- }
- return null;
- }
-
- public void Stop()
- {
- _hWnd = IntPtr.Zero;
- IsCapturing = false;
- }
-}
diff --git a/Fischless.WindowCapture/IWindowCapture.cs b/Fischless.WindowCapture/IWindowCapture.cs
deleted file mode 100644
index 21f741a8..00000000
--- a/Fischless.WindowCapture/IWindowCapture.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace Fischless.WindowCapture;
-
-public interface IWindowCapture : IDisposable
-{
- public bool IsCapturing { get; }
- public bool IsClientEnabled { get; set; }
-
- public void Start(nint hWnd);
-
- public Bitmap? Capture();
- public Bitmap? Capture(int x, int y, int width, int height);
-
- public void Stop();
-}