]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
another segfault fix
[wxWidgets.git] / src / msw / window.cpp
index 775c7bb684ad804ebfed1930654cf9379c3d92ae..dd98fe4c43069099616a4337cc7b332a6cb9a9c3 100644 (file)
@@ -825,36 +825,23 @@ int wxWindowMSW::GetScrollThumb(int orient) const
 
 void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
 {
 
 void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh)
 {
-#if defined(__WIN95__)
-    SCROLLINFO info;
-    int dir;
+    HWND hWnd = GetHwnd();
+    wxCHECK_RET( hWnd, _T("SetScrollPos: no HWND") );
 
 
-    if ( orient == wxHORIZONTAL ) {
-        dir = SB_HORZ;
-    } else {
-        dir = SB_VERT;
-    }
+    int dir = orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
 
 
+#if defined(__WIN95__)
+    SCROLLINFO info;
     info.cbSize = sizeof(SCROLLINFO);
     info.nPage = 0;
     info.nMin = 0;
     info.nPos = pos;
     info.fMask = SIF_POS;
 
     info.cbSize = sizeof(SCROLLINFO);
     info.nPage = 0;
     info.nMin = 0;
     info.nPos = pos;
     info.fMask = SIF_POS;
 
-    HWND hWnd = GetHwnd();
-    if ( hWnd )
-        ::SetScrollInfo(hWnd, dir, &info, refresh);
-#else
-    int wOrient;
-    if ( orient == wxHORIZONTAL )
-        wOrient = SB_HORZ;
-    else
-        wOrient = SB_VERT;
-
-    HWND hWnd = GetHwnd();
-    if ( hWnd )
-        ::SetScrollPos(hWnd, wOrient, pos, refresh);
-#endif
+    ::SetScrollInfo(hWnd, dir, &info, refresh);
+#else // !__WIN95__
+    ::SetScrollPos(hWnd, dir, pos, refresh);
+#endif // __WIN95__/!__WIN95__
 }
 
 // New function that will replace some of the above.
 }
 
 // New function that will replace some of the above.
@@ -1233,7 +1220,9 @@ void wxWindowMSW::Clear()
 
 static inline void SendSetRedraw(HWND hwnd, bool on)
 {
 
 static inline void SendSetRedraw(HWND hwnd, bool on)
 {
+#ifndef __WXMICROWIN__
     ::SendMessage(hwnd, WM_SETREDRAW, (WPARAM)on, 0);
     ::SendMessage(hwnd, WM_SETREDRAW, (WPARAM)on, 0);
+#endif
 }
 
 void wxWindowMSW::Freeze()
 }
 
 void wxWindowMSW::Freeze()
@@ -1504,40 +1493,65 @@ void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags)
 
 void wxWindowMSW::DoSetClientSize(int width, int height)
 {
 
 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;
+        }
+
+        if ( i == 2 )
+        {
+            // how did it happen? maybe OnSize() handler does something really
+            // strange in this class?
+            wxFAIL_MSG( _T("logic error in DoSetClientSize") );
 
 
-    RECT rect2;
-    GetWindowRect(hWnd, &rect2);
+            break;
+        }
 
 
-    // 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;
+        int widthClient = width,
+            heightClient = height;
 
 
-    // If there's a parent, must subtract the parent's top left corner
-    // since MoveWindow moves relative to the parent
+        // 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);
 
 
-    POINT point;
-    point.x = rect2.left;
-    point.y = rect2.top;
-    if ( parent )
-    {
-        ::ScreenToClient(hParentWnd, &point);
-    }
+        widthClient += rectWin.right - rectWin.left - rectClient.right;
+        heightClient += rectWin.bottom - rectWin.top - rectClient.bottom;
 
 
-    DoMoveWindow(point.x, point.y, actual_width, actual_height);
+        POINT point;
+        point.x = rectWin.left;
+        point.y = rectWin.top;
 
 
-    wxSizeEvent event(wxSize(width, height), m_windowId);
-    event.SetEventObject(this);
-    GetEventHandler()->ProcessEvent(event);
+        // 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
 }
 
 // For implementation purposes - sometimes decorations make the client area
@@ -3268,7 +3282,11 @@ bool wxWindowMSW::HandleSysColorChange()
     wxSysColourChangedEvent event;
     event.SetEventObject(this);
 
     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,
 }
 
 bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush,
@@ -3335,19 +3353,35 @@ bool wxWindowMSW::HandleQueryNewPalette()
 // Responds to colour changes: passes event on to children.
 void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& event)
 {
 // 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 )
     {
     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);
     }
 }
 
     }
 }
 
@@ -3534,17 +3568,19 @@ bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
 #endif // wxUSE_MENUS_NATIVE
 
     wxWindow *win = NULL;
 #endif // wxUSE_MENUS_NATIVE
 
     wxWindow *win = NULL;
-    if ( cmd == 0 || cmd == 1 ) // menu or accel - use id
+
+    // first try to find it from HWND - this works even with the broken
+    // programs using the same ids for different controls
+    if ( control )
     {
     {
-        // must cast to a signed type before comparing with other ids!
-        win = FindItem((signed short)id);
+        win = wxFindWinFromHandle(control);
     }
 
     }
 
-    if ( !win && control )
+    // try the id
+    if ( !win )
     {
     {
-        // find it from HWND - this works even with the broken programs using
-        // the same ids for different controls
-        win = wxFindWinFromHandle(control);
+        // must cast to a signed type before comparing with other ids!
+        win = FindItem((signed short)id);
     }
 
     if ( win )
     }
 
     if ( win )
@@ -4288,11 +4324,13 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
         // FIXME: this is clearly not the best way to do it but I think we'll
         //        need to change HWND <-> wxWindow code more heavily than I can
         //        do it now to fix it
         // FIXME: this is clearly not the best way to do it but I think we'll
         //        need to change HWND <-> wxWindow code more heavily than I can
         //        do it now to fix it
+#ifndef __WXMICROWIN__
         if ( ::GetWindow(hwnd, GW_OWNER) )
         {
             // it's a dialog box, don't go upwards
             break;
         }
         if ( ::GetWindow(hwnd, GW_OWNER) )
         {
             // it's a dialog box, don't go upwards
             break;
         }
+#endif
 
         hwnd = ::GetParent(hwnd);
         win = wxFindWinFromHandle((WXHWND)hwnd);
 
         hwnd = ::GetParent(hwnd);
         win = wxFindWinFromHandle((WXHWND)hwnd);