Другие вопросы здесь не отвечают на вашу часть 2, поэтому я сделаю это:
2. Как Windows это делает? (Мне более любопытно, чем что-либо, но если это не так сложно, может быть, я мог бы реализовать нечто подобное в моей собственной программе?)
Необходимо понять, что даже если у вас открыто несколько десятков окон, в каждом из которых много панелей инструментов, в каждом из которых много элементов и т. Д., При каждом перемещении мыши окна не нужно проверять все .
Windows в основном структурирована в два уровня: есть HWNDs, и именно так Windows сама управляет разделением пространства на рабочем столе; и обычно в каждом HWND есть элемент управления, который управляет его собственным пространством в этом HWND: список, управляющий его собственными элементами списка, элемент управления вкладками, управляющий его собственными вкладками, элемент управления HTML, управляющий его собственным макетом страницы HTML, и так далее. (Или, в вашем случае, код, управляющий примерно 50 прямоугольниками.)
Когда мышь перемещается, Windows сначала определяет правильный HWND для отправки этого WM_MOUSEMOVE. И это происходит путем обхода HWND. HWND хранятся в виде дерева, представляющего содержание, и порядка среди братьев и сестер, представляющих Z-порядок, поэтому Windows может выполнить простой спуск на глубину в это дерево, чтобы найти самый нижний HWND в любой заданной точке. Если вы запустите приложение Spy ++, вы сможете увидеть, как выглядит это дерево HWND. Обратите внимание, что Windows не выполняет полный исчерпывающий обход: например, при обходе окон приложений верхнего уровня, чтобы выяснить, в каком приложении находится точка, как только Windows находит первый HWND верхнего уровня, содержащий точку, она подробно расскажет об этом, полностью игнорируя все другие приложения, которые находятся ниже или после него, и все элементы управления внутри них. Это ключ, который означает, что окна должны проходить только относительно немного HWND, даже если на экране видно много разных изображений.
Как только Windows определяет правильный HWND, она отправляет соответствующее сообщение этому (WM_NCHITTEST, WM_MOUSEMOVE и т. Д.), И затем этот элемент управления также должен сделать то же самое для своего собственного контента. Для списка, содержащего элементы фиксированного размера, определение элемента в конкретной точке может быть таким же простым, как операция деления; или для элемента управления HTML элемент управления может иметь собственный эквивалент «дерева макетов», которое он может использовать для быстрого поиска элемента в этой точке. В вашем случае, циклический просмотр списка прямоугольников может быть вполне нормальным.
Это несколько упрощенная версия: она немного сложнее, чем выше - например. окна не просто для проверки «точка-в-прямоугольник», существуют другие проверки, позволяющие создавать нечетные и прозрачные окна (а также невидимые и отключенные окна); но основная идея происхождения дерева применима.
Другая важная проблема, которую следует помнить, заключается в том, что все это довольно быстро: перемещение мыши происходит в «человеческое время», и современный ЦП может выполнять множество операций за то время, которое требуется мыши для перемещения пары. пикселей на экране. И наконец, обратите внимание, что при перемещении мыши из точки A в точку B на экране мышь не всегда пересекает каждый отдельный пиксель между ними - особенно если вы быстро перемещаете мышь.