Skip to content

Commit a61391d

Browse files
committed
fix: 修复 Win32 touch_move 不生效问题
fix #763
1 parent 829279e commit a61391d

File tree

4 files changed

+58
-27
lines changed

4 files changed

+58
-27
lines changed

source/MaaWin32ControlUnit/Input/LegacyEventInput.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,15 @@ bool LegacyEventInput::touch_move(int contact, int x, int y, int pressure)
7979
}
8080
// LogInfo << VAR(contact) << VAR(x) << VAR(y) << VAR(pressure) << VAR(point.x) << VAR(point.y) << VAR_VOIDP(hwnd_);
8181

82-
SetCursorPos(point.x, point.y);
82+
// 使用 mouse_event + MOUSEEVENTF_MOVE + MOUSEEVENTF_ABSOLUTE 移动光标
83+
// 需要将屏幕坐标转换为 0-65535 范围的归一化坐标
84+
int screen_width = GetSystemMetrics(SM_CXSCREEN);
85+
int screen_height = GetSystemMetrics(SM_CYSCREEN);
86+
87+
DWORD norm_x = static_cast<DWORD>((point.x * 65535) / screen_width);
88+
DWORD norm_y = static_cast<DWORD>((point.y * 65535) / screen_height);
89+
90+
mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, norm_x, norm_y, 0, 0);
8391

8492
return true;
8593
}

source/MaaWin32ControlUnit/Input/MessageInput.cpp

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,15 @@ void MessageInput::restore_cursor_pos()
6464
}
6565
}
6666

67-
void MessageInput::set_cursor_to_client_pos(int x, int y)
67+
LPARAM MessageInput::prepare_mouse_position(int x, int y)
6868
{
69-
POINT screen_pos = client_to_screen(x, y);
70-
SetCursorPos(screen_pos.x, screen_pos.y);
69+
if (with_cursor_pos_) {
70+
// Genshin 模式:移动真实光标到目标位置
71+
POINT screen_pos = client_to_screen(x, y);
72+
SetCursorPos(screen_pos.x, screen_pos.y);
73+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
74+
}
75+
return MAKELPARAM(x, y);
7176
}
7277

7378
MaaControllerFeature MessageInput::get_features() const
@@ -98,35 +103,42 @@ bool MessageInput::touch_down(int contact, int x, int y, int pressure)
98103
return false;
99104
}
100105

106+
MouseMessageInfo move_info;
107+
if (!contact_to_mouse_move_message(contact, move_info)) {
108+
LogError << VAR(mode_) << VAR(with_cursor_pos_) << "contact out of range" << VAR(contact);
109+
return false;
110+
}
111+
112+
MouseMessageInfo down_info;
113+
if (!contact_to_mouse_down_message(contact, down_info)) {
114+
LogError << VAR(mode_) << VAR(with_cursor_pos_) << "contact out of range" << VAR(contact);
115+
return false;
116+
}
117+
101118
ensure_foreground();
102119

103120
if (block_input_) {
104121
BlockInput(TRUE);
105122
}
106123

107-
// 如果需要管理光标位置,保存当前位置并移动到目标位置
108124
if (with_cursor_pos_) {
109125
save_cursor_pos();
110-
set_cursor_to_client_pos(x, y);
111126
}
112127

113-
// 先发送 MOVE 消息
114-
touch_move(contact, x, y, pressure);
128+
// 准备位置(with_cursor_pos_ 模式下会移动光标)并发送 MOVE 消息
129+
LPARAM lParam = prepare_mouse_position(x, y);
115130

