Skip to content

Commit b4c3620

Browse files
committed
[Breaking change] feat: support Win32ScreencapMethods speed test
MaaXYZ/MaaFramework#1183
1 parent f2fe94c commit b4c3620

9 files changed

Lines changed: 86 additions & 69 deletions

File tree

docs/articles/overview-of-wrapper-and-api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
| --- | --- |
2525
| AdbScreencapMethods | `MaaAdbScreencapMethod` |
2626
| AdbInputMethods | `MaaAdbInputMethod` |
27-
| Win32ScreencapMethod | `MaaWin32ScreencapMethod` |
27+
| Win32ScreencapMethods | `MaaWin32ScreencapMethod` |
2828
| Win32InputMethod | `MaaWin32InputMethod` |
2929
| MacOSScreencapMethod | `MaaMacOSScreencapMethod` |
3030
| MacOSInputMethod | `MaaMacOSInputMethod` |

src/MaaFramework.Binding.Native/Extensions/DesktopWindowInfoExtensions.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public static class DesktopWindowInfoExtensions
99
/// Converts a <see cref="DesktopWindowInfo"/> to a <see cref="MaaWin32Controller"/>.
1010
/// </summary>
1111
/// <param name="info">The DesktopWindowInfo.</param>
12-
/// <param name="screencapMethod">The screencap method.</param>
12+
/// <param name="screencapMethods">The screencap methods.</param>
1313
/// <param name="mouseMethod">The mouse method.</param>
1414
/// <param name="keyboardMethod">The keyboard method.</param>
1515
/// <param name="hWnd">The new handle to a win32 window.</param>
@@ -18,7 +18,7 @@ public static class DesktopWindowInfoExtensions
1818
/// <returns>A MaaWin32Controller.</returns>
1919
/// <exception cref="ArgumentNullException"/>
2020
public static MaaWin32Controller ToWin32ControllerWith(this DesktopWindowInfo info,
21-
Win32ScreencapMethod? screencapMethod = null,
21+
Win32ScreencapMethods? screencapMethods = null,
2222
Win32InputMethod? mouseMethod = null,
2323
Win32InputMethod? keyboardMethod = null,
2424
nint? hWnd = null,
@@ -33,7 +33,7 @@ public static MaaWin32Controller ToWin32ControllerWith(this DesktopWindowInfo in
3333
handle,
3434
handle == info.Handle ? info.Name : string.Empty,
3535
handle == info.Handle ? info.ClassName : string.Empty,
36-
screencapMethod ?? info.ScreencapMethod,
36+
screencapMethods ?? info.ScreencapMethods,
3737
mouseMethod ?? info.MouseMethod,
3838
keyboardMethod ?? info.KeyboardMethod
3939
),
@@ -42,7 +42,7 @@ public static MaaWin32Controller ToWin32ControllerWith(this DesktopWindowInfo in
4242
);
4343
}
4444

