mirror of
https://github.com/babalae/better-genshin-impact
synced 2025-01-09 04:19:47 +08:00
Merge pull request #3 from babalae/user/Lightczx
Win32.Pinvoke instead of Vanara.PInvoke. Refactor Windows.Graphics.Capture
This commit is contained in:
commit
a70e25ef97
20
BetterGenshinImpact.Win32/BetterGenshinImpact.Win32.csproj
Normal file
20
BetterGenshinImpact.Win32/BetterGenshinImpact.Win32.csproj
Normal file
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="NativeMethods.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.46-beta">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
10
BetterGenshinImpact.Win32/NativeMethods.json
Normal file
10
BetterGenshinImpact.Win32/NativeMethods.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/microsoft/CsWin32/main/src/Microsoft.Windows.CsWin32/settings.schema.json",
|
||||
"allowMarshaling": true,
|
||||
"useSafeHandles": false,
|
||||
"emitSingleFile": true,
|
||||
"public": true,
|
||||
"comInterop": {
|
||||
"useIntPtrForComOutPointers": true
|
||||
}
|
||||
}
|
34
BetterGenshinImpact.Win32/NativeMethods.txt
Normal file
34
BetterGenshinImpact.Win32/NativeMethods.txt
Normal file
@ -0,0 +1,34 @@
|
||||
// D3D11
|
||||
CreateDirect3D11DeviceFromDXGIDevice
|
||||
CreateDirect3D11SurfaceFromDXGISurface
|
||||
|
||||
// GDI32
|
||||
BitBlt
|
||||
CreateCompatibleBitmap
|
||||
CreateCompatibleDC
|
||||
DeleteDC
|
||||
GetDeviceCaps
|
||||
SelectObject
|
||||
|
||||
// User32
|
||||
GetClientRect
|
||||
GetDC
|
||||
GetForegroundWindow
|
||||
GetSystemMetrics
|
||||
GetWindowDC
|
||||
GetWindowRect
|
||||
GetWindowThreadProcessId
|
||||
mouse_event
|
||||
PostMessage
|
||||
ReleaseDC
|
||||
|
||||
// COM & WinRT
|
||||
D3D11CreateDevice
|
||||
ID3D11Device3
|
||||
IDirect3DDxgiInterfaceAccess
|
||||
IGraphicsCaptureItemInterop
|
||||
|
||||
// Constants
|
||||
D3D11_SDK_VERSION
|
||||
WM_LBUTTONDOWN
|
||||
WM_LBUTTONUP
|
@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vision.WindowCapture", "Vis
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vision.Recognition", "Vision.Recognition\Vision.Recognition.csproj", "{97A12A37-613B-4BE3-B01B-BF3411503711}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterGenshinImpact.Win32", "BetterGenshinImpact.Win32\BetterGenshinImpact.Win32.csproj", "{75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -27,6 +29,10 @@ Global
|
||||
{97A12A37-613B-4BE3-B01B-BF3411503711}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{97A12A37-613B-4BE3-B01B-BF3411503711}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{97A12A37-613B-4BE3-B01B-BF3411503711}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{75F4541B-9624-4AFB-BAEA-3EAFD3300EE1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -1,17 +1,11 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Serilog;
|
||||
using static Vanara.PInvoke.Kernel32;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenCvSharp;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using Vision.Recognition;
|
||||
using WinRT;
|
||||
|
||||
namespace BetterGenshinImpact
|
||||
{
|
||||
|
@ -10,8 +10,10 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageReference Include="Config.Net" Version="5.1.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.46-beta">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
<PackageReference Include="MouseKeyHook" Version="5.7.1" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="7.0.0" />
|
||||
|
@ -1,29 +1,24 @@
|
||||
using BetterGenshinImpact.GameTask.AutoSkip.Assets;
|
||||
using BetterGenshinImpact.GameTask.AutoFishing.Assets;
|
||||
using BetterGenshinImpact.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenCvSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using BetterGenshinImpact.Core.Config;
|
||||
using BetterGenshinImpact.GameTask.AutoFishing.Assets;
|
||||
using BetterGenshinImpact.Utils;
|
||||
using Vision.Recognition;
|
||||
using Vision.Recognition.Helper.OpenCv;
|
||||
using Vision.Recognition.Helper.Simulator;
|
||||
using Vision.Recognition.Task;
|
||||
using WindowsInput;
|
||||
using static Vanara.PInvoke.User32;
|
||||
using Point = OpenCvSharp.Point;
|
||||
using Serilog.Core;
|
||||
using Vision.Recognition.Helper.OCR;
|
||||
using Vision.Recognition.Helper.OpenCv;
|
||||
using Vision.Recognition.Task;
|
||||
using Windows.Win32.UI.Input.KeyboardAndMouse;
|
||||
using WindowsInput;
|
||||
|
||||
namespace BetterGenshinImpact.GameTask.AutoFishing
|
||||
{
|
||||
public class AutoFishingTrigger : ITaskTrigger
|
||||
{
|
||||
private readonly ILogger<AutoFishingTrigger> _logger = App.GetLogger<AutoFishingTrigger>();
|
||||
private IOcrService _ocrService = OcrFactory.Create(OcrEngineType.WinRT);
|
||||
private readonly IOcrService _ocrService = OcrFactory.Create(OcrEngineType.WinRT);
|
||||
|
||||
public string Name => "自动钓鱼";
|
||||
public bool IsEnabled { get; set; }
|
||||
@ -239,7 +234,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
|
||||
|
||||
private int _noRectsCount = 0;
|
||||
private Rect _cur, _left, _right;
|
||||
private MOUSEEVENTF _prevMouseEvent = 0x0;
|
||||
private MOUSE_EVENT_FLAGS _prevMouseEvent = 0x0;
|
||||
private bool _findFishBoxTips;
|
||||
|
||||
|
||||
@ -285,21 +280,21 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
|
||||
|
||||
if (_cur.X < _left.X)
|
||||
{
|
||||
if (_prevMouseEvent != MOUSEEVENTF.MOUSEEVENTF_LEFTDOWN)
|
||||
if (_prevMouseEvent != MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTDOWN)
|
||||
{
|
||||
simulator.Mouse.LeftButtonDown();
|
||||
//Simulator.PostMessage(TaskContext.Instance().GameHandle).LeftButtonDown();
|
||||
_prevMouseEvent = MOUSEEVENTF.MOUSEEVENTF_LEFTDOWN;
|
||||
_prevMouseEvent = MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTDOWN;
|
||||
//Debug.WriteLine("进度不到 左键按下");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_prevMouseEvent == MOUSEEVENTF.MOUSEEVENTF_LEFTDOWN)
|
||||
if (_prevMouseEvent == MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTDOWN)
|
||||
{
|
||||
simulator.Mouse.LeftButtonUp();
|
||||
//Simulator.PostMessage(TaskContext.Instance().GameHandle).LeftButtonUp();
|
||||
_prevMouseEvent = MOUSEEVENTF.MOUSEEVENTF_LEFTUP;
|
||||
_prevMouseEvent = MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTUP;
|
||||
//Debug.WriteLine("进度超出 左键松开");
|
||||
}
|
||||
}
|
||||
@ -314,21 +309,21 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
|
||||
|
||||
if (_right.X + _right.Width - (_cur.X + _cur.Width) <= _cur.X - _left.X)
|
||||
{
|
||||
if (_prevMouseEvent == MOUSEEVENTF.MOUSEEVENTF_LEFTDOWN)
|
||||
if (_prevMouseEvent == MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTDOWN)
|
||||
{
|
||||
simulator.Mouse.LeftButtonUp();
|
||||
//Simulator.PostMessage(TaskContext.Instance().GameHandle).LeftButtonUp();
|
||||
_prevMouseEvent = MOUSEEVENTF.MOUSEEVENTF_LEFTUP;
|
||||
_prevMouseEvent = MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTUP;
|
||||
//Debug.WriteLine("进入框内中间 左键松开");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_prevMouseEvent != MOUSEEVENTF.MOUSEEVENTF_LEFTDOWN)
|
||||
if (_prevMouseEvent != MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTDOWN)
|
||||
{
|
||||
simulator.Mouse.LeftButtonDown();
|
||||
//Simulator.PostMessage(TaskContext.Instance().GameHandle).LeftButtonDown();
|
||||
_prevMouseEvent = MOUSEEVENTF.MOUSEEVENTF_LEFTDOWN;
|
||||
_prevMouseEvent = MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTDOWN;
|
||||
//Debug.WriteLine("未到框内中间 左键按下");
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,14 @@
|
||||
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.Xml.Linq;
|
||||
using Vanara.PInvoke;
|
||||
using Windows.Win32.Foundation;
|
||||
using static Windows.Win32.PInvoke;
|
||||
|
||||
namespace BetterGenshinImpact.GameTask
|
||||
{
|
||||
public class SystemControl
|
||||
{
|
||||
public static IntPtr FindGenshinImpactHandle()
|
||||
public static nint FindGenshinImpactHandle()
|
||||
{
|
||||
return FindHandleByProcessName("YuanShen", "GenshinImpact", "Genshin Impact Cloud Game");
|
||||
}
|
||||
@ -23,7 +19,7 @@ namespace BetterGenshinImpact.GameTask
|
||||
return name is "YuanShen" or "GenshinImpact" or "Genshin Impact Cloud Game";
|
||||
}
|
||||
|
||||
public static IntPtr FindHandleByProcessName(params string[] names)
|
||||
public static nint FindHandleByProcessName(params string[] names)
|
||||
{
|
||||
foreach (var name in names)
|
||||
{
|
||||
@ -34,32 +30,34 @@ namespace BetterGenshinImpact.GameTask
|
||||
}
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static string? GetActiveProcessName()
|
||||
public static unsafe string? GetActiveProcessName()
|
||||
{
|
||||
try
|
||||
{
|
||||
var hWnd = User32.GetForegroundWindow();
|
||||
User32.GetWindowThreadProcessId(hWnd, out var pid);
|
||||
var hWnd = GetForegroundWindow();
|
||||
uint pid = default;
|
||||
_ = GetWindowThreadProcessId(hWnd, &pid);
|
||||
var p = Process.GetProcessById((int)pid);
|
||||
return p.ProcessName;
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取窗口位置
|
||||
/// </summary>
|
||||
/// <param name="hWnd"></param>
|
||||
/// <returns></returns>
|
||||
public static RECT GetWindowRect(IntPtr hWnd)
|
||||
public static RECT GetWindowRect(HWND hWnd)
|
||||
{
|
||||
User32.GetWindowRect(hWnd, out var windowRect);
|
||||
Windows.Win32.PInvoke.GetWindowRect(hWnd, out var windowRect);
|
||||
return windowRect;
|
||||
}
|
||||
|
||||
@ -68,9 +66,9 @@ namespace BetterGenshinImpact.GameTask
|
||||
/// </summary>
|
||||
/// <param name="hWnd"></param>
|
||||
/// <returns></returns>
|
||||
public static RECT GetGameScreenRect(IntPtr hWnd)
|
||||
public static RECT GetGameScreenRect(HWND hWnd)
|
||||
{
|
||||
User32.GetClientRect(hWnd, out var clientRect);
|
||||
Windows.Win32.PInvoke.GetWindowRect(hWnd, out var clientRect);
|
||||
return clientRect;
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Timers;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using Vision.Recognition.Task;
|
||||
using Vision.WindowCapture;
|
||||
using Windows.Win32.Foundation;
|
||||
|
||||
namespace BetterGenshinImpact.GameTask
|
||||
{
|
||||
@ -34,7 +36,7 @@ namespace BetterGenshinImpact.GameTask
|
||||
|
||||
public void Start(CaptureMode mode, int frameRate = 30)
|
||||
{
|
||||
IntPtr hWnd = SystemControl.FindGenshinImpactHandle();
|
||||
HWND hWnd = (HWND)SystemControl.FindGenshinImpactHandle();
|
||||
if (hWnd == IntPtr.Zero)
|
||||
{
|
||||
MessageBox.Show("未找到原神窗口");
|
||||
@ -46,7 +48,7 @@ namespace BetterGenshinImpact.GameTask
|
||||
_frameRate = frameRate;
|
||||
|
||||
_capture = WindowCaptureFactory.Create(mode);
|
||||
_capture.Start(hWnd);
|
||||
_capture.Start((Windows.Win32.Foundation.HWND)hWnd);
|
||||
|
||||
_frameIndex = 0;
|
||||
_timer.Interval = Convert.ToInt32(1000d / frameRate);
|
||||
@ -117,6 +119,10 @@ namespace BetterGenshinImpact.GameTask
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex.StackTrace);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (hasLock)
|
||||
|
@ -1,11 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BetterGenshinImpact.GameTask;
|
||||
using BetterGenshinImpact.GameTask;
|
||||
using OpenCvSharp;
|
||||
using System;
|
||||
using Vision.Recognition.Helper.Simulator;
|
||||
using Windows.Win32.Foundation;
|
||||
|
||||
namespace BetterGenshinImpact.Utils.Extensions
|
||||
{
|
||||
@ -18,7 +15,7 @@ namespace BetterGenshinImpact.Utils.Extensions
|
||||
return point;
|
||||
}
|
||||
|
||||
var rc = SystemControl.GetWindowRect(TaskContext.Instance().GameHandle);
|
||||
var rc = SystemControl.GetWindowRect((HWND)TaskContext.Instance().GameHandle);
|
||||
return new Point(rc.X + point.X, rc.Y + point.Y);
|
||||
}
|
||||
|
||||
@ -36,7 +33,7 @@ namespace BetterGenshinImpact.Utils.Extensions
|
||||
return point;
|
||||
}
|
||||
|
||||
var rc = SystemControl.GetWindowRect(TaskContext.Instance().GameHandle);
|
||||
var rc = SystemControl.GetWindowRect((HWND)TaskContext.Instance().GameHandle);
|
||||
return new Point(rc.X + point.X + offsetX, rc.Y + point.Y + offsetY);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Windows.Win32.Foundation;
|
||||
using Vision.WindowCapture;
|
||||
|
||||
namespace BetterGenshinImpact.View.Test
|
||||
@ -28,7 +29,7 @@ namespace BetterGenshinImpact.View.Test
|
||||
|
||||
|
||||
_capture = WindowCaptureFactory.Create(captureMode);
|
||||
_capture.Start(hWnd);
|
||||
_capture.Start((HWND)hWnd);
|
||||
|
||||
CompositionTarget.Rendering += Loop;
|
||||
}
|
||||
|
@ -1,21 +1,17 @@
|
||||
using BetterGenshinImpact.GameTask;
|
||||
using BetterGenshinImpact.View.Test;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using BetterGenshinImpact.Core.Config;
|
||||
using BetterGenshinImpact.View.Test;
|
||||
using OpenCvSharp;
|
||||
using Vanara.PInvoke;
|
||||
using Vision.Recognition;
|
||||
using Vision.Recognition.Helper.Simulator;
|
||||
using Vision.WindowCapture;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
using static Windows.Win32.PInvoke;
|
||||
|
||||
namespace BetterGenshinImpact.ViewModel
|
||||
{
|
||||
@ -79,7 +75,8 @@ namespace BetterGenshinImpact.ViewModel
|
||||
[RelayCommand]
|
||||
private void OnStopTrigger()
|
||||
{
|
||||
if (SelectedMode == null)
|
||||
HWND hWnd = (HWND)SystemControl.FindGenshinImpactHandle();
|
||||
if (hWnd == HWND.Null)
|
||||
{
|
||||
MessageBox.Show("请选择捕获方式");
|
||||
return;
|
||||
@ -96,7 +93,7 @@ namespace BetterGenshinImpact.ViewModel
|
||||
// return;
|
||||
// }
|
||||
|
||||
// User32.GetWindowRect(hWnd, out var rect);
|
||||
// GetWindowRect(hWnd, out var rect);
|
||||
// //var x = rect.X;
|
||||
// //var y = rect.Y;
|
||||
// //var w = rect.Width;
|
||||
@ -126,14 +123,14 @@ namespace BetterGenshinImpact.ViewModel
|
||||
|
||||
private void TestMask()
|
||||
{
|
||||
var hWnd = SystemControl.FindGenshinImpactHandle();
|
||||
if (hWnd == IntPtr.Zero)
|
||||
HWND hWnd = (HWND)SystemControl.FindGenshinImpactHandle();
|
||||
if (hWnd == HWND.Null)
|
||||
{
|
||||
MessageBox.Show("未找到原神窗口");
|
||||
return;
|
||||
}
|
||||
|
||||
User32.GetWindowRect(hWnd, out var rect);
|
||||
GetWindowRect(hWnd, out var rect);
|
||||
var x = rect.X;
|
||||
var y = rect.Y;
|
||||
var w = rect.Width;
|
||||
|
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Vision.Recognition.Controls.Adorners;
|
||||
|
||||
public class DoubleFormatConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
double d = (double)value;
|
||||
return Math.Round(d);
|
||||
}
|
||||
|
||||
public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
@ -3,40 +3,43 @@ using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Vision.Recognition.Controls.Adorners
|
||||
namespace Vision.Recognition.Controls.Adorners;
|
||||
|
||||
public class ResizeRotateAdorner : Adorner
|
||||
{
|
||||
public class ResizeRotateAdorner : Adorner
|
||||
private readonly VisualCollection visuals;
|
||||
private readonly ResizeRotateChrome chrome;
|
||||
|
||||
protected override int VisualChildrenCount
|
||||
{
|
||||
private VisualCollection visuals;
|
||||
private ResizeRotateChrome chrome;
|
||||
|
||||
protected override int VisualChildrenCount
|
||||
get
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.visuals.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public ResizeRotateAdorner(ContentControl designerItem)
|
||||
: base(designerItem)
|
||||
{
|
||||
SnapsToDevicePixels = true;
|
||||
this.chrome = new ResizeRotateChrome();
|
||||
this.chrome.DataContext = designerItem;
|
||||
this.visuals = new VisualCollection(this);
|
||||
this.visuals.Add(this.chrome);
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size arrangeBounds)
|
||||
{
|
||||
this.chrome.Arrange(new Rect(arrangeBounds));
|
||||
return arrangeBounds;
|
||||
}
|
||||
|
||||
protected override Visual GetVisualChild(int index)
|
||||
{
|
||||
return this.visuals[index];
|
||||
return visuals.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public ResizeRotateAdorner(ContentControl? designerItem)
|
||||
: base(designerItem)
|
||||
{
|
||||
SnapsToDevicePixels = true;
|
||||
chrome = new ResizeRotateChrome
|
||||
{
|
||||
DataContext = designerItem
|
||||
};
|
||||
visuals = new VisualCollection(this)
|
||||
{
|
||||
chrome
|
||||
};
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size arrangeBounds)
|
||||
{
|
||||
chrome.Arrange(new Rect(arrangeBounds));
|
||||
return arrangeBounds;
|
||||
}
|
||||
|
||||
protected override Visual GetVisualChild(int index)
|
||||
{
|
||||
return visuals[index];
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Vision.Recognition.Controls.Adorners
|
||||
namespace Vision.Recognition.Controls.Adorners;
|
||||
|
||||
public class ResizeRotateChrome : Control
|
||||
{
|
||||
public class ResizeRotateChrome : Control
|
||||
static ResizeRotateChrome()
|
||||
{
|
||||
static ResizeRotateChrome()
|
||||
{
|
||||
FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(ResizeRotateChrome), new FrameworkPropertyMetadata(typeof(ResizeRotateChrome)));
|
||||
}
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(ResizeRotateChrome), new FrameworkPropertyMetadata(typeof(ResizeRotateChrome)));
|
||||
}
|
||||
}
|
||||
|
@ -3,42 +3,45 @@ using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Vision.Recognition.Controls.Adorners
|
||||
namespace Vision.Recognition.Controls.Adorners;
|
||||
|
||||
public class SizeAdorner : Adorner
|
||||
{
|
||||
public class SizeAdorner : Adorner
|
||||
private readonly SizeChrome chrome;
|
||||
private readonly VisualCollection visuals;
|
||||
private readonly ContentControl designerItem;
|
||||
|
||||
protected override int VisualChildrenCount
|
||||
{
|
||||
private SizeChrome chrome;
|
||||
private VisualCollection visuals;
|
||||
private ContentControl designerItem;
|
||||
|
||||
protected override int VisualChildrenCount
|
||||
get
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.visuals.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public SizeAdorner(ContentControl designerItem)
|
||||
: base(designerItem)
|
||||
{
|
||||
this.SnapsToDevicePixels = true;
|
||||
this.designerItem = designerItem;
|
||||
this.chrome = new SizeChrome();
|
||||
this.chrome.DataContext = designerItem;
|
||||
this.visuals = new VisualCollection(this);
|
||||
this.visuals.Add(this.chrome);
|
||||
}
|
||||
|
||||
protected override Visual GetVisualChild(int index)
|
||||
{
|
||||
return this.visuals[index];
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size arrangeBounds)
|
||||
{
|
||||
this.chrome.Arrange(new Rect(new Point(0.0, 0.0), arrangeBounds));
|
||||
return arrangeBounds;
|
||||
return visuals.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public SizeAdorner(ContentControl designerItem)
|
||||
: base(designerItem)
|
||||
{
|
||||
SnapsToDevicePixels = true;
|
||||
this.designerItem = designerItem;
|
||||
chrome = new SizeChrome
|
||||
{
|
||||
DataContext = designerItem
|
||||
};
|
||||
visuals = new VisualCollection(this)
|
||||
{
|
||||
chrome
|
||||
};
|
||||
}
|
||||
|
||||
protected override Visual GetVisualChild(int index)
|
||||
{
|
||||
return visuals[index];
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size arrangeBounds)
|
||||
{
|
||||
chrome.Arrange(new Rect(default, arrangeBounds));
|
||||
return arrangeBounds;
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,12 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Vision.Recognition.Controls.Adorners
|
||||
namespace Vision.Recognition.Controls.Adorners;
|
||||
|
||||
public class SizeChrome : Control
|
||||
{
|
||||
public class SizeChrome : Control
|
||||
static SizeChrome()
|
||||
{
|
||||
static SizeChrome()
|
||||
{
|
||||
FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(SizeChrome), new FrameworkPropertyMetadata(typeof(SizeChrome)));
|
||||
}
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(SizeChrome), new FrameworkPropertyMetadata(typeof(SizeChrome)));
|
||||
}
|
||||
|
||||
public class DoubleFormatConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
double d = (double)value;
|
||||
return Math.Round(d);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
namespace Vision.Recognition.Controls;
|
||||
|
||||
namespace Vision.Recognition.Controls
|
||||
public class AreaSettingsControlBuilder
|
||||
{
|
||||
public class AreaSettingsControlBuilder
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -1,98 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Vision.Recognition.Controls.Adorners;
|
||||
|
||||
namespace Vision.Recognition.Controls
|
||||
namespace Vision.Recognition.Controls;
|
||||
|
||||
public class DesignerItemDecorator : Control
|
||||
{
|
||||
public class DesignerItemDecorator : Control
|
||||
private Adorner? adorner;
|
||||
|
||||
public bool ShowDecorator
|
||||
{
|
||||
private Adorner adorner;
|
||||
get { return (bool)GetValue(ShowDecoratorProperty); }
|
||||
set { SetValue(ShowDecoratorProperty, value); }
|
||||
}
|
||||
|
||||
public bool ShowDecorator
|
||||
public static readonly DependencyProperty ShowDecoratorProperty =
|
||||
DependencyProperty.Register(nameof(ShowDecorator), typeof(bool), typeof(DesignerItemDecorator),
|
||||
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnShowDecoratorChanged)));
|
||||
|
||||
public DesignerItemDecorator()
|
||||
{
|
||||
Unloaded += OnDesignerItemDecoratorUnloaded;
|
||||
}
|
||||
|
||||
private void HideAdorner()
|
||||
{
|
||||
if (adorner is not null)
|
||||
{
|
||||
get { return (bool)GetValue(ShowDecoratorProperty); }
|
||||
set { SetValue(ShowDecoratorProperty, value); }
|
||||
adorner.Visibility = Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShowDecoratorProperty =
|
||||
DependencyProperty.Register("ShowDecorator", typeof(bool), typeof(DesignerItemDecorator),
|
||||
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(ShowDecoratorProperty_Changed)));
|
||||
|
||||
public DesignerItemDecorator()
|
||||
private void ShowAdorner()
|
||||
{
|
||||
if (adorner is null)
|
||||
{
|
||||
Unloaded += new RoutedEventHandler(this.DesignerItemDecorator_Unloaded);
|
||||
}
|
||||
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
||||
|
||||
private void HideAdorner()
|
||||
{
|
||||
if (this.adorner != null)
|
||||
if (adornerLayer is not null)
|
||||
{
|
||||
this.adorner.Visibility = Visibility.Hidden;
|
||||
ContentControl? designerItem = DataContext as ContentControl;
|
||||
// Canvas? canvas = VisualTreeHelper.GetParent(designerItem) as Canvas;
|
||||
adorner = new ResizeRotateAdorner(designerItem);
|
||||
adornerLayer.Add(adorner);
|
||||
|
||||
adorner.Visibility = ShowDecorator ? Visibility.Visible : Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowAdorner()
|
||||
else
|
||||
{
|
||||
if (this.adorner == null)
|
||||
{
|
||||
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
||||
|
||||
if (adornerLayer != null)
|
||||
{
|
||||
ContentControl designerItem = this.DataContext as ContentControl;
|
||||
Canvas canvas = VisualTreeHelper.GetParent(designerItem) as Canvas;
|
||||
this.adorner = new ResizeRotateAdorner(designerItem);
|
||||
adornerLayer.Add(this.adorner);
|
||||
|
||||
if (this.ShowDecorator)
|
||||
{
|
||||
this.adorner.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.adorner.Visibility = Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.adorner.Visibility = Visibility.Visible;
|
||||
}
|
||||
adorner.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
private void DesignerItemDecorator_Unloaded(object sender, RoutedEventArgs e)
|
||||
private void OnDesignerItemDecoratorUnloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (adorner is not null)
|
||||
{
|
||||
if (this.adorner != null)
|
||||
{
|
||||
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
||||
if (adornerLayer != null)
|
||||
{
|
||||
adornerLayer.Remove(this.adorner);
|
||||
}
|
||||
|
||||
this.adorner = null;
|
||||
}
|
||||
AdornerLayer.GetAdornerLayer(this)?.Remove(adorner);
|
||||
adorner = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowDecoratorProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
private static void OnShowDecoratorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
DesignerItemDecorator decorator = (DesignerItemDecorator)d;
|
||||
bool showDecorator = (bool)e.NewValue;
|
||||
|
||||
if (showDecorator)
|
||||
{
|
||||
DesignerItemDecorator decorator = (DesignerItemDecorator)d;
|
||||
bool showDecorator = (bool)e.NewValue;
|
||||
|
||||
if (showDecorator)
|
||||
{
|
||||
decorator.ShowAdorner();
|
||||
}
|
||||
else
|
||||
{
|
||||
decorator.HideAdorner();
|
||||
}
|
||||
decorator.ShowAdorner();
|
||||
}
|
||||
else
|
||||
{
|
||||
decorator.HideAdorner();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,43 +3,42 @@ using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Vision.Recognition.Controls
|
||||
namespace Vision.Recognition.Controls;
|
||||
|
||||
public class MoveThumb : Thumb
|
||||
{
|
||||
public class MoveThumb : Thumb
|
||||
private RotateTransform? rotateTransform;
|
||||
private ContentControl? designerItem;
|
||||
|
||||
public MoveThumb()
|
||||
{
|
||||
private RotateTransform rotateTransform;
|
||||
private ContentControl designerItem;
|
||||
DragStarted += OnMoveThumbDragStarted;
|
||||
DragDelta += OnMoveThumbDragDelta;
|
||||
}
|
||||
|
||||
public MoveThumb()
|
||||
private void OnMoveThumbDragStarted(object sender, DragStartedEventArgs e)
|
||||
{
|
||||
designerItem = DataContext as ContentControl;
|
||||
|
||||
if (designerItem != null)
|
||||
{
|
||||
DragStarted += new DragStartedEventHandler(this.MoveThumb_DragStarted);
|
||||
DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
|
||||
rotateTransform = designerItem.RenderTransform as RotateTransform;
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveThumb_DragStarted(object sender, DragStartedEventArgs e)
|
||||
private void OnMoveThumbDragDelta(object sender, DragDeltaEventArgs e)
|
||||
{
|
||||
if (designerItem is not null)
|
||||
{
|
||||
this.designerItem = DataContext as ContentControl;
|
||||
Point dragDelta = new(e.HorizontalChange, e.VerticalChange);
|
||||
|
||||
if (this.designerItem != null)
|
||||
if (rotateTransform is not null)
|
||||
{
|
||||
this.rotateTransform = this.designerItem.RenderTransform as RotateTransform;
|
||||
dragDelta = rotateTransform.Transform(dragDelta);
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
|
||||
{
|
||||
if (this.designerItem != null)
|
||||
{
|
||||
Point dragDelta = new Point(e.HorizontalChange, e.VerticalChange);
|
||||
|
||||
if (this.rotateTransform != null)
|
||||
{
|
||||
dragDelta = this.rotateTransform.Transform(dragDelta);
|
||||
}
|
||||
|
||||
Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + dragDelta.X);
|
||||
Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + dragDelta.Y);
|
||||
}
|
||||
Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) + dragDelta.X);
|
||||
Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) + dragDelta.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,114 +7,108 @@ using System.Windows.Media;
|
||||
using System.Collections.Generic;
|
||||
using Vision.Recognition.Controls.Adorners;
|
||||
|
||||
namespace Vision.Recognition.Controls
|
||||
namespace Vision.Recognition.Controls;
|
||||
|
||||
public class ResizeThumb : Thumb
|
||||
{
|
||||
public class ResizeThumb : Thumb
|
||||
private RotateTransform? rotateTransform;
|
||||
private double angle;
|
||||
private Adorner? adorner;
|
||||
private Point transformOrigin;
|
||||
private ContentControl? designerItem;
|
||||
private Canvas? canvas;
|
||||
|
||||
public ResizeThumb()
|
||||
{
|
||||
private RotateTransform rotateTransform;
|
||||
private double angle;
|
||||
private Adorner adorner;
|
||||
private Point transformOrigin;
|
||||
private ContentControl designerItem;
|
||||
private Canvas canvas;
|
||||
DragStarted += OnResizeThumbDragStarted;
|
||||
DragDelta += OnResizeThumbDragDelta;
|
||||
DragCompleted += OnResizeThumbDragCompleted;
|
||||
}
|
||||
|
||||
public ResizeThumb()
|
||||
private void OnResizeThumbDragStarted(object sender, DragStartedEventArgs e)
|
||||
{
|
||||
designerItem = DataContext as ContentControl;
|
||||
|
||||
if (designerItem is not null)
|
||||
{
|
||||
DragStarted += new DragStartedEventHandler(this.ResizeThumb_DragStarted);
|
||||
DragDelta += new DragDeltaEventHandler(this.ResizeThumb_DragDelta);
|
||||
DragCompleted += new DragCompletedEventHandler(this.ResizeThumb_DragCompleted);
|
||||
}
|
||||
canvas = VisualTreeHelper.GetParent(designerItem) as Canvas;
|
||||
|
||||
private void ResizeThumb_DragStarted(object sender, DragStartedEventArgs e)
|
||||
{
|
||||
this.designerItem = this.DataContext as ContentControl;
|
||||
|
||||
if (this.designerItem != null)
|
||||
if (canvas is not null)
|
||||
{
|
||||
this.canvas = VisualTreeHelper.GetParent(this.designerItem) as Canvas;
|
||||
transformOrigin = designerItem.RenderTransformOrigin;
|
||||
|
||||
if (this.canvas != null)
|
||||
rotateTransform = designerItem.RenderTransform as RotateTransform;
|
||||
if (rotateTransform is not null)
|
||||
{
|
||||
this.transformOrigin = this.designerItem.RenderTransformOrigin;
|
||||
|
||||
this.rotateTransform = this.designerItem.RenderTransform as RotateTransform;
|
||||
if (this.rotateTransform != null)
|
||||
{
|
||||
this.angle = this.rotateTransform.Angle * Math.PI / 180.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.angle = 0.0d;
|
||||
}
|
||||
|
||||
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.canvas);
|
||||
if (adornerLayer != null)
|
||||
{
|
||||
this.adorner = new SizeAdorner(this.designerItem);
|
||||
adornerLayer.Add(this.adorner);
|
||||
}
|
||||
angle = rotateTransform.Angle * Math.PI / 180.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
|
||||
{
|
||||
if (this.designerItem != null)
|
||||
{
|
||||
double deltaVertical, deltaHorizontal;
|
||||
|
||||
switch (VerticalAlignment)
|
||||
else
|
||||
{
|
||||
case System.Windows.VerticalAlignment.Bottom:
|
||||
deltaVertical = Math.Min(-e.VerticalChange, this.designerItem.ActualHeight - this.designerItem.MinHeight);
|
||||
Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + (this.transformOrigin.Y * deltaVertical * (1 - Math.Cos(-this.angle))));
|
||||
Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) - deltaVertical * this.transformOrigin.Y * Math.Sin(-this.angle));
|
||||
this.designerItem.Height -= deltaVertical;
|
||||
break;
|
||||
case System.Windows.VerticalAlignment.Top:
|
||||
deltaVertical = Math.Min(e.VerticalChange, this.designerItem.ActualHeight - this.designerItem.MinHeight);
|
||||
Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + deltaVertical * Math.Cos(-this.angle) + (this.transformOrigin.Y * deltaVertical * (1 - Math.Cos(-this.angle))));
|
||||
Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + deltaVertical * Math.Sin(-this.angle) - (this.transformOrigin.Y * deltaVertical * Math.Sin(-this.angle)));
|
||||
this.designerItem.Height -= deltaVertical;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
angle = 0.0d;
|
||||
}
|
||||
|
||||
switch (HorizontalAlignment)
|
||||
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(canvas);
|
||||
if (adornerLayer is not null)
|
||||
{
|
||||
case System.Windows.HorizontalAlignment.Left:
|
||||
deltaHorizontal = Math.Min(e.HorizontalChange, this.designerItem.ActualWidth - this.designerItem.MinWidth);
|
||||
Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + deltaHorizontal * Math.Sin(this.angle) - this.transformOrigin.X * deltaHorizontal * Math.Sin(this.angle));
|
||||
Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + deltaHorizontal * Math.Cos(this.angle) + (this.transformOrigin.X * deltaHorizontal * (1 - Math.Cos(this.angle))));
|
||||
this.designerItem.Width -= deltaHorizontal;
|
||||
break;
|
||||
case System.Windows.HorizontalAlignment.Right:
|
||||
deltaHorizontal = Math.Min(-e.HorizontalChange, this.designerItem.ActualWidth - this.designerItem.MinWidth);
|
||||
Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) - this.transformOrigin.X * deltaHorizontal * Math.Sin(this.angle));
|
||||
Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + (deltaHorizontal * this.transformOrigin.X * (1 - Math.Cos(this.angle))));
|
||||
this.designerItem.Width -= deltaHorizontal;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
adorner = new SizeAdorner(designerItem);
|
||||
adornerLayer.Add(adorner);
|
||||
}
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void ResizeThumb_DragCompleted(object sender, DragCompletedEventArgs e)
|
||||
{
|
||||
if (this.adorner != null)
|
||||
{
|
||||
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.canvas);
|
||||
if (adornerLayer != null)
|
||||
{
|
||||
adornerLayer.Remove(this.adorner);
|
||||
}
|
||||
|
||||
this.adorner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnResizeThumbDragDelta(object sender, DragDeltaEventArgs e)
|
||||
{
|
||||
if (designerItem is not null)
|
||||
{
|
||||
double deltaVertical, deltaHorizontal;
|
||||
|
||||
switch (VerticalAlignment)
|
||||
{
|
||||
case VerticalAlignment.Bottom:
|
||||
deltaVertical = Math.Min(-e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
|
||||
Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) + (transformOrigin.Y * deltaVertical * (1 - Math.Cos(-angle))));
|
||||
Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) - deltaVertical * transformOrigin.Y * Math.Sin(-angle));
|
||||
designerItem.Height -= deltaVertical;
|
||||
break;
|
||||
case VerticalAlignment.Top:
|
||||
deltaVertical = Math.Min(e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
|
||||
Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) + deltaVertical * Math.Cos(-angle) + (transformOrigin.Y * deltaVertical * (1 - Math.Cos(-angle))));
|
||||
Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) + deltaVertical * Math.Sin(-angle) - (transformOrigin.Y * deltaVertical * Math.Sin(-angle)));
|
||||
designerItem.Height -= deltaVertical;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (HorizontalAlignment)
|
||||
{
|
||||
case HorizontalAlignment.Left:
|
||||
deltaHorizontal = Math.Min(e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
|
||||
Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) + deltaHorizontal * Math.Sin(angle) - transformOrigin.X * deltaHorizontal * Math.Sin(angle));
|
||||
Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) + deltaHorizontal * Math.Cos(angle) + (transformOrigin.X * deltaHorizontal * (1 - Math.Cos(angle))));
|
||||
designerItem.Width -= deltaHorizontal;
|
||||
break;
|
||||
case HorizontalAlignment.Right:
|
||||
deltaHorizontal = Math.Min(-e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
|
||||
Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) - transformOrigin.X * deltaHorizontal * Math.Sin(angle));
|
||||
Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) + (deltaHorizontal * transformOrigin.X * (1 - Math.Cos(angle))));
|
||||
designerItem.Width -= deltaHorizontal;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnResizeThumbDragCompleted(object sender, DragCompletedEventArgs e)
|
||||
{
|
||||
if (adorner is not null)
|
||||
{
|
||||
AdornerLayer.GetAdornerLayer(canvas)?.Remove(adorner);
|
||||
adorner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,68 +5,67 @@ using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Vision.Recognition.Controls
|
||||
namespace Vision.Recognition.Controls;
|
||||
|
||||
public class RotateThumb : Thumb
|
||||
{
|
||||
public class RotateThumb : Thumb
|
||||
private double initialAngle;
|
||||
private RotateTransform? rotateTransform;
|
||||
private Vector startVector;
|
||||
private Point centerPoint;
|
||||
private ContentControl? designerItem;
|
||||
private Canvas? canvas;
|
||||
|
||||
public RotateThumb()
|
||||
{
|
||||
private double initialAngle;
|
||||
private RotateTransform rotateTransform;
|
||||
private Vector startVector;
|
||||
private Point centerPoint;
|
||||
private ContentControl designerItem;
|
||||
private Canvas canvas;
|
||||
DragDelta += OnRotateThumbDragDelta;
|
||||
DragStarted += OnRotateThumbDragStarted;
|
||||
}
|
||||
|
||||
public RotateThumb()
|
||||
private void OnRotateThumbDragStarted(object sender, DragStartedEventArgs e)
|
||||
{
|
||||
designerItem = DataContext as ContentControl;
|
||||
|
||||
if (designerItem is not null)
|
||||
{
|
||||
DragDelta += new DragDeltaEventHandler(this.RotateThumb_DragDelta);
|
||||
DragStarted += new DragStartedEventHandler(this.RotateThumb_DragStarted);
|
||||
}
|
||||
canvas = VisualTreeHelper.GetParent(designerItem) as Canvas;
|
||||
|
||||
private void RotateThumb_DragStarted(object sender, DragStartedEventArgs e)
|
||||
{
|
||||
this.designerItem = DataContext as ContentControl;
|
||||
|
||||
if (this.designerItem != null)
|
||||
if (canvas is not null)
|
||||
{
|
||||
this.canvas = VisualTreeHelper.GetParent(this.designerItem) as Canvas;
|
||||
centerPoint = designerItem.TranslatePoint(
|
||||
new Point(designerItem.Width * designerItem.RenderTransformOrigin.X,
|
||||
designerItem.Height * designerItem.RenderTransformOrigin.Y),
|
||||
canvas);
|
||||
|
||||
if (this.canvas != null)
|
||||
Point startPoint = Mouse.GetPosition(canvas);
|
||||
startVector = Point.Subtract(startPoint, centerPoint);
|
||||
|
||||
rotateTransform = designerItem.RenderTransform as RotateTransform;
|
||||
if (rotateTransform is null)
|
||||
{
|
||||
this.centerPoint = this.designerItem.TranslatePoint(
|
||||
new Point(this.designerItem.Width * this.designerItem.RenderTransformOrigin.X,
|
||||
this.designerItem.Height * this.designerItem.RenderTransformOrigin.Y),
|
||||
this.canvas);
|
||||
|
||||
Point startPoint = Mouse.GetPosition(this.canvas);
|
||||
this.startVector = Point.Subtract(startPoint, this.centerPoint);
|
||||
|
||||
this.rotateTransform = this.designerItem.RenderTransform as RotateTransform;
|
||||
if (this.rotateTransform == null)
|
||||
{
|
||||
this.designerItem.RenderTransform = new RotateTransform(0);
|
||||
this.initialAngle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.initialAngle = this.rotateTransform.Angle;
|
||||
}
|
||||
designerItem.RenderTransform = new RotateTransform(0);
|
||||
initialAngle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
initialAngle = rotateTransform.Angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RotateThumb_DragDelta(object sender, DragDeltaEventArgs e)
|
||||
private void OnRotateThumbDragDelta(object sender, DragDeltaEventArgs e)
|
||||
{
|
||||
if (designerItem is not null && canvas is not null)
|
||||
{
|
||||
if (this.designerItem != null && this.canvas != null)
|
||||
{
|
||||
Point currentPoint = Mouse.GetPosition(this.canvas);
|
||||
Vector deltaVector = Point.Subtract(currentPoint, this.centerPoint);
|
||||
Point currentPoint = Mouse.GetPosition(canvas);
|
||||
Vector deltaVector = Point.Subtract(currentPoint, centerPoint);
|
||||
|
||||
double angle = Vector.AngleBetween(this.startVector, deltaVector);
|
||||
double angle = Vector.AngleBetween(startVector, deltaVector);
|
||||
|
||||
RotateTransform rotateTransform = this.designerItem.RenderTransform as RotateTransform;
|
||||
rotateTransform.Angle = this.initialAngle + Math.Round(angle, 0);
|
||||
this.designerItem.InvalidateMeasure();
|
||||
}
|
||||
RotateTransform? rotateTransform = designerItem.RenderTransform as RotateTransform;
|
||||
rotateTransform!.Angle = initialAngle + Math.Round(angle, 0);
|
||||
designerItem.InvalidateMeasure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,97 +7,96 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Vision.Recognition
|
||||
namespace Vision.Recognition;
|
||||
|
||||
public class DrawContent
|
||||
{
|
||||
public class DrawContent
|
||||
/// <summary>
|
||||
/// 在遮罩窗口上绘制的矩形
|
||||
/// </summary>
|
||||
public ConcurrentDictionary<string, RectDrawable> RectList { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 在遮罩窗口上绘制的文本
|
||||
/// </summary>
|
||||
public ConcurrentDictionary<string, TextDrawable> TextList { get; set; } = new();
|
||||
|
||||
public void PutRect(string key, RectDrawable newRect)
|
||||
{
|
||||
/// <summary>
|
||||
/// 在遮罩窗口上绘制的矩形
|
||||
/// </summary>
|
||||
public ConcurrentDictionary<string, RectDrawable> RectList { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 在遮罩窗口上绘制的文本
|
||||
/// </summary>
|
||||
public ConcurrentDictionary<string, TextDrawable> TextList { get; set; } = new();
|
||||
|
||||
public void PutRect(string key, RectDrawable newRect)
|
||||
if (RectList.TryGetValue(key, out var prevRect))
|
||||
{
|
||||
if (RectList.TryGetValue(key, out var prevRect))
|
||||
if (newRect.Equals(prevRect))
|
||||
{
|
||||
if (newRect.Equals(prevRect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
RectList[key] = newRect;
|
||||
MaskWindow.Instance().Refresh();
|
||||
}
|
||||
|
||||
public void PutOrRemoveRectList(List<(string, RectDrawable)> list)
|
||||
RectList[key] = newRect;
|
||||
MaskWindow.Instance().Refresh();
|
||||
}
|
||||
|
||||
public void PutOrRemoveRectList(List<(string, RectDrawable)> list)
|
||||
{
|
||||
bool changed = false;
|
||||
list.ForEach(item =>
|
||||
{
|
||||
bool changed = false;
|
||||
list.ForEach(item =>
|
||||
var newRect = item.Item2;
|
||||
if (newRect.IsEmpty)
|
||||
{
|
||||
var newRect = item.Item2;
|
||||
if (newRect.IsEmpty)
|
||||
if (RectList.TryGetValue(item.Item1, out _))
|
||||
{
|
||||
if (RectList.TryGetValue(item.Item1, out _))
|
||||
{
|
||||
RectList.TryRemove(item.Item1, out _);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RectList.TryGetValue(item.Item1, out var prevRect))
|
||||
{
|
||||
if (newRect.Equals(prevRect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
RectList[item.Item1] = newRect;
|
||||
RectList.TryRemove(item.Item1, out _);
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
if (changed)
|
||||
{
|
||||
MaskWindow.Instance().Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveRect(string key)
|
||||
{
|
||||
if (RectList.TryGetValue(key, out _))
|
||||
else
|
||||
{
|
||||
RectList.TryRemove(key, out _);
|
||||
MaskWindow.Instance().Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void PutText(string key, TextDrawable newText)
|
||||
{
|
||||
if (TextList.TryGetValue(key, out var prevText))
|
||||
{
|
||||
if (newText.Equals(prevText))
|
||||
if (RectList.TryGetValue(item.Item1, out var prevRect))
|
||||
{
|
||||
return;
|
||||
if (newRect.Equals(prevRect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
RectList[item.Item1] = newRect;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
TextList[key] = newText;
|
||||
});
|
||||
if (changed)
|
||||
{
|
||||
MaskWindow.Instance().Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveText(string key)
|
||||
public void RemoveRect(string key)
|
||||
{
|
||||
if (RectList.TryGetValue(key, out _))
|
||||
{
|
||||
if (TextList.TryGetValue(key, out _))
|
||||
RectList.TryRemove(key, out _);
|
||||
MaskWindow.Instance().Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void PutText(string key, TextDrawable newText)
|
||||
{
|
||||
if (TextList.TryGetValue(key, out var prevText))
|
||||
{
|
||||
if (newText.Equals(prevText))
|
||||
{
|
||||
TextList.TryRemove(key, out _);
|
||||
MaskWindow.Instance().Refresh();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TextList[key] = newText;
|
||||
MaskWindow.Instance().Refresh();
|
||||
}
|
||||
|
||||
public void RemoveText(string key)
|
||||
{
|
||||
if (TextList.TryGetValue(key, out _))
|
||||
{
|
||||
TextList.TryRemove(key, out _);
|
||||
MaskWindow.Instance().Refresh();
|
||||
}
|
||||
}
|
||||
}
|
@ -5,23 +5,22 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Vision.Recognition.Helper
|
||||
namespace Vision.Recognition.Helper;
|
||||
|
||||
public class Log
|
||||
{
|
||||
public class Log
|
||||
public static void LogInformation(string? message, params object?[] args)
|
||||
{
|
||||
public static void LogInformation(string? message, params object?[] args)
|
||||
{
|
||||
VisionContext.Instance().Log?.LogInformation(message, args);
|
||||
}
|
||||
VisionContext.Instance().Log?.LogInformation(message, args);
|
||||
}
|
||||
|
||||
public static void LogWarning(string? message, params object?[] args)
|
||||
{
|
||||
VisionContext.Instance().Log?.LogWarning(message, args);
|
||||
}
|
||||
public static void LogWarning(string? message, params object?[] args)
|
||||
{
|
||||
VisionContext.Instance().Log?.LogWarning(message, args);
|
||||
}
|
||||
|
||||
public static void LogError(string? message, params object?[] args)
|
||||
{
|
||||
VisionContext.Instance().Log?.LogError(message, args);
|
||||
}
|
||||
public static void LogError(string? message, params object?[] args)
|
||||
{
|
||||
VisionContext.Instance().Log?.LogError(message, args);
|
||||
}
|
||||
}
|
||||
|
@ -1,56 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using Vanara.PInvoke;
|
||||
using Windows.Win32.UI.Input.KeyboardAndMouse;
|
||||
using static Windows.Win32.PInvoke;
|
||||
|
||||
namespace Vision.Recognition.Helper.Simulator
|
||||
namespace Vision.Recognition.Helper.Simulator;
|
||||
|
||||
public class MouseEventSimulator
|
||||
{
|
||||
public class MouseEventSimulator
|
||||
public static void Move(int x, int y)
|
||||
{
|
||||
public static void Move(int x, int y)
|
||||
{
|
||||
User32.mouse_event(User32.MOUSEEVENTF.MOUSEEVENTF_ABSOLUTE | User32.MOUSEEVENTF.MOUSEEVENTF_MOVE,
|
||||
x * 65535 / PrimaryScreen.DESKTOP.Width, y * 65535 / PrimaryScreen.DESKTOP.Height,
|
||||
0, 0);
|
||||
}
|
||||
mouse_event(
|
||||
MOUSE_EVENT_FLAGS.MOUSEEVENTF_ABSOLUTE|MOUSE_EVENT_FLAGS.MOUSEEVENTF_MOVE,
|
||||
x * 65535 / PrimaryScreen.DESKTOP.Width,
|
||||
y * 65535 / PrimaryScreen.DESKTOP.Height,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
|
||||
public static void LeftButtonDown()
|
||||
{
|
||||
User32.mouse_event(User32.MOUSEEVENTF.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
|
||||
}
|
||||
public static void LeftButtonDown()
|
||||
{
|
||||
mouse_event(MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public static void LeftButtonUp()
|
||||
{
|
||||
User32.mouse_event(User32.MOUSEEVENTF.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
|
||||
}
|
||||
public static void LeftButtonUp()
|
||||
{
|
||||
mouse_event(MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
public static bool Click(int x, int y)
|
||||
public static bool Click(int x, int y)
|
||||
{
|
||||
if (x == 0 && y == 0)
|
||||
{
|
||||
if (x == 0 && y == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Move(x, y);
|
||||
LeftButtonDown();
|
||||
Thread.Sleep(20);
|
||||
LeftButtonUp();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
Move(x, y);
|
||||
LeftButtonDown();
|
||||
Thread.Sleep(20);
|
||||
LeftButtonUp();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool Click(Point point)
|
||||
{
|
||||
return Click((int)point.X, (int)point.Y);
|
||||
}
|
||||
public static bool Click(Point point)
|
||||
{
|
||||
return Click((int)point.X, (int)point.Y);
|
||||
}
|
||||
|
||||
public static bool DoubleClick(Point point)
|
||||
{
|
||||
Click(point);
|
||||
Thread.Sleep(200);
|
||||
return Click(point);
|
||||
}
|
||||
public static bool DoubleClick(Point point)
|
||||
{
|
||||
Click(point);
|
||||
Thread.Sleep(200);
|
||||
return Click(point);
|
||||
}
|
||||
}
|
||||
|
@ -1,54 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Interop;
|
||||
using Vanara.PInvoke;
|
||||
using System.Threading;
|
||||
using Windows.Win32.Foundation;
|
||||
using static Windows.Win32.PInvoke;
|
||||
|
||||
namespace Vision.Recognition.Helper.Simulator
|
||||
namespace Vision.Recognition.Helper.Simulator;
|
||||
|
||||
public class PostMessageSimulator
|
||||
{
|
||||
public class PostMessageSimulator
|
||||
private readonly HWND _hWnd;
|
||||
|
||||
public PostMessageSimulator(HWND hWnd)
|
||||
{
|
||||
public static readonly uint WM_LBUTTONDOWN = 0x201; //按下鼠标左键
|
||||
_hWnd = hWnd;
|
||||
}
|
||||
|
||||
public static readonly uint WM_LBUTTONUP = 0x202; //释放鼠标左键
|
||||
/// <summary>
|
||||
/// 指定位置并按下左键
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
public void LeftButtonClick(int x, int y)
|
||||
{
|
||||
LPARAM p = (y << 16) | x;
|
||||
PostMessage(_hWnd, WM_LBUTTONDOWN, default, p);
|
||||
Thread.Sleep(100);
|
||||
PostMessage(_hWnd, WM_LBUTTONUP, default, p);
|
||||
}
|
||||
|
||||
private readonly IntPtr _hWnd;
|
||||
/// <summary>
|
||||
/// 默认位置左键按下
|
||||
/// </summary>
|
||||
public void LeftButtonDown()
|
||||
{
|
||||
PostMessage(_hWnd, WM_LBUTTONDOWN, default, default);
|
||||
}
|
||||
|
||||
public PostMessageSimulator(IntPtr hWnd)
|
||||
{
|
||||
this._hWnd = hWnd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定位置并按下左键
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
public void LeftButtonClick(int x, int y)
|
||||
{
|
||||
IntPtr p = (y << 16) | x;
|
||||
User32.PostMessage(_hWnd, WM_LBUTTONDOWN, IntPtr.Zero, p);
|
||||
Thread.Sleep(100);
|
||||
User32.PostMessage(_hWnd, WM_LBUTTONUP, IntPtr.Zero, p);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 默认位置左键按下
|
||||
/// </summary>
|
||||
public void LeftButtonDown()
|
||||
{
|
||||
User32.PostMessage(_hWnd, WM_LBUTTONDOWN, IntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 默认位置左键释放
|
||||
/// </summary>
|
||||
public void LeftButtonUp()
|
||||
{
|
||||
User32.PostMessage(_hWnd, WM_LBUTTONUP, IntPtr.Zero);
|
||||
}
|
||||
/// <summary>
|
||||
/// 默认位置左键释放
|
||||
/// </summary>
|
||||
public void LeftButtonUp()
|
||||
{
|
||||
PostMessage(_hWnd, WM_LBUTTONUP, default, default);
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using Vanara.PInvoke;
|
||||
using static Vanara.PInvoke.Gdi32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Gdi;
|
||||
using static Windows.Win32.PInvoke;
|
||||
|
||||
namespace Vision.Recognition.Helper.Simulator
|
||||
{
|
||||
@ -15,13 +16,13 @@ namespace Vision.Recognition.Helper.Simulator
|
||||
{
|
||||
get
|
||||
{
|
||||
var hdc = User32.GetDC(IntPtr.Zero);
|
||||
var hdc = GetDC(default);
|
||||
var size = new Size
|
||||
{
|
||||
Width = Gdi32.GetDeviceCaps(hdc, DeviceCap.HORZRES),
|
||||
Height = Gdi32.GetDeviceCaps(hdc, DeviceCap.VERTRES)
|
||||
Width = GetDeviceCaps(hdc, GET_DEVICE_CAPS_INDEX.HORZRES),
|
||||
Height = GetDeviceCaps(hdc, GET_DEVICE_CAPS_INDEX.VERTRES)
|
||||
};
|
||||
User32.ReleaseDC(IntPtr.Zero, hdc);
|
||||
ReleaseDC(default, hdc);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
@ -32,9 +33,9 @@ namespace Vision.Recognition.Helper.Simulator
|
||||
{
|
||||
get
|
||||
{
|
||||
var hdc = User32.GetDC(IntPtr.Zero);
|
||||
var dpiX = Gdi32.GetDeviceCaps(hdc, DeviceCap.LOGPIXELSX);
|
||||
User32.ReleaseDC(IntPtr.Zero, hdc);
|
||||
var hdc = GetDC(default);
|
||||
var dpiX = GetDeviceCaps(hdc, GET_DEVICE_CAPS_INDEX.LOGPIXELSX);
|
||||
ReleaseDC(default, hdc);
|
||||
return dpiX;
|
||||
}
|
||||
}
|
||||
@ -45,9 +46,9 @@ namespace Vision.Recognition.Helper.Simulator
|
||||
{
|
||||
get
|
||||
{
|
||||
var hdc = User32.GetDC(IntPtr.Zero);
|
||||
var dpiX = Gdi32.GetDeviceCaps(hdc, DeviceCap.LOGPIXELSY);
|
||||
User32.ReleaseDC(IntPtr.Zero, hdc);
|
||||
var hdc = GetDC(default);
|
||||
var dpiX = GetDeviceCaps(hdc, GET_DEVICE_CAPS_INDEX.LOGPIXELSY);
|
||||
ReleaseDC(default, hdc);
|
||||
return dpiX;
|
||||
}
|
||||
}
|
||||
@ -58,13 +59,13 @@ namespace Vision.Recognition.Helper.Simulator
|
||||
{
|
||||
get
|
||||
{
|
||||
var hdc = User32.GetDC(IntPtr.Zero);
|
||||
var hdc = GetDC(default);
|
||||
var size = new Size
|
||||
{
|
||||
Width = Gdi32.GetDeviceCaps(hdc, DeviceCap.DESKTOPHORZRES),
|
||||
Height = Gdi32.GetDeviceCaps(hdc, DeviceCap.DESKTOPVERTRES)
|
||||
Width = GetDeviceCaps(hdc, GET_DEVICE_CAPS_INDEX.DESKTOPHORZRES),
|
||||
Height = GetDeviceCaps(hdc, GET_DEVICE_CAPS_INDEX.DESKTOPVERTRES)
|
||||
};
|
||||
User32.ReleaseDC(IntPtr.Zero, hdc);
|
||||
ReleaseDC(default, hdc);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
@ -76,9 +77,9 @@ namespace Vision.Recognition.Helper.Simulator
|
||||
{
|
||||
get
|
||||
{
|
||||
var hdc = User32.GetDC(IntPtr.Zero);
|
||||
var scaleX = (float)Gdi32.GetDeviceCaps(hdc, DeviceCap.DESKTOPHORZRES) / (float)Gdi32.GetDeviceCaps(hdc, DeviceCap.HORZRES);
|
||||
User32.ReleaseDC(IntPtr.Zero, hdc);
|
||||
var hdc = GetDC(default);
|
||||
var scaleX = (float)GetDeviceCaps(hdc, GET_DEVICE_CAPS_INDEX.DESKTOPHORZRES) / GetDeviceCaps(hdc, GET_DEVICE_CAPS_INDEX.HORZRES);
|
||||
ReleaseDC(default, hdc);
|
||||
return scaleX;
|
||||
}
|
||||
}
|
||||
@ -89,9 +90,9 @@ namespace Vision.Recognition.Helper.Simulator
|
||||
{
|
||||
get
|
||||
{
|
||||
var hdc = User32.GetDC(IntPtr.Zero);
|
||||
var scaleY = (float)Gdi32.GetDeviceCaps(hdc, DeviceCap.DESKTOPVERTRES) / (float)Gdi32.GetDeviceCaps(hdc, DeviceCap.VERTRES);
|
||||
User32.ReleaseDC(IntPtr.Zero, hdc);
|
||||
var hdc = GetDC(default);
|
||||
var scaleY = (float)GetDeviceCaps(hdc, GET_DEVICE_CAPS_INDEX.DESKTOPVERTRES) / GetDeviceCaps(hdc, GET_DEVICE_CAPS_INDEX.VERTRES);
|
||||
ReleaseDC(default, hdc);
|
||||
return scaleY;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Win32.Foundation;
|
||||
|
||||
namespace Vision.Recognition.Helper.Simulator
|
||||
namespace Vision.Recognition.Helper.Simulator;
|
||||
|
||||
public class Simulator
|
||||
{
|
||||
public class Simulator
|
||||
public static PostMessageSimulator PostMessage(HWND hWnd)
|
||||
{
|
||||
public static PostMessageSimulator PostMessage(IntPtr hWnd)
|
||||
{
|
||||
return new PostMessageSimulator(hWnd);
|
||||
}
|
||||
return new PostMessageSimulator(hWnd);
|
||||
}
|
||||
}
|
@ -6,21 +6,20 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Vision.Recognition.Task
|
||||
namespace Vision.Recognition.Task;
|
||||
|
||||
/// <summary>
|
||||
/// 和触发器的区别:任务不需要持续捕获游戏图像
|
||||
/// </summary>
|
||||
public class BaseTaskThread
|
||||
{
|
||||
/// <summary>
|
||||
/// 和触发器的区别:任务不需要持续捕获游戏图像
|
||||
/// </summary>
|
||||
public class BaseTaskThread
|
||||
protected ILogger<BaseTaskThread> Log;
|
||||
|
||||
protected CancellationTokenSource Cancellation;
|
||||
|
||||
public BaseTaskThread(ILogger<BaseTaskThread> logger, CancellationTokenSource cts)
|
||||
{
|
||||
protected ILogger<BaseTaskThread> Log;
|
||||
|
||||
protected CancellationTokenSource Cancellation;
|
||||
|
||||
public BaseTaskThread(ILogger<BaseTaskThread> logger, CancellationTokenSource cts)
|
||||
{
|
||||
Log = logger;
|
||||
Cancellation = cts;
|
||||
}
|
||||
Log = logger;
|
||||
Cancellation = cts;
|
||||
}
|
||||
}
|
@ -1,70 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenCvSharp;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OpenCvSharp;
|
||||
using Vision.Recognition.Helper.OpenCv;
|
||||
|
||||
namespace Vision.Recognition.Task
|
||||
namespace Vision.Recognition.Task;
|
||||
|
||||
/// <summary>
|
||||
/// 捕获的内容
|
||||
/// 以及一些多个trigger会用到的内容
|
||||
/// </summary>
|
||||
public class CaptureContent
|
||||
{
|
||||
/// <summary>
|
||||
/// 捕获的内容
|
||||
/// 以及一些多个trigger会用到的内容
|
||||
/// </summary>
|
||||
public class CaptureContent
|
||||
public static readonly int MaxFrameIndexSecond = 60;
|
||||
|
||||
public Bitmap SrcBitmap { get; }
|
||||
public int FrameIndex { get; private set; }
|
||||
public int FrameRate { get; private set; }
|
||||
|
||||
public CaptureContent(Bitmap srcBitmap, int frameIndex, int frameRate)
|
||||
{
|
||||
public static readonly int MaxFrameIndexSecond = 60;
|
||||
SrcBitmap = srcBitmap;
|
||||
FrameIndex = frameIndex;
|
||||
FrameRate = frameRate;
|
||||
}
|
||||
|
||||
public Bitmap SrcBitmap { get; }
|
||||
public int FrameIndex { get; private set; }
|
||||
public int FrameRate { get; private set; }
|
||||
private Mat? _srcMat;
|
||||
|
||||
public CaptureContent(Bitmap srcBitmap, int frameIndex, int frameRate)
|
||||
public Mat SrcMat
|
||||
{
|
||||
get
|
||||
{
|
||||
SrcBitmap = srcBitmap;
|
||||
FrameIndex = frameIndex;
|
||||
FrameRate = frameRate;
|
||||
}
|
||||
|
||||
private Mat? _srcMat;
|
||||
|
||||
public Mat SrcMat
|
||||
{
|
||||
get
|
||||
{
|
||||
_srcMat ??= SrcBitmap.ToMat();
|
||||
return _srcMat;
|
||||
}
|
||||
}
|
||||
|
||||
private Mat? _srcGreyMat;
|
||||
|
||||
public Mat SrcGreyMat
|
||||
{
|
||||
get
|
||||
{
|
||||
_srcGreyMat ??= new Mat();
|
||||
Cv2.CvtColor(SrcMat, _srcGreyMat, ColorConversionCodes.BGR2GRAY);
|
||||
return _srcGreyMat;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 达到了什么时间间隔
|
||||
/// 最大MaxFrameIndexSecond秒
|
||||
/// </summary>
|
||||
/// <param name="interval"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsReachInterval(TimeSpan interval)
|
||||
{
|
||||
if (interval.TotalSeconds > MaxFrameIndexSecond)
|
||||
{
|
||||
throw new ArgumentException($"时间间隔不能超过{MaxFrameIndexSecond}s");
|
||||
}
|
||||
|
||||
return FrameIndex % (FrameRate * interval.TotalSeconds) == 0;
|
||||
_srcMat ??= SrcBitmap.ToMat();
|
||||
return _srcMat;
|
||||
}
|
||||
}
|
||||
|
||||
private Mat? _srcGreyMat;
|
||||
|
||||
public Mat SrcGreyMat
|
||||
{
|
||||
get
|
||||
{
|
||||
_srcGreyMat ??= new Mat();
|
||||
Cv2.CvtColor(SrcMat, _srcGreyMat, ColorConversionCodes.BGR2GRAY);
|
||||
return _srcGreyMat;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 达到了什么时间间隔
|
||||
/// 最大MaxFrameIndexSecond秒
|
||||
/// </summary>
|
||||
/// <param name="interval"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsReachInterval(TimeSpan interval)
|
||||
{
|
||||
if (interval.TotalSeconds > MaxFrameIndexSecond)
|
||||
{
|
||||
throw new ArgumentException($"时间间隔不能超过{MaxFrameIndexSecond}s");
|
||||
}
|
||||
|
||||
return FrameIndex % (FrameRate * interval.TotalSeconds) == 0;
|
||||
}
|
||||
}
|
@ -4,12 +4,11 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Vision.Recognition.Task.Config
|
||||
{
|
||||
public class TaskSettings
|
||||
{
|
||||
string Name { get; set; }
|
||||
namespace Vision.Recognition.Task.Config;
|
||||
|
||||
bool IsEnabled { get; set; }
|
||||
}
|
||||
public class TaskSettings
|
||||
{
|
||||
string Name { get; set; }
|
||||
|
||||
bool IsEnabled { get; set; }
|
||||
}
|
||||
|
@ -5,36 +5,35 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Vision.Recognition
|
||||
namespace Vision.Recognition;
|
||||
|
||||
[Serializable]
|
||||
public class TextDrawable
|
||||
{
|
||||
[Serializable]
|
||||
public class TextDrawable
|
||||
public string Text { get; set; }
|
||||
public Point Point { get; set; }
|
||||
|
||||
public TextDrawable(string text, Point point)
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public Point Point { get; set; }
|
||||
|
||||
public TextDrawable(string text, Point point)
|
||||
{
|
||||
Text = text;
|
||||
Point = point;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj == null || GetType() != obj.GetType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var other = (TextDrawable)obj;
|
||||
return Point.Equals(other.Point);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Point.GetHashCode();
|
||||
}
|
||||
|
||||
public bool IsEmpty => Point is { X: 0, Y: 0 };
|
||||
Text = text;
|
||||
Point = point;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj == null || GetType() != obj.GetType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var other = (TextDrawable)obj;
|
||||
return Point.Equals(other.Point);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Point.GetHashCode();
|
||||
}
|
||||
|
||||
public bool IsEmpty => Point is { X: 0, Y: 0 };
|
||||
}
|
@ -13,7 +13,10 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
|
||||
<PackageReference Include="OpenCvSharp4.Windows" Version="4.8.0.20230708" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageReference Include="Vanara.PInvoke.User32" Version="3.4.16" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BetterGenshinImpact.Win32\BetterGenshinImpact.Win32.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,23 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
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;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Gdi;
|
||||
using static Windows.Win32.PInvoke;
|
||||
|
||||
namespace Vision.WindowCapture.BitBlt
|
||||
{
|
||||
public class BitBltCapture : IWindowCapture
|
||||
{
|
||||
private IntPtr _hWnd;
|
||||
private HWND _hWnd;
|
||||
|
||||
public bool IsCapturing { get; private set; }
|
||||
|
||||
public void Start(IntPtr hWnd)
|
||||
public void Start(HWND hWnd)
|
||||
{
|
||||
_hWnd = hWnd;
|
||||
IsCapturing = true;
|
||||
@ -32,21 +27,21 @@ namespace Vision.WindowCapture.BitBlt
|
||||
|
||||
try
|
||||
{
|
||||
User32.GetWindowRect(_hWnd, out var windowRect);
|
||||
GetWindowRect(_hWnd, out var windowRect);
|
||||
var width = windowRect.Width;
|
||||
var height = windowRect.Height;
|
||||
|
||||
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);
|
||||
var hdcSrc = GetWindowDC(_hWnd);
|
||||
var hdcDest = CreateCompatibleDC(hdcSrc);
|
||||
var hBitmap = CreateCompatibleBitmap(hdcSrc, width, height);
|
||||
var hOld = SelectObject(hdcDest, hBitmap);
|
||||
Windows.Win32.PInvoke.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, ROP_CODE.SRCCOPY);
|
||||
SelectObject(hdcDest, hOld);
|
||||
DeleteDC(hdcDest);
|
||||
ReleaseDC(_hWnd, hdcSrc);
|
||||
|
||||
var bitmap = Image.FromHbitmap(hBitmap);
|
||||
DeleteObject(hBitmap);
|
||||
return bitmap;
|
||||
}
|
||||
catch (Exception e)
|
||||
@ -58,7 +53,7 @@ namespace Vision.WindowCapture.BitBlt
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_hWnd = IntPtr.Zero;
|
||||
_hWnd = HWND.Null;
|
||||
IsCapturing = false;
|
||||
}
|
||||
}
|
||||
|
7
Vision.WindowCapture/CaptureMode.cs
Normal file
7
Vision.WindowCapture/CaptureMode.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Vision.WindowCapture;
|
||||
|
||||
public enum CaptureMode
|
||||
{
|
||||
BitBlt,
|
||||
WindowsGraphicsCapture
|
||||
}
|
9
Vision.WindowCapture/CaptureModeExtensions.cs
Normal file
9
Vision.WindowCapture/CaptureModeExtensions.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Vision.WindowCapture;
|
||||
|
||||
public static class CaptureModeExtensions
|
||||
{
|
||||
public static CaptureMode ToCaptureMode(this string modeName)
|
||||
{
|
||||
return (CaptureMode) Enum.Parse(typeof(CaptureMode), modeName);
|
||||
}
|
||||
}
|
@ -1,32 +1,22 @@
|
||||
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 System.Drawing;
|
||||
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;
|
||||
using Windows.Win32.Foundation;
|
||||
|
||||
namespace Vision.WindowCapture.GraphicsCapture
|
||||
{
|
||||
public class GraphicsCapture : IWindowCapture
|
||||
{
|
||||
private IntPtr _hWnd;
|
||||
private HWND _hWnd;
|
||||
|
||||
private Direct3D11CaptureFramePool _captureFramePool;
|
||||
private GraphicsCaptureItem _captureItem;
|
||||
private GraphicsCaptureSession _captureSession;
|
||||
private Direct3D11CaptureFramePool? _captureFramePool;
|
||||
private GraphicsCaptureItem? _captureItem;
|
||||
private GraphicsCaptureSession? _captureSession;
|
||||
|
||||
public bool IsCapturing { get; private set; }
|
||||
|
||||
public void Start(IntPtr hWnd)
|
||||
public void Start(HWND hWnd)
|
||||
{
|
||||
_hWnd = hWnd;
|
||||
IsCapturing = true;
|
||||
@ -47,7 +37,7 @@ namespace Vision.WindowCapture.GraphicsCapture
|
||||
throw new InvalidOperationException("Failed to create capture item.");
|
||||
}
|
||||
|
||||
_captureItem.Closed += CaptureItemOnClosed;
|
||||
_captureItem.Closed += OnCaptureItemClosed;
|
||||
|
||||
var device = Direct3D11Helper.CreateDevice();
|
||||
|
||||
@ -72,15 +62,15 @@ namespace Vision.WindowCapture.GraphicsCapture
|
||||
{
|
||||
_captureSession?.Dispose();
|
||||
_captureFramePool?.Dispose();
|
||||
_captureSession = null;
|
||||
_captureFramePool = null;
|
||||
_captureItem = null;
|
||||
_captureSession = default;
|
||||
_captureFramePool = default;
|
||||
_captureItem = default;
|
||||
|
||||
_hWnd = IntPtr.Zero;
|
||||
_hWnd = HWND.Null;
|
||||
IsCapturing = false;
|
||||
}
|
||||
|
||||
private void CaptureItemOnClosed(GraphicsCaptureItem sender, object args)
|
||||
private void OnCaptureItemClosed(GraphicsCaptureItem sender, object args)
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
@ -22,67 +22,40 @@
|
||||
// THE SOFTWARE.
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.System.WinRT.Graphics.Capture;
|
||||
using Windows.Graphics.Capture;
|
||||
using WinRT;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace Vision.WindowCapture.GraphicsCapture.Helpers
|
||||
namespace Vision.WindowCapture.GraphicsCapture.Helpers;
|
||||
|
||||
public static class CaptureHelper
|
||||
{
|
||||
public static class CaptureHelper
|
||||
static readonly Guid GraphicsCaptureItemGuid = Guid.Parse("79C3F95B-31F7-4EC2-A464-632EF5D30760");
|
||||
|
||||
public static void SetWindow(this GraphicsCapturePicker picker, IntPtr hwnd)
|
||||
{
|
||||
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;
|
||||
//}
|
||||
InitializeWithWindow.Initialize(picker, hwnd);
|
||||
}
|
||||
|
||||
public static GraphicsCaptureItem CreateItemForWindow(HWND hwnd)
|
||||
{
|
||||
GraphicsCaptureItem
|
||||
.As<IGraphicsCaptureItemInterop>()
|
||||
.CreateForWindow(hwnd, GraphicsCaptureItemGuid, out nint thisPtr);
|
||||
return GraphicsCaptureItem.FromAbi(thisPtr);
|
||||
}
|
||||
|
||||
//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;
|
||||
//}
|
||||
}
|
||||
|
@ -22,11 +22,15 @@
|
||||
// THE SOFTWARE.
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Graphics.DirectX.Direct3D11;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Graphics.Direct3D;
|
||||
using Windows.Win32.Graphics.Direct3D11;
|
||||
using Windows.Win32.Graphics.Dxgi;
|
||||
using Windows.Win32.System.WinRT.Direct3D11;
|
||||
using WinRT;
|
||||
using static Windows.Win32.PInvoke;
|
||||
|
||||
namespace Vision.WindowCapture.GraphicsCapture.Helpers
|
||||
{
|
||||
@ -35,106 +39,71 @@ namespace Vision.WindowCapture.GraphicsCapture.Helpers
|
||||
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 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()
|
||||
public static IDirect3DDevice? CreateDevice()
|
||||
{
|
||||
return CreateDevice(false);
|
||||
}
|
||||
|
||||
public static IDirect3DDevice CreateDevice(bool useWARP)
|
||||
public static unsafe 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;
|
||||
D3D_DRIVER_TYPE driverType = useWARP ? D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_SOFTWARE : D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_HARDWARE;
|
||||
D3D11CreateDevice(
|
||||
default,
|
||||
driverType,
|
||||
default,
|
||||
D3D11_CREATE_DEVICE_FLAG.D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
default,
|
||||
D3D11_SDK_VERSION,
|
||||
out ID3D11Device? d3d11Device,
|
||||
default,
|
||||
out _);
|
||||
|
||||
return CreateDirect3DDeviceFromD3D11Device(d3d11Device);
|
||||
}
|
||||
|
||||
public static IDirect3DDevice CreateDirect3DDeviceFromSharpDXDevice(SharpDX.Direct3D11.Device d3dDevice)
|
||||
public static IDirect3DDevice? CreateDirect3DDeviceFromD3D11Device(ID3D11Device d3d11Device)
|
||||
{
|
||||
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.
|
||||
if (CreateDirect3D11DeviceFromDXGIDevice(d3d11Device.As<IDXGIDevice>(), out Windows.Win32.System.WinRT.IInspectable iInspectable).Succeeded)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
nint pointer = Marshal.GetIUnknownForObject(iInspectable);
|
||||
return MarshalInterface<IDirect3DDevice>.FromAbi(pointer);
|
||||
}
|
||||
|
||||
return device;
|
||||
return default;
|
||||
}
|
||||
|
||||
public static IDirect3DSurface CreateDirect3DSurfaceFromSharpDXTexture(SharpDX.Direct3D11.Texture2D texture)
|
||||
public static IDirect3DSurface? CreateDirect3DSurfaceFromSharpDXTexture(ID3D11Texture2D 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.
|
||||
if (CreateDirect3D11SurfaceFromDXGISurface(texture.As<IDXGISurface>(), out Windows.Win32.System.WinRT.IInspectable iInspectable).Succeeded)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
nint pointer = Marshal.GetIUnknownForObject(iInspectable);
|
||||
return MarshalInterface<IDirect3DSurface>.FromAbi(pointer);
|
||||
}
|
||||
|
||||
return surface;
|
||||
return default;
|
||||
}
|
||||
|
||||
public static SharpDX.Direct3D11.Device CreateSharpDXDevice(IDirect3DDevice device)
|
||||
public static ID3D11Device CreateD3D11Device(IDirect3DDevice device)
|
||||
{
|
||||
var access = (IDirect3DDxgiInterfaceAccess)device;
|
||||
var d3dPointer = access.GetInterface(ID3D11Device);
|
||||
var d3dDevice = new SharpDX.Direct3D11.Device(d3dPointer);
|
||||
return d3dDevice;
|
||||
device
|
||||
.As<IDirect3DDxgiInterfaceAccess>()
|
||||
.GetInterface(typeof(ID3D11Device).GUID, out var d3dDevice);
|
||||
return MarshalInterface<ID3D11Device>.FromAbi(d3dDevice);
|
||||
}
|
||||
|
||||
public static SharpDX.Direct3D11.Texture2D CreateSharpDXTexture2D(IDirect3DSurface surface)
|
||||
public static ID3D11Texture2D CreateD3D11Texture2D(IDirect3DSurface surface)
|
||||
{
|
||||
var access = surface.As<IDirect3DDxgiInterfaceAccess>();
|
||||
var d3dPointer = access.GetInterface(ID3D11Texture2D);
|
||||
var d3dSurface = new SharpDX.Direct3D11.Texture2D(d3dPointer);
|
||||
return d3dSurface;
|
||||
surface
|
||||
.As<IDirect3DDxgiInterfaceAccess>()
|
||||
.GetInterface(typeof(ID3D11Texture2D).GUID, out var d3dSurface);
|
||||
return MarshalInterface<ID3D11Texture2D>.FromAbi(d3dSurface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,65 +1,51 @@
|
||||
using SharpDX;
|
||||
using SharpDX.Direct3D11;
|
||||
using SharpDX.DXGI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
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 Windows.Win32;
|
||||
using Windows.Win32.Graphics.Direct3D11;
|
||||
using Windows.Win32.Graphics.Dxgi.Common;
|
||||
using WinRT;
|
||||
|
||||
namespace Vision.WindowCapture.GraphicsCapture.Helpers
|
||||
{
|
||||
public static class Texture2DExtensions
|
||||
{
|
||||
public static Bitmap? ToBitmap(this Direct3D11CaptureFrame frame)
|
||||
public static unsafe Bitmap ToBitmap(this Direct3D11CaptureFrame frame)
|
||||
{
|
||||
var texture2dBitmap = Direct3D11Helper.CreateSharpDXTexture2D(frame.Surface);
|
||||
var texture2dBitmap = Direct3D11Helper.CreateD3D11Texture2D(frame.Surface);
|
||||
|
||||
var d3dDevice = texture2dBitmap.Device;
|
||||
texture2dBitmap.GetDevice(out var d3dDevice);
|
||||
texture2dBitmap.GetDesc(out D3D11_TEXTURE2D_DESC desc);
|
||||
D3D11_TEXTURE2D_DESC newDesc = new()
|
||||
{
|
||||
Width = (uint)frame.ContentSize.Width,
|
||||
Height = (uint)frame.ContentSize.Height,
|
||||
MipLevels = 1U,
|
||||
ArraySize = 1U,
|
||||
Format = desc.Format,
|
||||
Usage = D3D11_USAGE.D3D11_USAGE_STAGING,
|
||||
SampleDesc = new DXGI_SAMPLE_DESC() { Count = 1 },
|
||||
CPUAccessFlags = D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ,
|
||||
};
|
||||
|
||||
// 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
|
||||
});
|
||||
d3dDevice.CreateTexture2D(newDesc, default, out ID3D11Texture2D staging);
|
||||
d3dDevice.GetImmediateContext(out ID3D11DeviceContext context);
|
||||
|
||||
try
|
||||
{
|
||||
// Copy data
|
||||
d3dDevice.ImmediateContext.CopyResource(texture2dBitmap, staging);
|
||||
// Copy data
|
||||
context.CopyResource(texture2dBitmap, staging);
|
||||
D3D11_MAPPED_SUBRESOURCE subResource = default;
|
||||
context.Map(staging, default, D3D11_MAP.D3D11_MAP_READ, default, &subResource);
|
||||
|
||||
var dataBox = d3dDevice.ImmediateContext.MapSubresource(staging, 0, 0, MapMode.Read,
|
||||
SharpDX.Direct3D11.MapFlags.None,
|
||||
out DataStream stream);
|
||||
staging.GetDesc(out var stagingDesc);
|
||||
var bitmap = new Bitmap(
|
||||
(int)stagingDesc.Width,
|
||||
(int)stagingDesc.Height,
|
||||
(int)subResource.RowPitch,
|
||||
PixelFormat.Format32bppArgb,
|
||||
(nint)subResource.pData);
|
||||
|
||||
var bitmap = new Bitmap(staging.Description.Width, staging.Description.Height, dataBox.RowPitch,
|
||||
PixelFormat.Format32bppArgb, dataBox.DataPointer);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
finally
|
||||
{
|
||||
staging.Dispose();
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
//public static Stream ToBitmapStream(this Direct3D11CaptureFrame frame)
|
||||
|
@ -1,115 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
using System.Drawing;
|
||||
using Windows.Win32.Foundation;
|
||||
|
||||
namespace Vision.WindowCapture
|
||||
namespace Vision.WindowCapture;
|
||||
|
||||
public interface IWindowCapture
|
||||
{
|
||||
public interface IWindowCapture
|
||||
{
|
||||
bool IsCapturing { get; }
|
||||
|
||||
void Start(IntPtr hWnd);
|
||||
bool IsCapturing { get; }
|
||||
|
||||
void Start(HWND hWnd);
|
||||
|
||||
Bitmap? Capture();
|
||||
Bitmap? Capture();
|
||||
|
||||
void Stop();
|
||||
}
|
||||
void Stop();
|
||||
}
|
@ -8,11 +8,16 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />
|
||||
<None Remove="README.md" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<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" />
|
||||
<PackageReference Include="Vortice.Direct3D11" Version="3.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BetterGenshinImpact.Win32\BetterGenshinImpact.Win32.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,44 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
namespace Vision.WindowCapture;
|
||||
|
||||
namespace Vision.WindowCapture
|
||||
public class WindowCaptureFactory
|
||||
{
|
||||
public enum CaptureMode
|
||||
public static string[] ModeNames()
|
||||
{
|
||||
BitBlt,
|
||||
WindowsGraphicsCapture
|
||||
return Enum.GetNames(typeof(CaptureMode));
|
||||
}
|
||||
|
||||
public static class CaptureModeExtensions
|
||||
|
||||
public static IWindowCapture Create(CaptureMode mode)
|
||||
{
|
||||
public static CaptureMode ToCaptureMode(this string modeName)
|
||||
switch (mode)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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