|
11 | 11 |
|
12 | 12 | logger = Logger.get_logger(__name__) |
13 | 13 |
|
| 14 | + |
14 | 15 | class PostMessageInteraction(BaseInteraction): |
15 | 16 |
|
16 | 17 | def __init__(self, capture: BaseCaptureMethod, hwnd_window): |
@@ -72,6 +73,7 @@ def input_text(self, text, activate=True): |
72 | 73 | def move(self, x, y, down_btn=0): |
73 | 74 | long_pos = self.update_mouse_pos(x, y, True) |
74 | 75 | self.post(win32con.WM_MOUSEMOVE, down_btn, long_pos) |
| 76 | + return long_pos |
75 | 77 |
|
76 | 78 | def scroll(self, x, y, scroll_amount): |
77 | 79 | self.try_activate() |
@@ -137,9 +139,10 @@ def try_activate(self): |
137 | 139 | def click(self, x=-1, y=-1, move_back=False, name=None, down_time=0.01, move=True, key="left"): |
138 | 140 | super().click(x, y, name=name) |
139 | 141 | if move: |
140 | | - self.move(x, y) |
| 142 | + long_position = self.move(x, y) |
141 | 143 | time.sleep(down_time) |
142 | | - long_position = self.update_mouse_pos(x, y, activate=not move) |
| 144 | + else: |
| 145 | + long_position = self.update_mouse_pos(x, y, activate=True) |
143 | 146 |
|
144 | 147 | if key == "left": |
145 | 148 | btn_down = win32con.WM_LBUTTONDOWN |
@@ -181,75 +184,52 @@ def mouse_down(self, x=-1, y=-1, name=None, key="left"): |
181 | 184 |
|
182 | 185 | def update_mouse_pos(self, x, y, activate=True): |
183 | 186 | self.try_activate() |
184 | | - |
| 187 | + |
185 | 188 | base_hwnd = self.hwnd_window.top_hwnd if self.hwnd_window.top_hwnd else self.hwnd_window.hwnd |
186 | | - |
| 189 | + |
187 | 190 | if x == -1 or y == -1: |
188 | 191 | x, y = getattr(self, 'bg_mouse_pos', (0, 0)) |
189 | 192 | else: |
190 | 193 | x, y = self.hwnd_window.get_top_window_cords(x, y) |
191 | 194 | self.bg_mouse_pos = (x, y) |
192 | | - |
| 195 | + |
193 | 196 | try: |
194 | 197 | abs_x, abs_y = win32gui.ClientToScreen(base_hwnd, (int(x), int(y))) |
195 | | - |
196 | | - # Validate that the click position falls within the boundary of base_hwnd. |
197 | | - # If not, search through the available hwnds list for one that contains it. |
| 198 | + |
| 199 | + target_hwnd = base_hwnd |
198 | 200 | hwnds = getattr(self.hwnd_window, 'hwnds', []) |
199 | | - if hwnds and len(hwnds) > 1: |
| 201 | + for hwnd_info in hwnds: |
| 202 | + candidate = hwnd_info[0] |
| 203 | + if not win32gui.IsWindow(candidate): |
| 204 | + continue |
200 | 205 | try: |
201 | | - base_rect = win32gui.GetWindowRect(base_hwnd) |
202 | | - in_boundary = base_rect[0] <= abs_x < base_rect[2] and base_rect[1] <= abs_y < base_rect[3] |
203 | | - if not in_boundary: |
204 | | - for hwnd_info in hwnds: |
205 | | - candidate = hwnd_info[0] |
206 | | - if candidate == base_hwnd or not win32gui.IsWindow(candidate): |
207 | | - continue |
208 | | - try: |
209 | | - rect = win32gui.GetWindowRect(candidate) |
210 | | - if rect[0] <= abs_x < rect[2] and rect[1] <= abs_y < rect[3]: |
211 | | - logger.debug( |
212 | | - f'update_mouse_pos click ({abs_x},{abs_y}) outside base_hwnd {base_hwnd} rect {base_rect}, switching to hwnd {candidate} rect {rect}') |
213 | | - base_hwnd = candidate |
214 | | - # Recompute abs coords relative to the new base_hwnd |
215 | | - local_candidate_x = hwnd_info[4] if len(hwnd_info) > 4 else 0 |
216 | | - local_candidate_y = hwnd_info[5] if len(hwnd_info) > 5 else 0 |
217 | | - # x,y are in original bg-window coords; translate to candidate client coords |
218 | | - orig_base_info = next((w for w in hwnds if w[0] == (self.hwnd_window.top_hwnd or self.hwnd_window.hwnd)), None) |
219 | | - if orig_base_info: |
220 | | - dx = orig_base_info[4] - local_candidate_x |
221 | | - dy = orig_base_info[5] - local_candidate_y |
222 | | - abs_x, abs_y = win32gui.ClientToScreen(candidate, (int(x + dx), int(y + dy))) |
223 | | - break |
224 | | - except Exception: |
225 | | - continue |
| 206 | + left = hwnd_info[4] |
| 207 | + top = hwnd_info[5] |
| 208 | + right = left + hwnd_info[2] |
| 209 | + bottom = top + hwnd_info[3] |
| 210 | + if left <= abs_x < right and top <= abs_y < bottom: |
| 211 | + target_hwnd = candidate |
| 212 | + break |
226 | 213 | except Exception: |
227 | | - pass |
228 | | - |
229 | | - found_child = None |
230 | | - if self.hwnd_window.top_hwnd and self.hwnd_window.top_hwnd != self.hwnd_window.hwnd: |
231 | | - def find_child_at_point(child, _): |
232 | | - nonlocal found_child |
233 | | - if win32gui.IsWindowVisible(child): |
234 | | - rect = win32gui.GetWindowRect(child) |
235 | | - if rect[0] <= abs_x < rect[2] and rect[1] <= abs_y < rect[3]: |
236 | | - found_child = child |
237 | | - return False |
238 | | - return True |
239 | | - |
240 | | - try: |
241 | | - win32gui.EnumChildWindows(base_hwnd, find_child_at_point, None) |
242 | | - except Exception: pass |
243 | | - logger.debug(f'found_child {found_child}') |
244 | | - |
245 | | - target_hwnd = found_child if found_child else base_hwnd |
| 214 | + continue |
246 | 215 | self._dynamic_target_hwnd = target_hwnd |
247 | | - |
| 216 | + |
248 | 217 | local_x, local_y = win32gui.ScreenToClient(target_hwnd, (abs_x, abs_y)) |
249 | | - |
250 | | - # logger.debug(f'mouse_pos dynamically aimed at {target_hwnd} ({win32gui.GetClassName(target_hwnd)}): {local_x}, {local_y}') |
| 218 | + |
| 219 | + hwnd_descriptions = [] |
| 220 | + for index, hwnd_info in enumerate(hwnds): |
| 221 | + candidate = hwnd_info[0] |
| 222 | + try: |
| 223 | + class_name = win32gui.GetClassName(candidate) if win32gui.IsWindow(candidate) else '<invalid>' |
| 224 | + except Exception as e: |
| 225 | + class_name = f'<class error: {e}>' |
| 226 | + hwnd_descriptions.append(f'{index}:{candidate}({class_name})') |
| 227 | + logger.debug( |
| 228 | + f'hwnd_window hwnds hwnd={self.hwnd_window.hwnd} top_hwnd={self.hwnd_window.top_hwnd}: {hwnd_descriptions}') |
| 229 | + logger.debug( |
| 230 | + f'mouse_pos dynamically aimed at {target_hwnd} ({win32gui.GetClassName(target_hwnd)}): {local_x}, {local_y}') |
251 | 231 | return win32api.MAKELONG(local_x, local_y) |
252 | | - |
| 232 | + |
253 | 233 | except Exception as e: |
254 | 234 | logger.error(f'update_mouse_pos conversion error targeting {base_hwnd}', e) |
255 | 235 | self._dynamic_target_hwnd = base_hwnd |
|
0 commit comments