]> git.saurik.com Git - wxWidgets.git/commitdiff
Fix wxFindWindowAtPoint() with nested windows in wxMSW.
authorVadim Zeitlin <vadim@wxwidgets.org>
Thu, 13 Sep 2012 17:12:42 +0000 (17:12 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Thu, 13 Sep 2012 17:12:42 +0000 (17:12 +0000)
Return the deepest child of the window and not the first one as this function
needs to return the window that is at the top of Z-order.

Closes #14591.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72470 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/msw/window.cpp
tests/misc/guifuncs.cpp

index 6bb0616f0b5ea0016a4348202491f78865b67abc..67ee3d37f7859317867ac953cf5a3e61630597b2 100644 (file)
@@ -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);
index ffb339ac1dc530e6feecf49b38e0823c6e66e272..27a04138dd92e8cb92e0bc7618c0f48a1b79b0f3 100644 (file)
@@ -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);
 }