-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAutoRunController.cs
More file actions
171 lines (146 loc) · 4.55 KB
/
Copy pathAutoRunController.cs
File metadata and controls
171 lines (146 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
using System;
using System.Runtime.InteropServices;
namespace SquadTools;
internal sealed class AutoRunController : IDisposable
{
private readonly System.Windows.Forms.Timer inputTimer = new() { Interval = 50 };
private readonly NativeMethods.LowLevelKeyboardProc keyboardCallback;
private IntPtr keyboardHook;
private bool wDown;
private bool leftShiftDown;
private bool hasStartedInSquad;
internal event Action<string>? StatusChanged;
internal event Action<string>? Error;
internal event Action<string>? Stopped;
internal bool Enabled { get; private set; }
internal AutoRunController()
{
keyboardCallback = HandleKeyboardInput;
inputTimer.Tick += (_, _) => MaintainKeys();
}
internal void SetEnabled(bool enabled)
{
if (!enabled)
{
Stop("未启用", false);
return;
}
if (!InstallKeyboardHook())
{
Error?.Invoke("无法监听键盘输入,请尝试以管理员身份运行本程序。");
return;
}
Enabled = true;
hasStartedInSquad = false;
StatusChanged?.Invoke("已开启,等待 Squad 窗口");
inputTimer.Start();
MaintainKeys();
}
private void MaintainKeys()
{
if (!Enabled)
{
return;
}
bool squadForeground = NativeMethods.IsSquadForeground();
if (!squadForeground)
{
if (hasStartedInSquad)
{
Stop("已停止:已切出 Squad", true);
}
return;
}
if (!wDown)
{
if (!NativeMethods.SendKey(NativeMethods.VkW))
{
Stop("未启用", true);
Error?.Invoke($"Windows 未接受自动奔跑按键输入。{NativeMethods.DescribeLastInputError()}。请确认本程序与游戏权限一致。");
return;
}
wDown = true;
hasStartedInSquad = true;
StatusChanged?.Invoke("自动奔跑中");
return;
}
if (!leftShiftDown)
{
if (!NativeMethods.SendKey(NativeMethods.VkLeftShift))
{
Stop("未启用", true);
Error?.Invoke($"Windows 未接受自动奔跑按键输入。{NativeMethods.DescribeLastInputError()}。请确认本程序与游戏权限一致。");
return;
}
leftShiftDown = true;
}
}
private IntPtr HandleKeyboardInput(int code, IntPtr message, IntPtr data)
{
if (Enabled && code >= 0 &&
(message.ToInt32() == NativeMethods.WmKeyDown || message.ToInt32() == NativeMethods.WmSystemKeyDown))
{
NativeMethods.LowLevelKeyboardInput input = Marshal.PtrToStructure<NativeMethods.LowLevelKeyboardInput>(data);
bool injected = (input.Flags & NativeMethods.LowLevelKeyboardFlags.Injected) != 0;
if (!injected && input.VirtualKey != NativeMethods.VkF10)
{
Stop("已停止:检测到键盘输入", true);
}
}
return NativeMethods.CallNextHookEx(keyboardHook, code, message, data);
}
private bool InstallKeyboardHook()
{
if (keyboardHook != IntPtr.Zero)
{
return true;
}
keyboardHook = NativeMethods.SetWindowsHookEx(
NativeMethods.WhKeyboardLowLevel,
keyboardCallback,
NativeMethods.GetModuleHandle(null),
0);
return keyboardHook != IntPtr.Zero;
}
private void RemoveKeyboardHook()
{
if (keyboardHook == IntPtr.Zero)
{
return;
}
NativeMethods.UnhookWindowsHookEx(keyboardHook);
keyboardHook = IntPtr.Zero;
}
private void Stop(string status, bool notify)
{
bool wasEnabled = Enabled;
inputTimer.Stop();
Enabled = false;
ReleaseKeys();
RemoveKeyboardHook();
hasStartedInSquad = false;
StatusChanged?.Invoke(status);
if (notify && wasEnabled)
{
Stopped?.Invoke(status);
}
}
private void ReleaseKeys()
{
if (leftShiftDown)
{
NativeMethods.SendKey(NativeMethods.VkLeftShift, true);
leftShiftDown = false;
}
if (wDown)
{
NativeMethods.SendKey(NativeMethods.VkW, true);
wDown = false;
}
}
public void Dispose()
{
Stop("未启用", false);
inputTimer.Dispose();
}
}