Skip to content

Commit 8520de9

Browse files
authored
refactor: MaaFW style refactoring (#1241)
1 parent 722e33a commit 8520de9

3 files changed

Lines changed: 67 additions & 98 deletions

File tree

source/MaaWin32ControlUnit/Input/MessageInput.cpp

Lines changed: 65 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "InputUtils.h"
1111

12+
#include <algorithm>
1213
#include <mmsystem.h>
1314

1415
MAA_CTRL_UNIT_NS_BEGIN
@@ -28,44 +29,31 @@ struct ShcoreDllHolder : public LibraryHolder<ShcoreDllHolder>
2829
{
2930
};
3031

31-
template <typename Holder>
32-
void ensure_library_loaded(const wchar_t* libname)
33-
{
34-
static std::once_flag once;
35-
std::call_once(once, [libname]() { Holder::load_library(libname); });
36-
}
37-
38-
template <typename Holder, typename Fn>
39-
boost::function<Fn> resolve_library_function(const wchar_t* libname, const std::string& name)
40-
{
41-
ensure_library_loaded<Holder>(libname);
42-
return Holder::template get_function<Fn>(name);
43-
}
44-
4532
void ensure_process_dpi_awareness_once()
4633
{
47-
static std::once_flag once;
48-
std::call_once(once, []() {
34+
[[maybe_unused]] static const int dpi_init_once = []() {
35+
User32DllHolder::load_library(L"user32.dll");
36+
4937
using FnCtx = BOOL WINAPI(DPI_AWARENESS_CONTEXT);
50-
auto fn_ctx = resolve_library_function<User32DllHolder, FnCtx>(L"user32.dll", "SetProcessDpiAwarenessContext");
38+
auto fn_ctx = User32DllHolder::get_function<FnCtx>("SetProcessDpiAwarenessContext");
5139
if (fn_ctx && fn_ctx(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) {
52-
return;
40+
return 0;
5341
}
5442
if (fn_ctx && GetLastError() == ERROR_ACCESS_DENIED) {
55-
return;
43+
return 0;
5644
}
5745

46+
ShcoreDllHolder::load_library(L"shcore.dll");
47+
5848
using FnAware = HRESULT WINAPI(int);
59-
auto fn_aware = resolve_library_function<ShcoreDllHolder, FnAware>(L"shcore.dll", "SetProcessDpiAwareness");
49+
auto fn_aware = ShcoreDllHolder::get_function<FnAware>("SetProcessDpiAwareness");
6050
if (!fn_aware) {
61-
return;
51+
return 0;
6252
}
6353

64-
auto hr = fn_aware(2 /*PROCESS_PER_MONITOR_DPI_AWARE*/);
65-
if (SUCCEEDED(hr) || hr == E_ACCESSDENIED) {
66-
return;
67-
}
68-
});
54+
fn_aware(2 /*PROCESS_PER_MONITOR_DPI_AWARE*/);
55+
return 0;
56+
}();
6957
}
7058

7159
}
@@ -286,7 +274,6 @@ bool MessageInput::handle_hardware_mouse_move(const MSLLHOOKSTRUCT& mouse_info)
286274
pending_mouse_y_ += dy;
287275
has_pending_mouse_ = true;
288276

289-
// mouse_lock_follow 模式始终拦截
290277
return true;
291278
}
292279

@@ -398,8 +385,6 @@ LRESULT CALLBACK MessageInput::MouseHookProc(int nCode, WPARAM wParam, LPARAM lP
398385
return 1;
399386
}
400387

401-
// ======================== 目标进程挂起/恢复 ========================
402-
403388
void MessageInput::open_target_process()
404389
{
405390
if (target_process_handle_ || !hwnd_) {
@@ -416,7 +401,10 @@ void MessageInput::open_target_process()
416401
target_process_handle_ = OpenProcess(PROCESS_SUSPEND_RESUME, FALSE, pid);
417402
if (!target_process_handle_) {
418403
LogWarn << "OpenProcess failed" << VAR(pid) << VAR(GetLastError());
404+
return;
419405
}
406+
407+
NtDllHolder::load_library(L"ntdll.dll");
420408
}
421409

422410
void MessageInput::close_target_process()
@@ -428,20 +416,14 @@ void MessageInput::close_target_process()
428416
target_process_handle_ = nullptr;
429417
}
430418

