| 10681 | |
| 10682 | |
| 10683 | VarSizeType Script::ScriptGetCaret(VarTypeType aVarType, char *aBuf) |
| 10684 | { |
| 10685 | if (!aBuf) |
| 10686 | return MAX_NUMBER_LENGTH; |
| 10687 | |
| 10688 | // These static variables are used to keep the X and Y coordinates in sync with each other, as a snapshot |
| 10689 | // of where the caret was at one precise instant in time. This is because the X and Y vars are resolved |
| 10690 | // separately by the script, and due to split second timing, they might otherwise not be accurate with |
| 10691 | // respect to each other. This method also helps performance since it avoids unnecessary calls to |
| 10692 | // ATTACH_THREAD_INPUT. |
| 10693 | static HWND sForeWinPrev = NULL; |
| 10694 | static DWORD sTimestamp = GetTickCount(); |
| 10695 | static POINT sPoint; |
| 10696 | static BOOL sResult; |
| 10697 | |
| 10698 | // I believe only the foreground window can have a caret position due to relationship with focused control. |
| 10699 | HWND target_window = GetForegroundWindow(); // Variable must be named target_window for ATTACH_THREAD_INPUT. |
| 10700 | if (!target_window) // No window is in the foreground, report blank coordinate. |
| 10701 | { |
| 10702 | *aBuf = '\0'; |
| 10703 | return 0; |
| 10704 | } |
| 10705 | |
| 10706 | DWORD now_tick = GetTickCount(); |
| 10707 | |
| 10708 | if (target_window != sForeWinPrev || now_tick - sTimestamp > 5) // Different window or too much time has passed. |
| 10709 | { |
| 10710 | // Otherwise: |
| 10711 | ATTACH_THREAD_INPUT // au3: Doesn't work without attaching. |
| 10712 | sResult = GetCaretPos(&sPoint); |
| 10713 | HWND focused_control = GetFocus(); // Also relies on threads being attached. |
| 10714 | DETACH_THREAD_INPUT |
| 10715 | if (!sResult) |
| 10716 | { |
| 10717 | *aBuf = '\0'; |
| 10718 | return 0; |
| 10719 | } |
| 10720 | ClientToScreen(focused_control ? focused_control : target_window, &sPoint); |
| 10721 | if (!(g.CoordMode & COORD_MODE_CARET)) // Using the default, which is coordinates relative to window. |
| 10722 | { |
| 10723 | // Convert screen coordinates to window coordinates: |
| 10724 | RECT rect; |
| 10725 | GetWindowRect(target_window, &rect); |
| 10726 | sPoint.x -= rect.left; |
| 10727 | sPoint.y -= rect.top; |
| 10728 | } |
| 10729 | // Now that all failure conditions have been checked, update static variables for the next caller: |
| 10730 | sForeWinPrev = target_window; |
| 10731 | sTimestamp = now_tick; |
| 10732 | } |
| 10733 | else // Same window and recent enough, but did prior call fail? If so, provide a blank result like the prior. |
| 10734 | { |
| 10735 | if (!sResult) |
| 10736 | { |
| 10737 | *aBuf = '\0'; |
| 10738 | return 0; |
| 10739 | } |
| 10740 | } |