]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
added GetControlBounds for accessing contrl.rect
[wxWidgets.git] / src / msw / window.cpp
index 3864f654d423865f9a86d24e43310c62bee0ed03..7b171f9f7cc9c4d11ec8c01ef07129881ab0c8e4 100644 (file)
 #define SIF_TRACKPOS 16
 #endif
 
+#if wxUSE_MOUSEWHEEL
+    #ifndef WM_MOUSEWHEEL
+        #define WM_MOUSEWHEEL           0x020A
+    #endif
+    #ifndef WHEEL_DELTA
+        #define WHEEL_DELTA             120
+    #endif
+    #ifndef SPI_GETWHEELSCROLLLINES
+        #define SPI_GETWHEELSCROLLLINES 104
+    #endif
+#endif
+
+
 // ---------------------------------------------------------------------------
 // global variables
 // ---------------------------------------------------------------------------
@@ -275,12 +288,27 @@ wxWindow::~wxWindow()
     m_isBeingDeleted = TRUE;
 
     MSWDetachWindowMenu();
+    
+    // VS: make sure there's no wxFrame with last focus set to us:
+    for (wxWindow *win = GetParent(); win; win = win->GetParent())
+    {
+        wxFrame *frame = wxDynamicCast(win, wxFrame);
+        if ( frame )
+        {
+            if ( frame->GetLastFocus() == this )
+                frame->SetLastFocus((wxWindow*)NULL);
+            break;
+        }
+    }
+
+    // VS: destroy children first and _then_ detach *this from its parent.
+    //     If we'd do it the other way around, children wouldn't be able
+    //     find their parent frame (see above).
+    DestroyChildren();
 
     if ( m_parent )
         m_parent->RemoveChild(this);
 
-    DestroyChildren();
-
     if ( m_hWnd )
     {
         // VZ: test temp removed to understand what really happens here
@@ -366,7 +394,7 @@ wxWindow *wxWindowBase::FindFocus()
     HWND hWnd = ::GetFocus();
     if ( hWnd )
     {
-        return wxFindWinFromHandle((WXHWND) hWnd);
+        return wxGetWindowFromHWND((WXHWND)hWnd);
     }
 
     return NULL;
@@ -383,7 +411,7 @@ bool wxWindow::Enable(bool enable)
 
     // VZ: no, this is a bad idea: imagine that you have a dialog with some
     //     disabled controls and disable it - you really wouldn't like the
-    //     disabled controls eb reenabled too when you reenable the dialog!
+    //     disabled controls be reenabled too when you reenable the dialog!
 #if 0
     wxWindowList::Node *node = GetChildren().GetFirst();
     while ( node )
@@ -1910,6 +1938,12 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
                                         wParam);
             break;
 
+#if wxUSE_MOUSEWHEEL
+        case WM_MOUSEWHEEL:
+            processed = HandleMouseWheel(wParam, lParam);
+            break;
+#endif
+
         case WM_LBUTTONDOWN:
            // set focus to this window
            if (AcceptsFocus())
@@ -2182,36 +2216,55 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
                 rc.result = TRUE;
             }
             break;
+
 #ifdef __WIN32__
         case WM_HELP:
-        {
-            HELPINFO* info = (HELPINFO*) lParam;
-            // Don't yet process menu help events, just windows
-            if (info->iContextType == HELPINFO_WINDOW)
             {
-                wxWindow* subjectOfHelp = this;
-                bool eventProcessed = FALSE;
-                while (subjectOfHelp && !eventProcessed)
+                HELPINFO* info = (HELPINFO*) lParam;
+                // Don't yet process menu help events, just windows
+                if (info->iContextType == HELPINFO_WINDOW)
+                {
+                    wxWindow* subjectOfHelp = this;
+                    bool eventProcessed = FALSE;
+                    while (subjectOfHelp && !eventProcessed)
+                    {
+                        wxHelpEvent helpEvent(wxEVT_HELP,
+                                              subjectOfHelp->GetId(),
+                                              wxPoint(info->MousePos.x,
+                                              info->MousePos.y) );
+                        helpEvent.SetEventObject(this);
+                        eventProcessed =
+                            GetEventHandler()->ProcessEvent(helpEvent);
+
+                        // Go up the window hierarchy until the event is
+                        // handled (or not)
+                        subjectOfHelp = subjectOfHelp->GetParent();
+                    }
+
+                    processed = eventProcessed;
+                }
+                else if (info->iContextType == HELPINFO_MENUITEM)
                 {
-                    wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), wxPoint(info->MousePos.x, info->MousePos.y) ) ; // info->iCtrlId);
+                    wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId);
                     helpEvent.SetEventObject(this);