431-
template <typename Fn>
432-
static boost::function<Fn> resolve_nt_function(const std::string& name)
433-
{
434-
return resolve_library_function<NtDllHolder, Fn>(L"ntdll.dll", name);
435-
}
436-
437419
void MessageInput::suspend_target_process()
438420
{
439421
if (!target_process_handle_) {
440422
return;
441423
}
442424

443425
using NtSuspendProcessFn = LONG NTAPI(HANDLE);
444-
static auto fn = resolve_nt_function<NtSuspendProcessFn>("NtSuspendProcess");
426+
static auto fn = NtDllHolder::get_function<NtSuspendProcessFn>("NtSuspendProcess");
445427
if (fn) {
446428
fn(target_process_handle_);
447429
}
@@ -454,14 +436,12 @@ void MessageInput::resume_target_process()
454436
}
455437

456438
using NtResumeProcessFn = LONG NTAPI(HANDLE);
457-
static auto fn = resolve_nt_function<NtResumeProcessFn>("NtResumeProcess");
439+
static auto fn = NtDllHolder::get_function<NtResumeProcessFn>("NtResumeProcess");
458440
if (fn) {
459441
fn(target_process_handle_);
460442
}
461443
}
462444

463-
// ======================== 追踪线程 ========================
464-
465445
void MessageInput::process_pending_mouse_frame()
466446
{
467447
has_pending_mouse_ = false;
@@ -930,8 +910,6 @@ bool MessageInput::scroll(int dx, int dy)
930910
return success;
931911
}
932912

