diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 6bb0616f0b..67ee3d37f7 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -7215,9 +7215,21 @@ wxWindow* wxFindWindowAtPoint(const wxPoint& pt) { // WindowFromPoint() ignores the disabled children but we're supposed // to take them into account, so check if we have a child at this - // coordinate. - ::ScreenToClient(hWnd, &pt2); - hWnd = ::ChildWindowFromPointEx(hWnd, pt2, CWP_SKIPINVISIBLE); + // coordinate using ChildWindowFromPointEx(). + for ( ;; ) + { + pt2.x = pt.x; + pt2.y = pt.y; + ::ScreenToClient(hWnd, &pt2); + HWND child = ::ChildWindowFromPointEx(hWnd, pt2, CWP_SKIPINVISIBLE); + if ( child == hWnd || !child ) + break; + + // ChildWindowFromPointEx() only examines the immediate children + // but we want to get the deepest (top in Z-order) one, so continue + // iterating for as long as it finds anything. + hWnd = child; + } } return wxGetWindowFromHWND((WXHWND)hWnd); diff --git a/tests/misc/guifuncs.cpp b/tests/misc/guifuncs.cpp index ffb339ac1d..27a04138dd 100644 --- a/tests/misc/guifuncs.cpp +++ b/tests/misc/guifuncs.cpp @@ -177,6 +177,18 @@ void MiscGUIFuncsTestCase::FindWindowAtPoint() wxFindWindowAtPoint(parent->ClientToScreen(wxPoint(11, 91))) ); + btn2->Show(); + wxWindow* btn3 = new wxButton(btn2, wxID_ANY, "3", wxPoint(0, 0)); + btn3->Disable(); + CPPUNIT_ASSERT_EQUAL_MESSAGE + ( + "Point over recursive disabled child controls corresponds to deepest child", + btn3, + wxFindWindowAtPoint(parent->ClientToScreen(wxPoint(11, 91))) + ); + wxASSERT(wxFindWindowAtPoint(parent->ClientToScreen(wxPoint(11, 91))) == btn3); + wxDELETE(btn1); + wxDELETE(btn3); // delete child before parent wxDELETE(btn2); }