-                    eventProcessed = GetEventHandler()->ProcessEvent(helpEvent);
+                    processed = GetEventHandler()->ProcessEvent(helpEvent);
 
-                    // Go up the window hierarchy until the event is handled (or not)
-                    subjectOfHelp = subjectOfHelp->GetParent();
                 }
-                processed = eventProcessed;
+                //else: processed is already FALSE
             }
-            else if (info->iContextType == HELPINFO_MENUITEM)
+            break;
+
+        case WM_CONTEXTMENU:
             {
-                wxHelpEvent helpEvent(wxEVT_HELP, info->iCtrlId) ;
-                helpEvent.SetEventObject(this);
-                processed = GetEventHandler()->ProcessEvent(helpEvent);
+                // we don't convert from screen to client coordinates as
+                // the event may be handled by a parent window
+                wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+
+                wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
+                processed = GetEventHandler()->ProcessEvent(evtCtx);
             }
-            else processed = FALSE;
             break;
-        }
-#endif
+#endif // __WIN32__
     }
 
     if ( !processed )
@@ -2464,11 +2517,10 @@ bool wxWindow::MSWCreate(int id,
     {
         int controlId = 0;
         if ( style & WS_CHILD )
-          {
             controlId = id;
-            // all child windows should clip their siblings
-            // style |= /* WS_CLIPSIBLINGS */ ;
-          }
+
+        if ( GetWindowStyleFlag() & wxCLIP_SIBLINGS )
+          style |= WS_CLIPSIBLINGS;
 
         wxString className(wclass);
         if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE )
@@ -2880,19 +2932,20 @@ bool wxWindow::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct)
 
         wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
 
-        // prepare to call OnDrawItem()
-        wxDC dc;
-        dc.SetHDC((WXHDC)pDrawStruct->hDC, FALSE);
+        // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
+        // the DC from being released
+        wxDCTemp dc((WXHDC)pDrawStruct->hDC);
         wxRect rect(pDrawStruct->rcItem.left, pDrawStruct->rcItem.top,
                     pDrawStruct->rcItem.right - pDrawStruct->rcItem.left,
                     pDrawStruct->rcItem.bottom - pDrawStruct->rcItem.top);
 
         return pMenuItem->OnDrawItem
