]> git.saurik.com Git - wxWidgets.git/commitdiff
generate the mouse click events for the static controls
authorVadim Zeitlin <vadim@wxwidgets.org>
Thu, 9 May 2002 00:28:57 +0000 (00:28 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Thu, 9 May 2002 00:28:57 +0000 (00:28 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15459 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/msw/window.cpp

index bae64cf40387242b0f26eaaee8134277405c8989..a452a8a00ea9aa247dd5fe249b5ee5ecc50199a6 100644 (file)
@@ -178,6 +178,9 @@ static void TranslateKbdEventToMouse(wxWindowMSW *win,
 // get the text metrics for the current font
 static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
 
+// find the window for the mouse event at the specified position
+static wxWindowMSW *FindWindowForMouseEvent(wxWindow *win, int *x, int *y);
+
 // wrapper around BringWindowToTop() API
 static inline void wxBringWindowToTop(HWND hwnd)
 {
@@ -2378,68 +2381,43 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
         case WM_MBUTTONDOWN:
         case WM_MBUTTONUP:
         case WM_MBUTTONDBLCLK:
-         {
-                processed = FALSE;
+            {
 #ifdef __WXMICROWIN__
                 // MicroWindows seems to ignore the fact that a window is
                 // disabled. So catch mouse events and throw them away if
                 // necessary.
                 wxWindowMSW* win = this;
-                while (win)
+                for ( ;; )
                 {
                     if (!win->IsEnabled())
                     {
                         processed = TRUE;
                         break;
                     }
+
                     win = win->GetParent();
-                    if (win && win->IsTopLevel())
+                    if ( !win || win->IsTopLevel() )
                         break;
                 }
-#endif // __WXMICROWIN__
+
                 if (!processed)
+#endif // __WXMICROWIN__
                 {
-                    if (message == WM_LBUTTONDOWN && AcceptsFocus())
+                    // VZ: why do we need it here? DefWindowProc() is supposed
+                    //     to do this for us anyhow
+                    if ( message == WM_LBUTTONDOWN && AcceptsFocus() )
                         SetFocus();
-                     processed = HandleMouseEvent(message,
-                                         GET_X_LPARAM(lParam),
-                                         GET_Y_LPARAM(lParam),
-                                                  wParam);
-                }
-                break;
-         }
 
-#ifdef __WXMICROWIN__
-        case WM_NCLBUTTONDOWN:
-        case WM_NCLBUTTONUP:
-        case WM_NCLBUTTONDBLCLK:
-        case WM_NCRBUTTONDOWN:
-        case WM_NCRBUTTONUP:
-        case WM_NCRBUTTONDBLCLK:
-#if 0
-        case WM_NCMBUTTONDOWN:
-        case WM_NCMBUTTONUP:
-        case WM_NCMBUTTONDBLCLK:
-#endif
-            {
-                // MicroWindows seems to ignore the fact that a window
-                // is disabled. So catch mouse events and throw them away if necessary.
-                processed = FALSE;
-                wxWindowMSW* win = this;
-                while (win)
-                {
-                    if (!win->IsEnabled())
-                    {
-                        processed = TRUE;
-                        break;
-                    }
-                    win = win->GetParent();
-                    if (win && win->IsTopLevel())
-                        break;
+                    int x = GET_X_LPARAM(lParam),
+                        y = GET_Y_LPARAM(lParam);
+
+                    // redirect the event to a static control if necessary
+                    wxWindow *win = FindWindowForMouseEvent(this, &x, &y);
+
+                    processed = win->HandleMouseEvent(message, x, y, wParam);
                 }
-                break;
             }
-#endif // __WXMICROWIN__
+            break;
 
 #ifdef MM_JOY1MOVE
         case MM_JOY1MOVE:
@@ -3982,6 +3960,64 @@ void wxWindowMSW::InitMouseEvent(wxMouseEvent& event,
 #endif // wxUSE_MOUSEEVENT_HACK
 }
 
+// Windows doesn't send the mouse events to the static controls (which are
+// transparent in the sense that their WM_NCHITTEST handler returns
+// HTTRANSPARENT) at all but we want all controls to receive the mouse events
+// and so we manually check if we don't have a child window under mouse and if
+// we do, send the event to it instead of the window Windows had sent WM_XXX
+// to.
+//
+// Notice that this is not done for the mouse move events because this could
+// (would?) be too slow, but only for clicks which means that the static texts
+// still don't get move, enter nor leave events.
+static wxWindowMSW *FindWindowForMouseEvent(wxWindow *win, int *x, int *y)
+{
+    wxCHECK_MSG( x && y, win, _T("NULL pointer in FindWindowForMouseEvent") );
+
+    // first try to find a non transparent child: this allows us to send events
+    // to a static text which is inside a static box, for example
+    POINT pt = { *x, *y };
+    HWND hwnd = GetHwndOf(win),
+         hwndUnderMouse;
+
+#ifdef __WIN32__
+    hwndUnderMouse = ::ChildWindowFromPointEx
+                       (
+                        hwnd,
+                        pt,
+                        CWP_SKIPINVISIBLE   |
+                        CWP_SKIPDISABLED    |
+                        CWP_SKIPTRANSPARENT
+                       );
+
+    if ( !hwndUnderMouse || hwndUnderMouse == hwnd )
+#endif // __WIN32__
+    {
+        // now try any child window at all
+        hwndUnderMouse = ::ChildWindowFromPoint(hwnd, pt);
+    }
+
+    // check that we have a child window which is susceptible to receive mouse
+    // events: for this it must be shown and enabled
+    if ( hwndUnderMouse &&
+            hwndUnderMouse != hwnd &&
+                ::IsWindowVisible(hwndUnderMouse) &&
+                    ::IsWindowEnabled(hwndUnderMouse) )
+    {
+        wxWindow *winUnderMouse = wxFindWinFromHandle((WXHWND)hwndUnderMouse);
+        if ( winUnderMouse )
+        {
+            // translate the mouse coords to the other window coords
+            win->ClientToScreen(x, y);
+            winUnderMouse->ScreenToClient(x, y);
+
+            win = winUnderMouse;
+        }
+    }
+
+    return win;
+}
+
 bool wxWindowMSW::HandleMouseEvent(WXUINT msg, int x, int y, WXUINT flags)
 {
     // the mouse events take consecutive IDs from WM_MOUSEFIRST to