45-
/// <inheritdoc cref="ToWin32ControllerWith(DesktopWindowInfo, Win32ScreencapMethod?, Win32InputMethod?, Win32InputMethod?, nint?, LinkOption, CheckStatusOption)"/>
45+
/// <inheritdoc cref="ToWin32ControllerWith(DesktopWindowInfo, Win32ScreencapMethods?, Win32InputMethod?, Win32InputMethod?, nint?, LinkOption, CheckStatusOption)"/>
4646
public static MaaWin32Controller ToWin32Controller(this DesktopWindowInfo info,
4747
LinkOption link = LinkOption.Start,
4848
CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
@@ -57,15 +57,15 @@ public static MaaWin32Controller ToWin32Controller(this DesktopWindowInfo info,
5757
/// </summary>
5858
/// <param name="info">The DesktopWindowInfo.</param>
5959
/// <param name="gamepadType">The type of virtual gamepad.</param>
60-
/// <param name="screencapMethod">The screencap method.</param>
60+
/// <param name="screencapMethods">The screencap methods.</param>
6161
/// <param name="hWnd">The new handle to a win32 window.</param>
6262
/// <param name="link">Executes <see cref="MaaController.LinkStart"/> if <see cref="LinkOption.Start"/>; otherwise, not link.</param>
6363
/// <param name="check">Checks LinkStart().Wait() status if <see cref="CheckStatusOption.ThrowIfNotSucceeded"/>; otherwise, not check.</param>
6464
/// <returns>A MaaGamepadController.</returns>
6565
/// <exception cref="ArgumentNullException"/>
6666
public static MaaGamepadController ToGamepadControllerWith(this DesktopWindowInfo info,
6767
GamepadType gamepadType,
68-
Win32ScreencapMethod? screencapMethod = null,
68+
Win32ScreencapMethods? screencapMethods = null,
6969
nint? hWnd = null,
7070
LinkOption link = LinkOption.Start,
7171
CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
@@ -82,7 +82,7 @@ public static MaaGamepadController ToGamepadControllerWith(this DesktopWindowInf
8282
handle,
8383
handle == info.Handle ? info.Name : string.Empty,
8484
handle == info.Handle ? info.ClassName : string.Empty,
85-
screencapMethod ?? info.ScreencapMethod,
85+
screencapMethods ?? info.ScreencapMethods,
8686
Win32InputMethod.None,
8787
Win32InputMethod.None
8888
),
@@ -91,7 +91,7 @@ public static MaaGamepadController ToGamepadControllerWith(this DesktopWindowInf
9191
);
9292
}
9393

94-
/// <inheritdoc cref="ToGamepadControllerWith(DesktopWindowInfo, GamepadType, Win32ScreencapMethod?, nint?, LinkOption, CheckStatusOption)"/>
94+
/// <inheritdoc cref="ToGamepadControllerWith(DesktopWindowInfo, GamepadType, Win32ScreencapMethods?, nint?, LinkOption, CheckStatusOption)"/>
9595
public static MaaGamepadController ToGamepadController(this DesktopWindowInfo info,
9696
GamepadType gamepadType,
9797
LinkOption link = LinkOption.Start,

src/MaaFramework.Binding.Native/MaaController/MaaGamepadController.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public class MaaGamepadController : MaaController
3737
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
3838
private string DebuggerInfoString => _debugInfo is null
3939
? "No Screencap"
40-
: $"{nameof(_debugInfo.Name)} = {_debugInfo.Name}, {nameof(_debugInfo.ClassName)} = {_debugInfo.ClassName}, ScreencapMethod = {_debugInfo.ScreencapMethod}";
40+
: $"{nameof(_debugInfo.Name)} = {_debugInfo.Name}, {nameof(_debugInfo.ClassName)} = {_debugInfo.ClassName}, ScreencapMethod = {_debugInfo.ScreencapMethods}";
4141

4242
/// <summary>
4343
/// Creates a <see cref="MaaGamepadController"/> instance.
@@ -54,7 +54,7 @@ public MaaGamepadController(GamepadType gamepadType, DesktopWindowInfo? info = n
5454
{
5555
var handle = info is null
5656
? MaaGamepadControllerCreate(nint.Zero, (MaaGamepadType)gamepadType, 0UL)
57-
: MaaGamepadControllerCreate(info.Handle, (MaaGamepadType)gamepadType, (MaaWin32ScreencapMethod)info.ScreencapMethod);
57+
: MaaGamepadControllerCreate(info.Handle, (MaaGamepadType)gamepadType, (MaaWin32ScreencapMethod)info.ScreencapMethods);
5858
_ = MaaControllerAddSink(handle, MaaEventCallback, (nint)MaaHandleType.Controller);
5959
SetHandle(handle, needReleased: true);
6060

@@ -67,12 +67,12 @@ public MaaGamepadController(GamepadType gamepadType, DesktopWindowInfo? info = n
6767

6868
/// <param name="hWnd">Window handle for screencap (optional, can be <see cref="nint.Zero"/> if screencap not needed).</param>
6969
/// <param name="gamepadType">Type of virtual gamepad (<see cref="GamepadType.Xbox360"/> or <see cref="GamepadType.DualShock4"/>).</param>
70-
/// <param name="screencapMethod">Win32 screencap method to use. Ignored if hWnd is <see cref="nint.Zero"/>.</param>
70+
/// <param name="screencapMethods">Win32 screencap methods to use. Ignored if hWnd is <see cref="nint.Zero"/>.</param>
7171
/// <param name="link">Executes <see cref="IMaaController.LinkStart"/> if <see cref="LinkOption.Start"/>; otherwise, not link.</param>
7272
/// <param name="check">Checks LinkStart().Wait() status if <see cref="CheckStatusOption.ThrowIfNotSucceeded"/>; otherwise, not check.</param>
7373
/// <inheritdoc cref="Binding.MaaGamepadController(GamepadType, DesktopWindowInfo, LinkOption, CheckStatusOption)"/>
74-
public MaaGamepadController(nint hWnd, GamepadType gamepadType, Win32ScreencapMethod screencapMethod, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
75-
: this(gamepadType, hWnd == nint.Zero ? null : new(hWnd, string.Empty, string.Empty, screencapMethod, Win32InputMethod.None, Win32InputMethod.None), link, check)
74+
public MaaGamepadController(nint hWnd, GamepadType gamepadType, Win32ScreencapMethods screencapMethods, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
75+
: this(gamepadType, hWnd == nint.Zero ? null : new(hWnd, string.Empty, string.Empty, screencapMethods, Win32InputMethod.None, Win32InputMethod.None), link, check)
7676
{
7777
}
7878

src/MaaFramework.Binding.Native/MaaController/MaaWin32Controller.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class MaaWin32Controller : MaaController
1616
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
1717
private string DebuggerDisplay => IsInvalid
1818
? $"Invalid {GetType().Name}"
19-
: $"{GetType().Name} {{ {nameof(_debugInfo.Name)} = {_debugInfo.Name}, {nameof(_debugInfo.ClassName)} = {_debugInfo.ClassName}, ScreencapMethod = {_debugInfo.ScreencapMethod}, MouseMethod = {_debugInfo.MouseMethod}, KeyboardMethod = {_debugInfo.KeyboardMethod} }}";
19+
: $"{GetType().Name} {{ {nameof(_debugInfo.Name)} = {_debugInfo.Name}, {nameof(_debugInfo.ClassName)} = {_debugInfo.ClassName}, ScreencapMethod = {_debugInfo.ScreencapMethods}, MouseMethod = {_debugInfo.MouseMethod}, KeyboardMethod = {_debugInfo.KeyboardMethod} }}";
2020

2121
/// <summary>
2222
/// Creates a <see cref="MaaWin32Controller"/> instance.
@@ -34,7 +34,7 @@ public MaaWin32Controller(DesktopWindowInfo info, LinkOption link = LinkOption.S
3434
ArgumentNullException.ThrowIfNull(info);
3535
if (info.Handle == nint.Zero) throw new ArgumentException("Value cannot be zero.", "info.Handle");
3636

37-
var handle = MaaWin32ControllerCreate(info.Handle, (MaaWin32ScreencapMethod)info.ScreencapMethod, (MaaWin32InputMethod)info.MouseMethod, (MaaWin32InputMethod)info.KeyboardMethod);
37+
var handle = MaaWin32ControllerCreate(info.Handle, (MaaWin32ScreencapMethod)info.ScreencapMethods, (MaaWin32InputMethod)info.MouseMethod, (MaaWin32InputMethod)info.KeyboardMethod);
3838
_ = MaaControllerAddSink(handle, MaaEventCallback, (nint)MaaHandleType.Controller);
3939
SetHandle(handle, needReleased: true);
4040

@@ -45,14 +45,14 @@ public MaaWin32Controller(DesktopWindowInfo info, LinkOption link = LinkOption.S
4545
}
4646

4747
/// <param name="hWnd">The handle to a win32 window.</param>
48-
/// <param name="screencapMethod">The screencap method.</param>
48+
/// <param name="screencapMethods">The screencap methods.</param>
4949
/// <param name="mouseMethod">The mouse method.</param>
5050
/// <param name="keyboardMethod">The keyboard method.</param>
5151
/// <param name="link">Executes <see cref="IMaaController.LinkStart"/> if <see cref="LinkOption.Start"/>; otherwise, not link.</param>
5252
/// <param name="check">Checks LinkStart().Wait() status if <see cref="CheckStatusOption.ThrowIfNotSucceeded"/>; otherwise, not check.</param>
5353
/// <inheritdoc cref="Binding.MaaWin32Controller(DesktopWindowInfo, LinkOption, CheckStatusOption)"/>
54-
public MaaWin32Controller(nint hWnd, Win32ScreencapMethod screencapMethod, Win32InputMethod mouseMethod, Win32InputMethod keyboardMethod, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
55-
: this(new DesktopWindowInfo(hWnd, string.Empty, string.Empty, screencapMethod, mouseMethod, keyboardMethod), link, check)
54+
public MaaWin32Controller(nint hWnd, Win32ScreencapMethods screencapMethods, Win32InputMethod mouseMethod, Win32InputMethod keyboardMethod, LinkOption link = LinkOption.Start, CheckStatusOption check = CheckStatusOption.ThrowIfNotSucceeded)
55+
: this(new DesktopWindowInfo(hWnd, string.Empty, string.Empty, screencapMethods, mouseMethod, keyboardMethod), link, check)
5656
{
5757
}
5858
}

src/MaaFramework.Binding.UnitTests/Test_IMaaController.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,18 +118,18 @@ public void CreateInstances()
118118

119119
using var win32Native1 = new MaaWin32Controller(
120120
windowInfo.Handle,
121-
Win32ScreencapMethod.GDI,
121+
Win32ScreencapMethods.GDI,
122122
Win32InputMethod.SendMessage,
123123
Win32InputMethod.SendMessage);
124124
using var win32Native2 = new MaaWin32Controller(
125125
windowInfo.Handle,
126-
Win32ScreencapMethod.GDI,
126+
Win32ScreencapMethods.GDI,
127127
Win32InputMethod.SendMessage,
128128
Win32InputMethod.SendMessage,
129129
LinkOption.None);
130130
using var win32Native3 = new MaaWin32Controller(
131131
windowInfo.Handle,
132-
Win32ScreencapMethod.GDI,
132+
Win32ScreencapMethods.GDI,
133133
Win32InputMethod.SendMessage,
134134
Win32InputMethod.SendMessage,
135135
LinkOption.Start,

src/MaaFramework.Binding.UnitTests/Test_IMaaToolkit.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private static void Test_Win32_WindowInfos(MaaTypes type, IList<DesktopWindowInf
103103
using var maaController = type switch
104104
{
105105
MaaTypes.Native => windows[0].ToWin32ControllerWith(
106-
screencapMethod: Win32ScreencapMethod.GDI,
106+
screencapMethods: Win32ScreencapMethods.GDI,
107107
mouseMethod: Win32InputMethod.SendMessage,
108108
keyboardMethod: Win32InputMethod.SendMessage,
109109
link: LinkOption.None),
@@ -118,7 +118,7 @@ private static void Test_Win32_WindowInfos(MaaTypes type, IList<DesktopWindowInf
118118
using var optionalArgumentDefaultValuesTest = type switch
119119
{
120120
MaaTypes.Native => windows[0].ToWin32ControllerWith(
121-
screencapMethod: Win32ScreencapMethod.GDI,
121+
screencapMethods: Win32ScreencapMethods.GDI,
122122
mouseMethod: Win32InputMethod.SendMessage,
123123
keyboardMethod: Win32InputMethod.SendMessage),
124124
_ => throw new NotImplementedException(),

src/MaaFramework.Binding/Enums/Controllers/Win32ScreencapMethod.cs

Lines changed: 0 additions & 43 deletions
This file was deleted.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
#pragma warning disable CS1573 // 参数在 XML 注释中没有匹配的 param 标记
11+
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
12+
13+
namespace MaaFramework.Binding;
14+
15+
/// <summary>
16+
/// Win32 screencap method flags
17+
///
18+
/// <para>Use bitwise OR to set the methods you need.
19+
/// <br/>MaaFramework will test all provided methods and use the fastest available one.</para>
20+
///
21+
/// <para>No default value. Client should choose one as default.</para>
22+
///
23+
/// <para>Predefined combinations:
24+
/// <br/>- Foreground: DXGI_DesktopDup_Window | ScreenDC
25+
/// <br/>- Background: FramePool | PrintWindow</para>
26+
///
27+
/// <para>Different applications use different rendering methods, there is no universal solution.</para>
28+
///
29+
/// <code>| Method | Speed | Compatibility | Require Admin | Background Support | Notes |
30+
/// <br/>|-------------------------|-----------|---------------|---------------|--------------------|----------------------------------|
31+
/// <br/>| GDI | Fast | Medium | No | No | |
32+
/// <br/>| FramePool | Very Fast | Medium | No | Yes | Requires Windows 10 1903+ |
33+
/// <br/>| DXGI_DesktopDup | Very Fast | Low | No | No | Desktop duplication (full screen)|
34+
/// <br/>| DXGI_DesktopDup_Window | Very Fast | Low | No | No | Desktop duplication then crop |
35+
/// <br/>| PrintWindow | Medium | Medium | No | Yes | |
36+
/// <br/>| ScreenDC | Fast | High | No | No | |
37+
/// </code>
38+
///
39+
/// <para>Note: FramePool and PrintWindow support pseudo-minimize — when the target window
40+
/// <br/>is minimized, they make it transparent and click-through, then restore it without
41+
/// <br/>activation, allowing screencap to continue without disturbing the user.
42+
/// <br/>Other screencap methods will fail when the target window is minimized.</para>
43+
///
44+
/// </summary>
45+
[Flags]
46+
public enum Win32ScreencapMethods : System.UInt64
47+
{
48+
None = 0,
49+
GDI = 1,
50+
FramePool = (1 << 1),
51+
DXGI_DesktopDup = (1 << 2),
52+
DXGI_DesktopDup_Window = (1 << 3),
53+
PrintWindow = (1 << 4),
54+
ScreenDC = (1 << 5),
55+
56+
All = ~None,
57+
Foreground = DXGI_DesktopDup_Window | ScreenDC,
58+
Background = FramePool | PrintWindow,
59+
}
60+

src/MaaFramework.Binding/Infos/DesktopWindowInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
/// <param name="Handle">Gets the handle to a window.</param>
77
/// <param name="Name">Gets the window name.</param>
88
/// <param name="ClassName">Gets the window class name.</param>
9-
/// <param name="ScreencapMethod">The screencap method.</param>
9+
/// <param name="ScreencapMethods">The screencap methods.</param>
1010
/// <param name="MouseMethod">The mouse method.</param>
1111
/// <param name="KeyboardMethod">The keyboard method.</param>
1212
public record DesktopWindowInfo(
1313
nint Handle,
1414
string Name,
1515
string ClassName,
16-
Win32ScreencapMethod ScreencapMethod = Win32ScreencapMethod.DXGI_DesktopDup,
16+
Win32ScreencapMethods ScreencapMethods = Win32ScreencapMethods.Background,
1717
Win32InputMethod MouseMethod = Win32InputMethod.Seize,
1818
Win32InputMethod KeyboardMethod = Win32InputMethod.Seize
1919
);

0 commit comments

Comments
 (0)