-                          (
-                            dc, rect,
-                            (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction,
-                            (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
-                          );
+               (
+                dc,
+                rect,
+                (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction,
+                (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
+               );
     }
 
     wxWindow *item = FindItem(id);
@@ -3060,9 +3113,8 @@ bool wxWindow::HandleEraseBkgnd(WXHDC hdc)
     if ( ::IsIconic(GetHwnd()) )
         return TRUE;
 
-    wxDC dc;
+    wxDCTemp dc(hdc);
 
-    dc.SetHDC(hdc);
     dc.SetWindow(this);
     dc.BeginDrawing();
 
@@ -3071,8 +3123,9 @@ bool wxWindow::HandleEraseBkgnd(WXHDC hdc)
     bool rc = GetEventHandler()->ProcessEvent(event);
 
     dc.EndDrawing();
+
+    // must be called manually as ~wxDC doesn't do anything for wxDCTemp
     dc.SelectOldObjects(hdc);
-    dc.SetHDC((WXHDC) NULL);
 
     return rc;
 }
@@ -3336,7 +3389,7 @@ bool wxWindow::HandleMouseMove(int x, int y, WXUINT flags)
     if ( (m_lastMouseEvent == wxEVT_RIGHT_DOWN ||
           m_lastMouseEvent == wxEVT_LEFT_DOWN ||
           m_lastMouseEvent == wxEVT_MIDDLE_DOWN) &&
-         (m_lastMouseX == event.m_x && m_lastMouseY == event.m_y) )
+         (m_lastMouseX == x && m_lastMouseY == y) )
     {
         m_lastMouseEvent = wxEVT_MOTION;
 
@@ -3347,6 +3400,46 @@ bool wxWindow::HandleMouseMove(int x, int y, WXUINT flags)
     return HandleMouseEvent(WM_MOUSEMOVE, x, y, flags);
 }
 
+
+bool wxWindow::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
+{
+#if wxUSE_MOUSEWHEEL
+    wxMouseEvent event(wxEVT_MOUSEWHEEL);
+    InitMouseEvent(event,
+                   GET_X_LPARAM(lParam),
+                   GET_Y_LPARAM(lParam),
+                   LOWORD(wParam));
+    event.m_wheelRotation = (short)HIWORD(wParam);
+    event.m_wheelDelta = WHEEL_DELTA;
+
+#ifdef __WIN32__
+    static int s_linesPerRotation = -1;
+    if ( s_linesPerRotation == -1 )
+    {
+        if ( !::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
+                                     &s_linesPerRotation, 0))
+        {
+            // this is not supposed to happen
+            wxLogLastError(_T("SystemParametersInfo(GETWHEELSCROLLLINES)"));
+
+            // the default is 3, so use it if SystemParametersInfo() failed
+            s_linesPerRotation = 3;
+        }
+    }
+#else // Win16
+    // no SystemParametersInfo() under Win16
+    static const int s_linesPerRotation = 3;
+#endif
+
+    event.m_linesPerAction = s_linesPerRotation;
+    return GetEventHandler()->ProcessEvent(event);
+
+#else
+    return FALSE;
+#endif
+}
+
+
 // ---------------------------------------------------------------------------
 // keyboard handling
 // ---------------------------------------------------------------------------
@@ -3862,24 +3955,37 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
         win = wxFindWinFromHandle((WXHWND)hwnd);
         if ( !win )
         {
-            // the radiobox pointer is stored in GWL_USERDATA only under Win32
+            // all these hacks only work under Win32 anyhow
 #ifdef __WIN32__
+
+#if wxUSE_RADIOBOX
             // native radiobuttons return DLGC_RADIOBUTTON here and for any
             // wxWindow class which overrides WM_GETDLGCODE processing to
             // do it as well, win would be already non NULL
-            if ( ::SendMessage((HWND)hwnd, WM_GETDLGCODE,
-                               0, 0) & DLGC_RADIOBUTTON )
+            if ( ::SendMessage(hwnd, WM_GETDLGCODE, 0, 0) & DLGC_RADIOBUTTON )
             {
                 win = (wxWindow *)::GetWindowLong(hwnd, GWL_USERDATA);
             }
-            else
+            //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
+#endif // wxUSE_RADIOBOX
+
+            // spin control text buddy window should be mapped to spin ctrl
+            // itself so try it too
+#if wxUSE_SPINCTRL
+            if ( !win )
+            {
+                win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd);
+            }
+#endif // wxUSE_SPINCTRL
+
 #endif // Win32
+
+            if ( !win )
             {
                 // hwnd is not a wxWindow, try its parent next below
                 hwnd = ::GetParent(hwnd);
             }
         }
-        //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
     }
 
     while ( hwnd && !win )
@@ -3916,8 +4022,9 @@ void wxSetKeyboardHook(bool doIt)
     else
     {
         UnhookWindowsHookEx(wxTheKeyboardHook);
-               // avoids warning about statement with no effect (FreeProcInstance
-               // doesn't do anything under Win32)
+
+        // avoids warning about statement with no effect (FreeProcInstance
+        // doesn't do anything under Win32)
 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__)
         FreeProcInstance(wxTheKeyboardHookProc);
 #endif
@@ -4098,6 +4205,7 @@ const char *wxGetMessageName(int message)
         case 0x0207: return "WM_MBUTTONDOWN";
         case 0x0208: return "WM_MBUTTONUP";
         case 0x0209: return "WM_MBUTTONDBLCLK";
+        case 0x020A: return "WM_MOUSEWHEEL";
         case 0x0210: return "WM_PARENTNOTIFY";
         case 0x0211: return "WM_ENTERMENULOOP";
         case 0x0212: return "WM_EXITMENULOOP";