MCPcopy Create free account
hub / github.com/AutoHotkey/AutoHotkey / EnumChildFindPoint

Function EnumChildFindPoint

source/script2.cpp:5510–5560  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

5508
5509
5510BOOL 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

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected