]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
another segfault fix
[wxWidgets.git] / src / msw / window.cpp
index 5b4cbc254a5ddd644903b793c51d0ed15afbed27..dd98fe4c43069099616a4337cc7b332a6cb9a9c3 100644 (file)
@@ -1493,40 +1493,65 @@ void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags)
 
 void wxWindowMSW::DoSetClientSize(int width, int height)
 {
-    wxWindow *parent = GetParent();
-    HWND hWnd = GetHwnd();
-    HWND hParentWnd = (HWND) 0;
-    if ( parent )
-        hParentWnd = (HWND) parent->GetHWND();
+    // setting the client size is less obvious than it it could have been
+    // because in the result of changing the total size the window scrollbar
+    // may [dis]appear and/or its menubar may [un]wrap and so the client size
+    // will not be correct as the difference between the total and client size
+    // changes - so we keep changing it until we get it right
+    //
+    // normally this loop shouldn't take more than 2 iterations (usually 1 but
+    // if scrollbars [dis]appear as the result of the first call, then 2) but
+    // just to be on the safe side we check for it instead of making it an
+    // "infinite" loop (i.e. leaving break inside as the only way to get out)
+    for ( int i = 0; i < 3; i++ )
+    {
+        RECT rectClient;
+        ::GetClientRect(GetHwnd(), &rectClient);
 
-    RECT rect;
-    ::GetClientRect(hWnd, &rect);
+        // if the size is already ok, stop here (rectClient.left = top = 0)
+        if ( rectClient.right == width && rectClient.bottom == height )
+        {
+            break;
+        }
 
-    RECT rect2;
-    GetWindowRect(hWnd, &rect2);
+        if ( i == 2 )
+        {
+            // how did it happen? maybe OnSize() handler does something really
+            // strange in this class?
+            wxFAIL_MSG( _T("logic error in DoSetClientSize") );
 
-    // Find the difference between the entire window (title bar and all)
-    // and the client area; add this to the new client size to move the
-    // window
-    int actual_width = rect2.right - rect2.left - rect.right + width;
-    int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
+            break;
+        }
 
-    // If there's a parent, must subtract the parent's top left corner
-    // since MoveWindow moves relative to the parent
+        int widthClient = width,
+            heightClient = height;
 
-    POINT point;
-    point.x = rect2.left;
-    point.y = rect2.top;
-    if ( parent )
-    {
-        ::ScreenToClient(hParentWnd, &point);
-    }
+        // Find the difference between the entire window (title bar and all)
+        // and the client area; add this to the new client size to move the
+        // window
+        RECT rectWin;
+        ::GetWindowRect(GetHwnd(), &rectWin);
 
-    DoMoveWindow(point.x, point.y, actual_width, actual_height);
+        widthClient += rectWin.right - rectWin.left - rectClient.right;
+        heightClient += rectWin.bottom - rectWin.top - rectClient.bottom;
 
-    wxSizeEvent event(wxSize(width, height), m_windowId);
-    event.SetEventObject(this);
-    GetEventHandler()->ProcessEvent(event);
+        POINT point;
+        point.x = rectWin.left;
+        point.y = rectWin.top;
+
+        // MoveWindow positions the child windows relative to the parent, so
+        // adjust if necessary
+        if ( !IsTopLevel() )
+        {
+            wxWindow *parent = GetParent();
+            if ( parent )
+            {
+                ::ScreenToClient(GetHwndOf(parent), &point);
+            }
+        }
+
+        DoMoveWindow(point.x, point.y, widthClient, heightClient);
+    }
 }
 
 // For implementation purposes - sometimes decorations make the client area
@@ -3257,7 +3282,11 @@ bool wxWindowMSW::HandleSysColorChange()
     wxSysColourChangedEvent event;
     event.SetEventObject(this);
 
-    return GetEventHandler()->ProcessEvent(event);
+    (void)GetEventHandler()->ProcessEvent(event);
+
+    // always let the system carry on the default processing to allow the
+    // native controls to react to the colours update
+    return FALSE;
 }
 
 bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush,
@@ -3324,19 +3353,35 @@ bool wxWindowMSW::HandleQueryNewPalette()
 // Responds to colour changes: passes event on to children.
 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& event)
 {
-    wxNode *node = GetChildren().First();
+    wxWindowList::Node *node = GetChildren().GetFirst();
     while ( node )
     {
-        // Only propagate to non-top-level windows
-        wxWindow *win = (wxWindow *)node->Data();
-        if ( win->GetParent() )
+        // Only propagate to non-top-level windows because Windows already
+        // sends this event to all top-level ones
+        wxWindow *win = node->GetData();
+        if ( !win->IsTopLevel() )
         {
-            wxSysColourChangedEvent event2;
-            event.m_eventObject = win;
-            win->GetEventHandler()->ProcessEvent(event2);
+            // we need to send the real WM_SYSCOLORCHANGE and not just trigger
+            // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
+            // the standard controls
+            ::SendMessage(GetHwndOf(win), WM_SYSCOLORCHANGE, 0, 0);
         }
 
-        node = node->Next();
+        node = node->GetNext();
+    }
+
+    // update the colours we use if they were not set explicitly by the user:
+    // this must be done or OnCtlColor() would continue to use the old colours
+    if ( !m_hasFgCol )
+    {
+        m_foregroundColour = wxSystemSettings::
+                                GetSystemColour(wxSYS_COLOUR_WINDOWTEXT);
+    }
+
+    if ( !m_hasBgCol )
+    {
+        m_backgroundColour = wxSystemSettings::
+                                GetSystemColour(wxSYS_COLOUR_BTNFACE);
     }
 }