mirror of
https://github.com/babalae/better-genshin-impact
synced 2025-01-08 11:57:53 +08:00
feat: init
This commit is contained in:
commit
2cf632195c
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
.vs/
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Mine
|
||||
Tmp/
|
||||
/packages/
|
||||
node_modules/
|
31
BetterGenshinImpact.sln
Normal file
31
BetterGenshinImpact.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.6.33815.320
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BetterGenshinImpact", "BetterGenshinImpact\BetterGenshinImpact.csproj", "{75EC89E2-413D-4725-BCEA-AFAC57708F07}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vision.WindowCapture", "Vision.WindowCapture\Vision.WindowCapture.csproj", "{C9080C1D-1B26-46CB-A494-A5E7FE3FCEBA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{75EC89E2-413D-4725-BCEA-AFAC57708F07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{75EC89E2-413D-4725-BCEA-AFAC57708F07}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{75EC89E2-413D-4725-BCEA-AFAC57708F07}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{75EC89E2-413D-4725-BCEA-AFAC57708F07}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C9080C1D-1B26-46CB-A494-A5E7FE3FCEBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C9080C1D-1B26-46CB-A494-A5E7FE3FCEBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C9080C1D-1B26-46CB-A494-A5E7FE3FCEBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C9080C1D-1B26-46CB-A494-A5E7FE3FCEBA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {352D8B78-9DE3-4E58-985F-FADD22594DB4}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
9
BetterGenshinImpact/App.xaml
Normal file
9
BetterGenshinImpact/App.xaml
Normal file
@ -0,0 +1,9 @@
|
||||
<Application x:Class="BetterGenshinImpact.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:BetterGenshinImpact"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
17
BetterGenshinImpact/App.xaml.cs
Normal file
17
BetterGenshinImpact/App.xaml.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace BetterGenshinImpact
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
10
BetterGenshinImpact/AssemblyInfo.cs
Normal file
10
BetterGenshinImpact/AssemblyInfo.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.Windows;
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
14
BetterGenshinImpact/BetterGenshinImpact.csproj
Normal file
14
BetterGenshinImpact/BetterGenshinImpact.csproj
Normal file
@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net7.0-windows10.0.22000.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Vision.WindowCapture\Vision.WindowCapture.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
28
BetterGenshinImpact/Extensions/BitmapExtension.cs
Normal file
28
BetterGenshinImpact/Extensions/BitmapExtension.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace BetterGenshinImpact.Extensions
|
||||
{
|
||||
public static class BitmapExtension
|
||||
{
|
||||
|
||||
public static BitmapImage ToBitmapImage(this Bitmap bitmap)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
|
||||
BitmapImage image = new BitmapImage();
|
||||
image.BeginInit();
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
image.StreamSource = ms;
|
||||
image.EndInit();
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
26
BetterGenshinImpact/MainWindow.xaml
Normal file
26
BetterGenshinImpact/MainWindow.xaml
Normal file
@ -0,0 +1,26 @@
|
||||
<Window x:Class="BetterGenshinImpact.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BetterGenshinImpact"
|
||||
mc:Ignorable="d"
|
||||
Title="MainWindow" Height="450" Width="800"
|
||||
AllowsTransparency="True"
|
||||
WindowStyle="None"
|
||||
Topmost="True"
|
||||
ShowInTaskbar="False"
|
||||
DataContext="{Binding RelativeSource={RelativeSource Self}}">
|
||||
<Window.Background>
|
||||
<SolidColorBrush Color="#FFB0B0B0"
|
||||
Opacity="0" />
|
||||
</Window.Background>
|
||||
<Grid>
|
||||
<Image x:Name="ImageResult" HorizontalAlignment="Left" Height="172" Margin="129,10,0,0" VerticalAlignment="Top" Width="281"/>
|
||||
<Button x:Name="StartBtn" Content="开始捕获" HorizontalAlignment="Left" Height="22" Margin="10,10,0,0" VerticalAlignment="Top" Width="78" Click="Button_Click"/>
|
||||
<ComboBox x:Name="CboCaptureType" HorizontalAlignment="Left" Height="23" Margin="10,173,0,0" VerticalAlignment="Top" Width="78" ItemsSource="{Binding ModeNames}" SelectedItem="{Binding SelectedMode, Mode=TwoWay}"/>
|
||||
<Button x:Name="StopBtn" Content="停止" HorizontalAlignment="Left" Margin="10,44,0,0" VerticalAlignment="Top" Height="28" Width="78" Click="StopBtn_Click"/>
|
||||
<TextBlock HorizontalAlignment="Left" Margin="117,279,0,0" TextWrapping="Wrap" Text="INFO|XXXXXXXXXXXXXXXXXXXXXXXX/nxxxxxxxxxxxxxxxxxxxx" VerticalAlignment="Top" Height="161" Width="180"/>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
108
BetterGenshinImpact/MainWindow.xaml.cs
Normal file
108
BetterGenshinImpact/MainWindow.xaml.cs
Normal file
@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Threading;
|
||||
using BetterGenshinImpact.Extensions;
|
||||
using Vanara.PInvoke;
|
||||
using Vision.WindowCapture;
|
||||
using Vision.WindowCapture.BitBlt;
|
||||
using Vision.WindowCapture.GraphicsCapture;
|
||||
|
||||
namespace BetterGenshinImpact
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private IWindowCapture _capture;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public string[] ModeNames { get; } = WindowCaptureFactory.ModeNames();
|
||||
|
||||
public string SelectedMode { get; set; }
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
{
|
||||
drawingContext.DrawRectangle(Brushes.Transparent, new Pen(Brushes.Red, 2), new Rect(20, 20, 250, 250));
|
||||
|
||||
base.OnRender(drawingContext);
|
||||
}
|
||||
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IntPtr hWnd = FindGenshinImpactHandle();
|
||||
if (hWnd == IntPtr.Zero)
|
||||
{
|
||||
MessageBox.Show("未找到原神窗口");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_capture = WindowCaptureFactory.Create(SelectedMode.ToCaptureMode());
|
||||
_capture.Start(hWnd);
|
||||
|
||||
CompositionTarget.Rendering += Loop;
|
||||
|
||||
}
|
||||
|
||||
private void Loop(object? sender, EventArgs e)
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var bitmap = _capture.Capture();
|
||||
sw.Stop();
|
||||
Debug.WriteLine("截图耗时:" + sw.ElapsedMilliseconds);
|
||||
|
||||
if (bitmap != null)
|
||||
{
|
||||
sw.Reset();
|
||||
sw.Start();
|
||||
ImageResult.Source = bitmap.ToBitmapImage();
|
||||
sw.Stop();
|
||||
Debug.WriteLine("转换耗时:" + sw.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
public IntPtr FindGenshinImpactHandle()
|
||||
{
|
||||
var pros = Process.GetProcessesByName("YuanShen");
|
||||
if (pros.Any())
|
||||
{
|
||||
return pros[0].MainWindowHandle;
|
||||
}
|
||||
|
||||
pros = Process.GetProcessesByName("GenshinImpact");
|
||||
if (pros.Any())
|
||||
{
|
||||
return pros[0].MainWindowHandle;
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
private void StopBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_capture.Stop();
|
||||
}
|
||||
}
|
||||
}
|
35
README.md
Normal file
35
README.md
Normal file
@ -0,0 +1,35 @@
|
||||
更多:[🛠️账号切换](https://github.com/babalae/mihoyo-starter)
|
||||
|
||||
# 更好的原神
|
||||
|
||||
|
||||
|
||||
## 截图
|
||||
|
||||
|
||||
|
||||
## 下载地址
|
||||
|
||||
[📥Github下载(1.0)]()
|
||||
|
||||
[📥蓝奏云下载]() 密码:coco
|
||||
|
||||
|
||||
## 使用方法
|
||||
|
||||
由于图像识别比较吃性能,低配置电脑可能无法正常使用。
|
||||
|
||||
你的系统需要满足以下条件:
|
||||
* Windows 10 或更高版本的64位系统
|
||||
* .Net 7
|
||||
|
||||
|
||||
## 问题反馈
|
||||
|
||||
提 [Issue](https://github.com/babalae/genius-invokation-auto-toy/issues) 或 QQ群[894935931](https://qm.qq.com/cgi-bin/qm/qr?k=u9Ij0HrDVQhvcoFvaiQGv38V3R7ZNY6K&jump_from=webapi&authKey=N++f74HhGHDzFje1dDD6E8vzuf45jmSFaPiVbc3Z7x/nTUWGwZ3UdSPqYQqPfOXK)
|
||||
|
||||
## 投喂
|
||||
|
||||
觉的好用的话,可以支持作者哟ヾ(・ω・`。) 👇
|
||||
* [⚡爱发电](https://afdian.net/@huiyadanli)
|
||||
* [🍚微信赞赏](https://github.com/huiyadanli/huiyadanli/blob/master/DONATE.md)
|
56
Vision.WindowCapture/BitBlt/BitBltCapture.cs
Normal file
56
Vision.WindowCapture/BitBlt/BitBltCapture.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Vanara.Extensions;
|
||||
using Vanara.PInvoke;
|
||||
|
||||
namespace Vision.WindowCapture.BitBlt
|
||||
{
|
||||
public class BitBltCapture : IWindowCapture
|
||||
{
|
||||
private IntPtr _hWnd;
|
||||
public bool IsCapturing { get; private set; }
|
||||
|
||||
public void Start(IntPtr hWnd)
|
||||
{
|
||||
_hWnd = hWnd;
|
||||
IsCapturing = true;
|
||||
}
|
||||
|
||||
public Bitmap? Capture()
|
||||
{
|
||||
if (_hWnd == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
User32.GetWindowRect(_hWnd, 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;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_hWnd = IntPtr.Zero;
|
||||
IsCapturing = false;
|
||||
}
|
||||
}
|
||||
}
|
88
Vision.WindowCapture/GraphicsCapture/GraphicsCapture.cs
Normal file
88
Vision.WindowCapture/GraphicsCapture/GraphicsCapture.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Vision.WindowCapture.GraphicsCapture.Helpers;
|
||||
using Windows.Devices.HumanInterfaceDevice;
|
||||
using Windows.Graphics.Capture;
|
||||
using Windows.Graphics.DirectX;
|
||||
using Windows.Graphics.DirectX.Direct3D11;
|
||||
using SharpDX.Direct3D11;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace Vision.WindowCapture.GraphicsCapture
|
||||
{
|
||||
public class GraphicsCapture : IWindowCapture
|
||||
{
|
||||
private IntPtr _hWnd;
|
||||
|
||||
private Direct3D11CaptureFramePool _captureFramePool;
|
||||
private GraphicsCaptureItem _captureItem;
|
||||
private GraphicsCaptureSession _captureSession;
|
||||
|
||||
public bool IsCapturing { get; private set; }
|
||||
|
||||
public void Start(IntPtr hWnd)
|
||||
{
|
||||
_hWnd = hWnd;
|
||||
IsCapturing = true;
|
||||
|
||||
/*
|
||||
// if use GraphicsCapturePicker, need to set this window handle
|
||||
// new WindowInteropHelper(this).Handle
|
||||
var picker = new GraphicsCapturePicker();
|
||||
picker.SetWindow(hWnd);
|
||||
_captureItem = picker.PickSingleItemAsync().AsTask().Result;
|
||||
*/
|
||||
|
||||
_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.StartCapture();
|
||||
IsCapturing = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How to handle window size changes?
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Bitmap? Capture()
|
||||
{
|
||||
using var frame = _captureFramePool?.TryGetNextFrame();
|
||||
return frame?.ToBitmap();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
// ---------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Graphics.Capture;
|
||||
using WinRT;
|
||||
|
||||
namespace Vision.WindowCapture.GraphicsCapture.Helpers
|
||||
{
|
||||
public static class CaptureHelper
|
||||
{
|
||||
static readonly Guid GraphicsCaptureItemGuid = new Guid("79C3F95B-31F7-4EC2-A464-632EF5D30760");
|
||||
|
||||
[ComImport]
|
||||
[Guid("3E68D4BD-7135-4D10-8018-9FB6D9F33FA1")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComVisible(true)]
|
||||
interface IInitializeWithWindow
|
||||
{
|
||||
void Initialize(
|
||||
IntPtr hwnd);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("3628E81B-3CAC-4C60-B7F4-23CE0E0C3356")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComVisible(true)]
|
||||
interface IGraphicsCaptureItemInterop
|
||||
{
|
||||
IntPtr CreateForWindow(
|
||||
[In] IntPtr window,
|
||||
[In] ref Guid iid);
|
||||
|
||||
IntPtr CreateForMonitor(
|
||||
[In] IntPtr monitor,
|
||||
[In] ref Guid iid);
|
||||
}
|
||||
|
||||
public static void SetWindow(this GraphicsCapturePicker picker, IntPtr hwnd)
|
||||
{
|
||||
var interop = picker.As<IInitializeWithWindow>();
|
||||
interop.Initialize(hwnd);
|
||||
}
|
||||
|
||||
public static GraphicsCaptureItem CreateItemForWindow(IntPtr hwnd)
|
||||
{
|
||||
var factory = WinrtModule.GetActivationFactory("Windows.Graphics.Capture.GraphicsCaptureItem");
|
||||
var interop = factory.AsInterface<IGraphicsCaptureItemInterop>();
|
||||
var itemPointer = interop.CreateForWindow(hwnd, GraphicsCaptureItemGuid);
|
||||
return GraphicsCaptureItem.FromAbi(itemPointer);
|
||||
}
|
||||
|
||||
//public static GraphicsCaptureItem CreateItemForMonitor(IntPtr hmon)
|
||||
//{
|
||||
// var factory = WindowsRuntimeMarshal.GetActivationFactory(typeof(GraphicsCaptureItem));
|
||||
// var interop = (IGraphicsCaptureItemInterop)factory;
|
||||
// var temp = typeof(GraphicsCaptureItem);
|
||||
// var itemPointer = interop.CreateForMonitor(hmon, GraphicsCaptureItemGuid);
|
||||
// var item = Marshal.GetObjectForIUnknown(itemPointer) as GraphicsCaptureItem;
|
||||
// Marshal.Release(itemPointer);
|
||||
|
||||
// return item;
|
||||
//}
|
||||
}
|
||||
}
|
140
Vision.WindowCapture/GraphicsCapture/Helpers/Direct3D11Helper.cs
Normal file
140
Vision.WindowCapture/GraphicsCapture/Helpers/Direct3D11Helper.cs
Normal file
@ -0,0 +1,140 @@
|
||||
// ---------------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Graphics.DirectX.Direct3D11;
|
||||
using WinRT;
|
||||
|
||||
namespace Vision.WindowCapture.GraphicsCapture.Helpers
|
||||
{
|
||||
public static class Direct3D11Helper
|
||||
{
|
||||
static Guid IInspectable = new Guid("AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90");
|
||||
static Guid ID3D11Resource = new Guid("dc8e63f3-d12b-4952-b47b-5e45026a862d");
|
||||
static Guid IDXGIAdapter3 = new Guid("645967A4-1392-4310-A798-8053CE3E93FD");
|
||||
static Guid ID3D11Device = new Guid("db6f6ddb-ac77-4e88-8253-819df9bbf140");
|
||||
static Guid ID3D11Texture2D = new Guid("6f15aaf2-d208-4e89-9ab4-489535d34f9c");
|
||||
|
||||
[ComImport]
|
||||
[Guid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[ComVisible(true)]
|
||||
interface IDirect3DDxgiInterfaceAccess
|
||||
{
|
||||
IntPtr GetInterface([In] ref Guid iid);
|
||||
};
|
||||
|
||||
[DllImport(
|
||||
"d3d11.dll",
|
||||
EntryPoint = "CreateDirect3D11DeviceFromDXGIDevice",
|
||||
SetLastError = true,
|
||||
CharSet = CharSet.Unicode,
|
||||
ExactSpelling = true,
|
||||
CallingConvention = CallingConvention.StdCall
|
||||
)]
|
||||
static extern UInt32 CreateDirect3D11DeviceFromDXGIDevice(IntPtr dxgiDevice, out IntPtr graphicsDevice);
|
||||
|
||||
[DllImport(
|
||||
"d3d11.dll",
|
||||
EntryPoint = "CreateDirect3D11SurfaceFromDXGISurface",
|
||||
SetLastError = true,
|
||||
CharSet = CharSet.Unicode,
|
||||
ExactSpelling = true,
|
||||
CallingConvention = CallingConvention.StdCall
|
||||
)]
|
||||
static extern UInt32 CreateDirect3D11SurfaceFromDXGISurface(IntPtr dxgiSurface, out IntPtr graphicsSurface);
|
||||
|
||||
public static IDirect3DDevice CreateDevice()
|
||||
{
|
||||
return CreateDevice(false);
|
||||
}
|
||||
|
||||
public static IDirect3DDevice CreateDevice(bool useWARP)
|
||||
{
|
||||
var d3dDevice = new SharpDX.Direct3D11.Device(
|
||||
useWARP ? SharpDX.Direct3D.DriverType.Software : SharpDX.Direct3D.DriverType.Hardware,
|
||||
SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport);
|
||||
var device = CreateDirect3DDeviceFromSharpDXDevice(d3dDevice);
|
||||
return device;
|
||||
}
|
||||
|
||||
public static IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(SharpDX.Direct3D11.Device d3dDevice)
|
||||
{
|
||||
IDirect3DDevice device = null;
|
||||
|
||||
// Acquire the DXGI interface for the Direct3D device.
|
||||
using (var dxgiDevice = d3dDevice.QueryInterface<SharpDX.DXGI.Device3>())
|
||||
{
|
||||
// Wrap the native device using a WinRT interop object.
|
||||
uint hr = CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.NativePointer, out IntPtr pUnknown);
|
||||
|
||||
if (hr == 0)
|
||||
{
|
||||
device = MarshalInterface<IDirect3DDevice>.FromAbi(pUnknown);
|
||||
Marshal.Release(pUnknown);
|
||||
}
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
public static IDirect3DSurface CreateDirect3DSurfaceFromSharpDXTexture(SharpDX.Direct3D11.Texture2D texture)
|
||||
{
|
||||
IDirect3DSurface surface = null;
|
||||
|
||||
// Acquire the DXGI interface for the Direct3D surface.
|
||||
using (var dxgiSurface = texture.QueryInterface<SharpDX.DXGI.Surface>())
|
||||
{
|
||||
// Wrap the native device using a WinRT interop object.
|
||||
uint hr = CreateDirect3D11SurfaceFromDXGISurface(dxgiSurface.NativePointer, out IntPtr pUnknown);
|
||||
|
||||
if (hr == 0)
|
||||
{
|
||||
surface = Marshal.GetObjectForIUnknown(pUnknown) as IDirect3DSurface;
|
||||
Marshal.Release(pUnknown);
|
||||
}
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
public static SharpDX.Direct3D11.Device CreateSharpDXDevice(IDirect3DDevice device)
|
||||
{
|
||||
var access = (IDirect3DDxgiInterfaceAccess)device;
|
||||
var d3dPointer = access.GetInterface(ID3D11Device);
|
||||
var d3dDevice = new SharpDX.Direct3D11.Device(d3dPointer);
|
||||
return d3dDevice;
|
||||
}
|
||||
|
||||
public static SharpDX.Direct3D11.Texture2D CreateSharpDXTexture2D(IDirect3DSurface surface)
|
||||
{
|
||||
var access = surface.As<IDirect3DDxgiInterfaceAccess>();
|
||||
var d3dPointer = access.GetInterface(ID3D11Texture2D);
|
||||
var d3dSurface = new SharpDX.Direct3D11.Texture2D(d3dPointer);
|
||||
return d3dSurface;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
using SharpDX;
|
||||
using SharpDX.Direct3D11;
|
||||
using SharpDX.DXGI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Graphics.Capture;
|
||||
using Windows.Graphics.DirectX.Direct3D11;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.Storage.Streams;
|
||||
using Vision.WindowCapture.GraphicsCapture.Helpers;
|
||||
using WinRT;
|
||||
|
||||
namespace Vision.WindowCapture.GraphicsCapture.Helpers
|
||||
{
|
||||
public static class Texture2DExtensions
|
||||
{
|
||||
public static Bitmap? ToBitmap(this Direct3D11CaptureFrame frame)
|
||||
{
|
||||
var texture2dBitmap = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface);
|
||||
|
||||
var d3dDevice = texture2dBitmap.Device;
|
||||
|
||||
// Create texture copy
|
||||
var staging = new Texture2D(d3dDevice, new Texture2DDescription
|
||||
{
|
||||
Width = frame.ContentSize.Width,
|
||||
Height = frame.ContentSize.Height,
|
||||
MipLevels = 1,
|
||||
ArraySize = 1,
|
||||
Format = texture2dBitmap.Description.Format,
|
||||
Usage = ResourceUsage.Staging,
|
||||
SampleDescription = new SampleDescription(1, 0),
|
||||
BindFlags = BindFlags.None,
|
||||
CpuAccessFlags = CpuAccessFlags.Read,
|
||||
OptionFlags = ResourceOptionFlags.None
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
// Copy data
|
||||
d3dDevice.ImmediateContext.CopyResource(texture2dBitmap, staging);
|
||||
|
||||
var dataBox = d3dDevice.ImmediateContext.MapSubresource(staging, 0, 0, MapMode.Read,
|
||||
SharpDX.Direct3D11.MapFlags.None,
|
||||
out DataStream stream);
|
||||
|
||||
var bitmap = new Bitmap(staging.Description.Width, staging.Description.Height, dataBox.RowPitch,
|
||||
PixelFormat.Format32bppArgb, dataBox.DataPointer);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
finally
|
||||
{
|
||||
staging.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
//public static Stream ToBitmapStream(this Direct3D11CaptureFrame frame)
|
||||
//{
|
||||
// var bitmap = frame.ToBitmap();
|
||||
// Stream memoryStream = new MemoryStream();
|
||||
// bitmap.Save(memoryStream, ImageFormat.Png);
|
||||
|
||||
// return memoryStream;
|
||||
//}
|
||||
|
||||
|
||||
//public static async Task<SoftwareBitmap> ToSoftwareBitmapAsync(this Direct3D11CaptureFrame frame)
|
||||
//{
|
||||
// var result = await SoftwareBitmap.CreateCopyFromSurfaceAsync(frame.Surface, BitmapAlphaMode.Premultiplied);
|
||||
|
||||
// return result;
|
||||
//}
|
||||
|
||||
|
||||
//public static async Task<Bitmap> ToBitmapAsync(this SoftwareBitmap sbitmap)
|
||||
//{
|
||||
// using var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
|
||||
// var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
|
||||
// encoder.SetSoftwareBitmap(sbitmap);
|
||||
// await encoder.FlushAsync();
|
||||
// var bmp = new System.Drawing.Bitmap(stream.AsStream());
|
||||
// return bmp;
|
||||
//}
|
||||
|
||||
|
||||
//public static Bitmap Resize(this Bitmap source, int newWidth, int newHeight)
|
||||
//{
|
||||
// float wScale = (float)newWidth / source.Width;
|
||||
// float hScale = (float)newHeight / source.Height;
|
||||
|
||||
// float minScale = Math.Min(wScale, hScale);
|
||||
|
||||
// var nw = (int)(source.Width * minScale);
|
||||
// var nh = (int)(source.Height * minScale);
|
||||
|
||||
|
||||
// var padDimsW = (newWidth - nw) / 2;
|
||||
// var padDimsH = (newHeight - nh) / 2;
|
||||
|
||||
|
||||
// var newBitmap = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb);
|
||||
|
||||
// using var g = Graphics.FromImage(newBitmap);
|
||||
// g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
|
||||
// g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
|
||||
// g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
|
||||
// g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
|
||||
|
||||
// g.DrawImage(source, new Rectangle(padDimsW, padDimsH, nw, nh),
|
||||
// 0, 0, source.Width, source.Height, GraphicsUnit.Pixel);
|
||||
|
||||
// return newBitmap;
|
||||
//}
|
||||
|
||||
|
||||
//public static Bitmap ResizeWithoutPadding(this Bitmap source, int new_width, int new_height)
|
||||
//{
|
||||
// var newBitmap = new Bitmap(new_width, new_height, PixelFormat.Format24bppRgb);
|
||||
|
||||
// using var g = Graphics.FromImage(newBitmap);
|
||||
// g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
|
||||
// g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
|
||||
// g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
|
||||
// g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
|
||||
|
||||
// g.DrawImage(source, new Rectangle(0, 0, new_width, new_height),
|
||||
// 0, 0, source.Width, source.Height, GraphicsUnit.Pixel);
|
||||
|
||||
// return newBitmap;
|
||||
//}
|
||||
}
|
||||
}
|
115
Vision.WindowCapture/GraphicsCapture/Helpers/WinRT.cs
Normal file
115
Vision.WindowCapture/GraphicsCapture/Helpers/WinRT.cs
Normal file
@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using WinRT;
|
||||
|
||||
namespace Vision.WindowCapture.GraphicsCapture.Helpers
|
||||
{
|
||||
[ComImport]
|
||||
[Guid( "3628E81B-3CAC-4C60-B7F4-23CE0E0C3356" )]
|
||||
[InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
|
||||
internal interface IGraphicsCaptureItemInterop
|
||||
{
|
||||
int CreateForWindow( [In] IntPtr window, [In] ref Guid iid, out IntPtr result );
|
||||
|
||||
int CreateForMonitor( [In] IntPtr monitor, [In] ref Guid iid, out IntPtr result );
|
||||
}
|
||||
|
||||
[Guid( "00000035-0000-0000-C000-000000000046" )]
|
||||
internal unsafe struct IActivationFactoryVftbl
|
||||
{
|
||||
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
|
||||
public readonly IInspectable.Vftbl IInspectableVftbl;
|
||||
private readonly void* _ActivateInstance;
|
||||
#pragma warning restore
|
||||
|
||||
public delegate* unmanaged[Stdcall]< IntPtr, IntPtr*, int > ActivateInstance => (delegate* unmanaged[Stdcall]< IntPtr, IntPtr*, int >)_ActivateInstance;
|
||||
}
|
||||
|
||||
internal class Platform
|
||||
{
|
||||
[DllImport( "api-ms-win-core-com-l1-1-0.dll" )]
|
||||
internal static extern int CoDecrementMTAUsage( IntPtr cookie );
|
||||
|
||||
[DllImport( "api-ms-win-core-com-l1-1-0.dll" )]
|
||||
internal static extern unsafe int CoIncrementMTAUsage( IntPtr* cookie );
|
||||
|
||||
[DllImport( "api-ms-win-core-winrt-l1-1-0.dll" )]
|
||||
internal static extern unsafe int RoGetActivationFactory( IntPtr runtimeClassId, ref Guid iid, IntPtr* factory );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https://github.com/zlatanov/windows-screen-recorder
|
||||
/// </summary>
|
||||
internal static class WinrtModule
|
||||
{
|
||||
private static readonly Dictionary<string, ObjectReference<IActivationFactoryVftbl>> Cache = new Dictionary<string, ObjectReference<IActivationFactoryVftbl>>();
|
||||
|
||||
public static ObjectReference<IActivationFactoryVftbl> GetActivationFactory( string runtimeClassId )
|
||||
{
|
||||
lock ( Cache )
|
||||
{
|
||||
if ( Cache.TryGetValue( runtimeClassId, out var factory ) )
|
||||
return factory;
|
||||
|
||||
var m = MarshalString.CreateMarshaler( runtimeClassId );
|
||||
|
||||
try
|
||||
{
|
||||
var instancePtr = GetActivationFactory( MarshalString.GetAbi( m ) );
|
||||
|
||||
factory = ObjectReference<IActivationFactoryVftbl>.Attach( ref instancePtr );
|
||||
Cache.Add( runtimeClassId, factory );
|
||||
|
||||
return factory;
|
||||
}
|
||||
finally
|
||||
{
|
||||
m.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe IntPtr GetActivationFactory( IntPtr hstrRuntimeClassId )
|
||||
{
|
||||
if ( s_cookie == IntPtr.Zero )
|
||||
{
|
||||
lock ( s_lock )
|
||||
{
|
||||
if ( s_cookie == IntPtr.Zero )
|
||||
{
|
||||
IntPtr cookie;
|
||||
Marshal.ThrowExceptionForHR( Platform.CoIncrementMTAUsage( &cookie ) );
|
||||
|
||||
s_cookie = cookie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Guid iid = typeof( IActivationFactoryVftbl ).GUID;
|
||||
IntPtr instancePtr;
|
||||
int hr = Platform.RoGetActivationFactory( hstrRuntimeClassId, ref iid, &instancePtr );
|
||||
|
||||
if ( hr == 0 )
|
||||
return instancePtr;
|
||||
|
||||
throw new Win32Exception( hr );
|
||||
}
|
||||
|
||||
public static bool ResurrectObjectReference( IObjectReference objRef )
|
||||
{
|
||||
var disposedField = objRef.GetType().GetField( "disposed", BindingFlags.NonPublic | BindingFlags.Instance )!;
|
||||
if ( !(bool)disposedField.GetValue( objRef )! )
|
||||
return false;
|
||||
disposedField.SetValue( objRef, false );
|
||||
GC.ReRegisterForFinalize( objRef );
|
||||
return true;
|
||||
}
|
||||
|
||||
private static IntPtr s_cookie;
|
||||
private static readonly object s_lock = new object();
|
||||
}
|
||||
}
|
15
Vision.WindowCapture/IWindowCapture.cs
Normal file
15
Vision.WindowCapture/IWindowCapture.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace Vision.WindowCapture
|
||||
{
|
||||
public interface IWindowCapture
|
||||
{
|
||||
bool IsCapturing { get; }
|
||||
|
||||
void Start(IntPtr hWnd);
|
||||
|
||||
Bitmap? Capture();
|
||||
|
||||
void Stop();
|
||||
}
|
||||
}
|
9
Vision.WindowCapture/README.md
Normal file
9
Vision.WindowCapture/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Vision.WindowCapture
|
||||
|
||||
一个针对窗口截图的库。输入窗口句柄后可以进行捕获,不会捕获覆盖窗体的内容。
|
||||
|
||||
支持以下方案:
|
||||
|
||||
* BitBlt
|
||||
* Windows.Graphics.Capture
|
||||
* DwmSharedSurface (建设中)
|
18
Vision.WindowCapture/Vision.WindowCapture.csproj
Normal file
18
Vision.WindowCapture/Vision.WindowCapture.csproj
Normal file
@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows10.0.22000.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageReference Include="Vanara.PInvoke.Gdi32" Version="3.4.16" />
|
||||
<PackageReference Include="Vanara.PInvoke.User32" Version="3.4.16" />
|
||||
<PackageReference Include="Vanara.Windows.Extensions" Version="3.4.16" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
44
Vision.WindowCapture/WindowCaptureFactory.cs
Normal file
44
Vision.WindowCapture/WindowCaptureFactory.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Vision.WindowCapture
|
||||
{
|
||||
public enum CaptureMode
|
||||
{
|
||||
BitBlt,
|
||||
WindowsGraphicsCapture
|
||||
}
|
||||
|
||||
public static class CaptureModeExtensions
|
||||
{
|
||||
public static CaptureMode ToCaptureMode(this string modeName)
|
||||
{
|
||||
return (CaptureMode) Enum.Parse(typeof(CaptureMode), modeName);
|
||||
}
|
||||
}
|
||||
|
||||
public class WindowCaptureFactory
|
||||
{
|
||||
public static string[] ModeNames()
|
||||
{
|
||||
return Enum.GetNames(typeof(CaptureMode));
|
||||
}
|
||||
|
||||
|
||||
public static IWindowCapture Create(CaptureMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case CaptureMode.BitBlt:
|
||||
return new BitBlt.BitBltCapture();
|
||||
case CaptureMode.WindowsGraphicsCapture:
|
||||
return new GraphicsCapture.GraphicsCapture();
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user