| 5508 | |
| 5509 | |
| 5510 | BOOL CALLBACK EnumChildFindPoint(HWND aWnd, LPARAM lParam) |
| 5511 | // This is called by more than one caller. It finds the most appropriate child window that contains |
| 5512 | // the specified point (the point should be in screen coordinates). |
| 5513 | { |
| 5514 | point_and_hwnd_type &pah = *(point_and_hwnd_type *)lParam; // For performance and convenience. |
| 5515 | if (!IsWindowVisible(aWnd) // Omit hidden controls, like Window Spy does. |
| 5516 | || (pah.ignore_disabled_controls && !IsWindowEnabled(aWnd))) // For ControlClick, also omit disabled controls, since testing shows that the OS doesn't post mouse messages to them. |
| 5517 | return TRUE; |
| 5518 | RECT rect; |
| 5519 | if (!GetWindowRect(aWnd, &rect)) |
| 5520 | return TRUE; |
| 5521 | // The given point must be inside aWnd's bounds. Then, if there is no hwnd found yet or if aWnd |
| 5522 | // is entirely contained within the previously found hwnd, update to a "better" found window like |
| 5523 | // Window Spy. This overcomes the limitations of WindowFromPoint() and ChildWindowFromPoint(). |
| 5524 | // The pixel at (left, top) lies inside the control, whereas MSDN says "the pixel at (right, bottom) |
| 5525 | // lies immediately outside the rectangle" -- so use < instead of <= below: |
| 5526 | if (pah.pt.x >= rect.left && pah.pt.x < rect.right && pah.pt.y >= rect.top && pah.pt.y < rect.bottom) |
| 5527 | { |
| 5528 | // If the window's center is closer to the given point, break the tie and have it take |
| 5529 | // precedence. This solves the problem where a particular control from a set of overlapping |
| 5530 | // controls is chosen arbitrarily (based on Z-order) rather than based on something the |
| 5531 | // user would find more intuitive (the control whose center is closest to the mouse): |
| 5532 | double center_x = rect.left + (double)(rect.right - rect.left) / 2; |
| 5533 | double center_y = rect.top + (double)(rect.bottom - rect.top) / 2; |
| 5534 | // Taking the absolute value first is not necessary because it seems that qmathHypot() |
| 5535 | // takes the square root of the sum of the squares, which handles negatives correctly: |
| 5536 | double distance = qmathHypot(pah.pt.x - center_x, pah.pt.y - center_y); |
| 5537 | //double distance = qmathSqrt(qmathPow(pah.pt.x - center_x, 2) + qmathPow(pah.pt.y - center_y, 2)); |
| 5538 | bool update_it = !pah.hwnd_found; |
| 5539 | if (!update_it) |
| 5540 | { |
| 5541 | // If the new window's rect is entirely contained within the old found-window's rect, update |
| 5542 | // even if the distance is greater. Conversely, if the new window's rect entirely encloses |
| 5543 | // the old window's rect, do not update even if the distance is less: |
| 5544 | if (rect.left >= pah.rect_found.left && rect.right <= pah.rect_found.right |
| 5545 | && rect.top >= pah.rect_found.top && rect.bottom <= pah.rect_found.bottom) |
| 5546 | update_it = true; // New is entirely enclosed by old: update to the New. |
| 5547 | else if ( distance < pah.distance && |
| 5548 | (pah.rect_found.left < rect.left || pah.rect_found.right > rect.right |
| 5549 | || pah.rect_found.top < rect.top || pah.rect_found.bottom > rect.bottom) ) |
| 5550 | update_it = true; // New doesn't entirely enclose old and new's center is closer to the point. |
| 5551 | } |
| 5552 | if (update_it) |
| 5553 | { |
| 5554 | pah.hwnd_found = aWnd; |
| 5555 | pah.rect_found = rect; // And at least one caller uses this returned rect. |
| 5556 | pah.distance = distance; |
| 5557 | } |
| 5558 | } |
| 5559 | return TRUE; // Continue enumeration all the way through. |
| 5560 | } |
| 5561 | |
| 5562 | |
| 5563 |
nothing calls this directly
no outgoing calls
no test coverage detected