116-
std::this_thread::sleep_for(std::chrono::milliseconds(10));
117-
118-
MouseMessageInfo msg_info;
119-
if (!contact_to_mouse_down_message(contact, msg_info)) {
120-
LogError << VAR(mode_) << VAR(with_cursor_pos_) << "contact out of range" << VAR(contact);
121-
// 错误时恢复光标位置
131+
if (!send_or_post_w(move_info.message, move_info.w_param, lParam)) {
122132
if (with_cursor_pos_) {
123133
restore_cursor_pos();
124134
}
125135
return false;
126136
}
127137

128-
if (!send_or_post_w(msg_info.message, msg_info.w_param, MAKELPARAM(x, y))) {
129-
// 错误时恢复光标位置
138+
std::this_thread::sleep_for(std::chrono::milliseconds(10));
139+
140+
// 发送 DOWN 消息
141+
if (!send_or_post_w(down_info.message, down_info.w_param, lParam)) {
130142
if (with_cursor_pos_) {
131143
restore_cursor_pos();
132144
}
@@ -149,18 +161,16 @@ bool MessageInput::touch_move(int contact, int x, int y, int pressure)
149161
return false;
150162
}
151163

152-
if (with_cursor_pos_) {
153-
// 移动光标到目标位置
154-
set_cursor_to_client_pos(x, y);
155-
}
156-
157164
MouseMessageInfo msg_info;
158165
if (!contact_to_mouse_move_message(contact, msg_info)) {
159166
LogError << VAR(mode_) << VAR(with_cursor_pos_) << "contact out of range" << VAR(contact);
160167
return false;
161168
}
162169

163-
if (!send_or_post_w(msg_info.message, msg_info.w_param, MAKELPARAM(x, y))) {
170+
// 准备位置(with_cursor_pos_ 模式下会移动光标)并发送 MOVE 消息
171+
LPARAM lParam = prepare_mouse_position(x, y);
172+
173+
if (!send_or_post_w(msg_info.message, msg_info.w_param, lParam)) {
164174
return false;
165175
}
166176

@@ -284,10 +294,10 @@ bool MessageInput::scroll(int dx, int dy)
284294
});
285295

286296
if (with_cursor_pos_) {
287-
// 保存当前光标位置
297+
// 保存当前光标位置,并移动到上次记录的位置
288298
save_cursor_pos();
289-
// 移动光标到上次记录的位置
290-
set_cursor_to_client_pos(last_pos_.first, last_pos_.second);
299+
POINT screen_pos = client_to_screen(last_pos_.first, last_pos_.second);
300+
SetCursorPos(screen_pos.x, screen_pos.y);
291301
}
292302

293303
std::this_thread::sleep_for(std::chrono::milliseconds(10));

source/MaaWin32ControlUnit/Input/MessageInput.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,13 @@ class MessageInput : public InputBase
5151
void ensure_foreground();
5252
bool send_or_post_w(UINT message, WPARAM wParam, LPARAM lParam);
5353

54+
// 准备鼠标位置:with_cursor_pos_ 模式下移动真实光标,返回 lParam
55+
LPARAM prepare_mouse_position(int x, int y);
56+
5457
// helpers for with_cursor_pos
5558
POINT client_to_screen(int x, int y);
5659
void save_cursor_pos();
5760
void restore_cursor_pos();
58-
void set_cursor_to_client_pos(int x, int y);
5961

6062
const HWND hwnd_ = nullptr;
6163
const Mode mode_ = Mode::SendMessage;

source/MaaWin32ControlUnit/Input/SeizeInput.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,18 @@ bool SeizeInput::touch_move(int contact, int x, int y, int pressure)
8484
}
8585
// LogInfo << VAR(contact) << VAR(x) << VAR(y) << VAR(pressure) << VAR(point.x) << VAR(point.y) << VAR_VOIDP(hwnd_);
8686

87-
SetCursorPos(point.x, point.y);
87+
// 使用 SendInput + MOUSEEVENTF_MOVE + MOUSEEVENTF_ABSOLUTE 移动光标
88+
// 需要将屏幕坐标转换为 0-65535 范围的归一化坐标
89+
int screen_width = GetSystemMetrics(SM_CXSCREEN);
90+
int screen_height = GetSystemMetrics(SM_CYSCREEN);
91+
92+
INPUT input = {};
93+
input.type = INPUT_MOUSE;
94+
input.mi.dx = static_cast<LONG>((point.x * 65535) / screen_width);
95+
input.mi.dy = static_cast<LONG>((point.y * 65535) / screen_height);
96+
input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
97+
98+
SendInput(1, &input, sizeof(INPUT));
8899

89100
return true;
90101
}

0 commit comments

Comments
 (0)