933-
// ======================== MouseLockFollow ========================
934-
935913
bool MessageInput::relative_move(int dx, int dy)
936914
{
937915
if (!mouse_lock_follow_active_) {
@@ -963,17 +941,17 @@ bool MessageInput::relative_move(int dx, int dy)
963941

964942
bool MessageInput::set_mouse_lock_follow(bool enabled)
965943
{
966-
LogInfo << VAR(enabled) << VAR(mouse_lock_follow_active_);
944+
LogInfo << VAR(enabled) << VAR(mouse_lock_follow_active_.load());
967945

968946
if (enabled && !mouse_lock_follow_active_) {
969947
return activate_mouse_lock_follow();
970948
}
971-
else if (!enabled && mouse_lock_follow_active_) {
949+
950+
if (!enabled && mouse_lock_follow_active_) {
972951
deactivate_mouse_lock_follow();
973-
return true;
974952
}
975953

976-
return true; // 已经是目标状态
954+
return true;
977955
}
978956

979957
bool MessageInput::ensure_tracking_thread()
@@ -1026,6 +1004,36 @@ bool MessageInput::ensure_rawinput_window()
10261004
return rawinput_ensure_done_ && rawinput_ensure_ok_;
10271005
}
10281006

1007+
bool MessageInput::compute_window_center_on_cursor(const POINT& cursor, int& out_left, int& out_top)
1008+
{
1009+
RECT client_rect;
1010+
if (!GetClientRect(hwnd_, &client_rect)) {
1011+
LogError << "GetClientRect failed" << VAR(GetLastError());
1012+
return false;
1013+
}
1014+
1015+
int client_w = client_rect.right - client_rect.left;
1016+
int client_h = client_rect.bottom - client_rect.top;
1017+
1018+
POINT client_origin = { 0, 0 };
1019+
if (!ClientToScreen(hwnd_, &client_origin)) {
1020+
LogError << "ClientToScreen failed" << VAR(hwnd_) << VAR(GetLastError());
1021+
return false;
1022+
}
1023+
1024+
RECT win_rect;
1025+
if (!GetWindowRect(hwnd_, &win_rect)) {
1026+
LogError << "GetWindowRect failed" << VAR(hwnd_) << VAR(GetLastError());
1027+
return false;
1028+
}
1029+
1030+
int border_x = client_origin.x - win_rect.left;
1031+
int border_y = client_origin.y - win_rect.top;
1032+
out_left = cursor.x - client_w / 2 - border_x;
1033+
out_top = cursor.y - client_h / 2 - border_y;
1034+
return true;
1035+
}
1036+
10291037
bool MessageInput::activate_mouse_lock_follow()
10301038
{
10311039
LogInfo << "Activating mouse lock follow mode";
@@ -1042,7 +1050,6 @@ bool MessageInput::activate_mouse_lock_follow()
10421050
if (prev_dpi_ctx) SetThreadDpiAwarenessContext(prev_dpi_ctx);
10431051
});
10441052

1045-
// 确保追踪线程在运行
10461053
if (!ensure_tracking_thread()) {
10471054
LogError << "Failed to start mouse tracking thread for mouse lock follow";
10481055
return false;
@@ -1053,7 +1060,6 @@ bool MessageInput::activate_mouse_lock_follow()
10531060
return false;
10541061
}
10551062

1056-
// 保存窗口位置以便恢复
10571063
save_window_pos();
10581064
if (!window_pos_saved_) {
10591065
LogError << "Failed to save window position before activating mouse lock follow" << VAR(hwnd_);
@@ -1066,32 +1072,11 @@ bool MessageInput::activate_mouse_lock_follow()
10661072
return false;
10671073
}
10681074

1069-
RECT client_rect;
1070-
if (!GetClientRect(hwnd_, &client_rect)) {
1071-
LogError << "GetClientRect failed" << VAR(GetLastError());
1075+
int new_left = 0, new_top = 0;
1076+
if (!compute_window_center_on_cursor(cursor, new_left, new_top)) {
10721077
return false;
10731078
}
10741079

1075-
int client_w = client_rect.right - client_rect.left;
1076-
int client_h = client_rect.bottom - client_rect.top;
1077-
1078-
POINT client_origin = { 0, 0 };
1079-
if (!ClientToScreen(hwnd_, &client_origin)) {
1080-
LogError << "ClientToScreen failed" << VAR(hwnd_) << VAR(GetLastError());
1081-
return false;
1082-
}
1083-
RECT win_rect;
1084-
if (!GetWindowRect(hwnd_, &win_rect)) {
1085-
LogError << "GetWindowRect failed" << VAR(hwnd_) << VAR(GetLastError());
1086-
return false;
1087-
}
1088-
int border_x = client_origin.x - win_rect.left;
1089-
int border_y = client_origin.y - win_rect.top;
1090-
1091-
// 将窗口中心对齐到当前光标位置
1092-
int new_left = cursor.x - client_w / 2 - border_x;
1093-
int new_top = cursor.y - client_h / 2 - border_y;
1094-
10951080
bool activated = false;
10961081
bool window_moved = false;
10971082
tracking_stop_generation_ = 0;
@@ -1117,18 +1102,19 @@ bool MessageInput::activate_mouse_lock_follow()
11171102
return false;
11181103
}
11191104
window_moved = true;
1120-
// 等待 SetWindowPos 生效(最多 100ms)
1105+
bool settled = false;
11211106
for (int i = 0; i < 10; ++i) {
11221107
RECT cur;
1123-
if (GetWindowRect(hwnd_, &cur) &&
1124-
std::abs(cur.left - new_left) <= 1 &&
1125-
std::abs(cur.top - new_top) <= 1) {
1108+
if (GetWindowRect(hwnd_, &cur) && std::abs(cur.left - new_left) <= 1 && std::abs(cur.top - new_top) <= 1) {
1109+
settled = true;
11261110
break;
11271111
}
11281112
std::this_thread::sleep_for(std::chrono::milliseconds(10));
11291113
}
1114+
if (!settled) {
1115+
LogWarn << "SetWindowPos did not settle within 100ms" << VAR(hwnd_) << VAR(new_left) << VAR(new_top);
1116+
}
11301117

1131-
// 记录锚点
11321118
lock_anchor_cursor_ = cursor;
11331119
if (!GetWindowRect(hwnd_, &lock_anchor_window_)) {
11341120
LogError << "GetWindowRect failed after mouse lock follow activation move" << VAR(hwnd_) << VAR(GetLastError());
@@ -1137,24 +1123,20 @@ bool MessageInput::activate_mouse_lock_follow()
11371123
lock_offset_x_ = 0;
11381124
lock_offset_y_ = 0;
11391125

1140-
// 发送激活消息
11411126
send_activate();
11421127

1143-
// 清空待处理的鼠标位移
11441128
pending_mouse_x_ = 0;
11451129
pending_mouse_y_ = 0;
11461130
has_pending_mouse_ = false;
11471131
counter_pending_ = 0;
11481132

11491133
mouse_lock_follow_active_ = true;
1150-
1151-
// 设置追踪活跃状态
11521134
s_active_instance_ = this;
11531135
tracking_active_ = true;
11541136
activated = true;
11551137

1156-
LogInfo << "Mouse lock follow activated, anchor cursor=" << lock_anchor_cursor_.x << "," << lock_anchor_cursor_.y
1157-
<< " window=" << lock_anchor_window_.left << "," << lock_anchor_window_.top;
1138+
LogInfo << "Mouse lock follow activated" << VAR(lock_anchor_cursor_.x) << VAR(lock_anchor_cursor_.y)
1139+
<< VAR(lock_anchor_window_.left) << VAR(lock_anchor_window_.top);
11581140
return true;
11591141
}
11601142

@@ -1174,7 +1156,6 @@ void MessageInput::deactivate_mouse_lock_follow()
11741156
stop_window_tracking();
11751157
counter_pending_ = 0;
11761158

1177-
// 恢复窗口位置
11781159
restore_window_pos();
11791160

11801161
// 如果追踪线程是为 lock follow 单独启动的,停止它
@@ -1197,21 +1178,18 @@ void MessageInput::process_mouse_lock_follow_frame()
11971178
lock_offset_x_ += dx;
11981179
lock_offset_y_ += dy;
11991180

1200-
// 目标鼠标位置(绝对锚点策略)
12011181
int mx = lock_anchor_cursor_.x + lock_offset_x_;
12021182
int my = lock_anchor_cursor_.y + lock_offset_y_;
12031183

1204-
// 屏幕边界钳制
12051184
int vsx = GetSystemMetrics(SM_XVIRTUALSCREEN);
12061185
int vsy = GetSystemMetrics(SM_YVIRTUALSCREEN);
12071186
int vsw = GetSystemMetrics(SM_CXVIRTUALSCREEN);
12081187
int vsh = GetSystemMetrics(SM_CYVIRTUALSCREEN);
1209-
mx = std::max(vsx, std::min(mx, vsx + vsw - 1));
1210-
my = std::max(vsy, std::min(my, vsy + vsh - 1));
1188+
mx = std::clamp(mx, vsx, vsx + vsw - 1);
1189+
my = std::clamp(my, vsy, vsy + vsh - 1);
12111190
lock_offset_x_ = mx - lock_anchor_cursor_.x;
12121191
lock_offset_y_ = my - lock_anchor_cursor_.y;
12131192

1214-
// 窗口目标位置
12151193
int new_left = lock_anchor_window_.left + lock_offset_x_;
12161194
int new_top = lock_anchor_window_.top + lock_offset_y_;
12171195

@@ -1231,8 +1209,6 @@ void MessageInput::process_mouse_lock_follow_frame()
12311209
resume_target_process();
12321210
}
12331211

1234-
// ======================== RawInput 对冲 ========================
1235-
12361212
bool MessageInput::create_rawinput_window()
12371213
{
12381214
WNDCLASSEXW wc = {};
@@ -1273,7 +1249,6 @@ void MessageInput::destroy_rawinput_window()
12731249
return;
12741250
}
12751251

1276-
// 取消注册 RawInput
12771252
RAWINPUTDEVICE rid = {};
12781253
rid.usUsagePage = 0x01;
12791254
rid.usUsage = 0x02;

source/MaaWin32ControlUnit/Input/MessageInput.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,13 @@ class MessageInput : public RelativeMoveInput
137137
// 保留首次进入 WithWindowPos 会话前的窗口位置,避免一连串触摸操作反复覆盖原始锚点。
138138
bool window_pos_saved_ = false;
139139

140-
// ======================== MouseLockFollow ========================
141-
// 用于 TPS/FPS 游戏后台锁鼠标场景:窗口始终跟随鼠标,RawInput 对冲阻止游戏感知硬件移动。
142-
143140
bool activate_mouse_lock_follow();
144141
void deactivate_mouse_lock_follow();
145142
bool ensure_tracking_thread();
146143
bool ensure_rawinput_window();
147144
void process_mouse_lock_follow_frame();
145+
bool compute_window_center_on_cursor(const POINT& cursor, int& out_left, int& out_top);
148146

149-
// RawInput 对冲
150147
bool create_rawinput_window();
151148
void destroy_rawinput_window();
152149
void send_counter_move(int raw_dx, int raw_dy);
@@ -163,11 +160,9 @@ class MessageInput : public RelativeMoveInput
163160
bool rawinput_ensure_done_ = false;
164161
bool rawinput_ensure_ok_ = false;
165162

166-
// 模式状态
167-
bool mouse_lock_follow_active_ = false;
163+
std::atomic<bool> mouse_lock_follow_active_ = false;
168164
bool tracking_thread_started_for_lock_follow_ = false;
169165

170-
// 绝对定位锚点
171166
POINT lock_anchor_cursor_ = {};
172167
RECT lock_anchor_window_ = {};
173168
int lock_offset_x_ = 0;

source/modules/MaaFramework.cppm

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,6 @@ export using ::MaaControllerPostTouchDown;
178178
export using ::MaaControllerPostTouchMove;
179179
export using ::MaaControllerPostTouchUp;
180180
export using ::MaaControllerPostRelativeMove;
181-
export using ::MaaControllerPostMouseLockFollow;
182181
export using ::MaaControllerPostScreencap;
183182
export using ::MaaControllerPostScroll;
184183
export using ::MaaControllerPostShell;

0 commit comments

Comments
 (0)