]> git.saurik.com Git - wxWidgets.git/commitdiff
fixed bugs with setting the client size when the difference between the total and...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 8 Dec 2001 23:13:27 +0000 (23:13 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 8 Dec 2001 23:13:27 +0000 (23:13 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@12934 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/toplevel.h
include/wx/toplevel.h
src/common/framecmn.cpp
src/msw/frame.cpp
src/msw/toplevel.cpp
src/msw/window.cpp

index 66c81cfb453dd2861cfb081c5a033517e5c1e8b2..f6a42ff4b7701b4445f6379088d4d94b576a0965 100644 (file)
@@ -90,6 +90,7 @@ protected:
 
     // implement the geometry-related methods for a top level window
     virtual void DoSetClientSize(int width, int height);
+    virtual void DoGetClientSize(int *width, int *height) const;
 
     // get the MSW window flags corresponding to wxWindows ones
     //
index 9eb6f10f0c1426893224433f33288600031d75a5..64a1c964a0df543ede533060c083cd925073b7d9 100644 (file)
@@ -47,9 +47,9 @@ enum
     wxFULLSCREEN_NOSTATUSBAR = 0x0004,
     wxFULLSCREEN_NOBORDER    = 0x0008,
     wxFULLSCREEN_NOCAPTION   = 0x0010,
-    
-    wxFULLSCREEN_ALL         = wxFULLSCREEN_NOMENUBAR | wxFULLSCREEN_NOTOOLBAR | 
-                               wxFULLSCREEN_NOSTATUSBAR | wxFULLSCREEN_NOBORDER | 
+
+    wxFULLSCREEN_ALL         = wxFULLSCREEN_NOMENUBAR | wxFULLSCREEN_NOTOOLBAR |
+                               wxFULLSCREEN_NOSTATUSBAR | wxFULLSCREEN_NOBORDER |
                                wxFULLSCREEN_NOCAPTION
 };
 
@@ -105,7 +105,7 @@ public:
 
     // maximize the window to cover entire screen
     virtual bool ShowFullScreen(bool show, long style = wxFULLSCREEN_ALL) = 0;
-    
+
     // return TRUE if the frame is in fullscreen mode
     virtual bool IsFullScreen() const = 0;
 
@@ -122,7 +122,7 @@ public:
     bool Iconized() const { return IsIconized(); }
 #endif // WXWIN_COMPATIBILITY_2
 
-    
+
 #ifdef __WXUNIVERSAL__
     // move/resize the frame interactively, i.e. let the user do it
     virtual void InteractiveMove(int flags = wxINTERACTIVE_MOVE);
index fc7b2f413af0aeca6f1a6aaabd0e82c28e05a66f..7b067ddf0dda3d3585e91b4b4e72623a57089a29 100644 (file)
@@ -148,12 +148,13 @@ wxPoint wxFrameBase::GetClientAreaOrigin() const
     wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin();
 
 #if wxUSE_TOOLBAR
-    if ( GetToolBar() && GetToolBar()->IsShown() )
+    wxToolBar *toolbar = GetToolBar();
+    if ( toolbar && toolbar->IsShown() )
     {
         int w, h;
-        GetToolBar()->GetSize(& w, & h);
+        toolbar->GetSize(&w, &h);
 
-        if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
+        if ( toolbar->GetWindowStyleFlag() & wxTB_VERTICAL )
         {
             pt.x += w;
         }
@@ -186,7 +187,7 @@ bool wxFrameBase::ProcessCommand(int id)
     {
         if (!item->IsEnabled())
             return TRUE;
-            
+
         if (item->IsCheckable())
         {
             item->Toggle();
index d15747b1ea96bfbfdbe1e46cc890928b7a1cf575..814f3bd2544317516a62ef0abd0eebe12b660bcb 100644 (file)
@@ -142,30 +142,9 @@ wxFrame::~wxFrame()
     DeleteAllBars();
 }
 
-// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
-void wxFrame::DoGetClientSize(int *x, int *y) const
-{
-  RECT rect;
-  ::GetClientRect(GetHwnd(), &rect);
-
-#if wxUSE_STATUSBAR
-  if ( GetStatusBar() && GetStatusBar()->IsShown() )
-  {
-    int statusX, statusY;
-    GetStatusBar()->GetClientSize(&statusX, &statusY);
-    rect.bottom -= statusY;
-  }
-#endif // wxUSE_STATUSBAR
-
-  wxPoint pt(GetClientAreaOrigin());
-  rect.bottom -= pt.y;
-  rect.right -= pt.x;
-
-  if ( x )
-    *x = rect.right;
-  if ( y )
-    *y = rect.bottom;
-}
+// ----------------------------------------------------------------------------
+// wxFrame client size calculations
+// ----------------------------------------------------------------------------
 
 void wxFrame::DoSetClientSize(int width, int height)
 {
@@ -181,6 +160,24 @@ void wxFrame::DoSetClientSize(int width, int height)
     wxTopLevelWindow::DoSetClientSize(width, height);
 }
 
+// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc.
+void wxFrame::DoGetClientSize(int *x, int *y) const
+{
+    wxTopLevelWindow::DoGetClientSize(x, y);
+
+#if wxUSE_STATUSBAR
+    // adjust client area height to take the status bar into account
+    if ( y )
+    {
+        wxStatusBar *statbar = GetStatusBar();
+        if ( statbar && statbar->IsShown() )
+        {
+            *y -= statbar->GetClientSize().y;
+        }
+    }
+#endif // wxUSE_STATUSBAR
+}
+
 // ----------------------------------------------------------------------------
 // wxFrame: various geometry-related functions
 // ----------------------------------------------------------------------------
@@ -234,7 +231,7 @@ wxStatusBar *wxFrame::OnCreateStatusBar(int number,
 
 void wxFrame::PositionStatusBar()
 {
-    if ( !m_frameStatusBar )
+    if ( !m_frameStatusBar || !m_frameStatusBar->IsShown() )
         return;
 
     int w, h;
@@ -459,36 +456,40 @@ wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& nam
 
 void wxFrame::PositionToolBar()
 {
-    RECT rect;
-    ::GetClientRect(GetHwnd(), &rect);
+    wxToolBar *toolbar = GetToolBar();
+    if ( toolbar && toolbar->IsShown() )
+    {
+        // don't call our (or even wxTopLevelWindow) version because we want
+        // the real (full) client area size, not excluding the tool/status bar
+        int width, height;
+        wxWindow::DoGetClientSize(&width, &height);
 
 #if wxUSE_STATUSBAR
-    if ( GetStatusBar() )
-    {
-        int statusX, statusY;
-        GetStatusBar()->GetClientSize(&statusX, &statusY);
-        rect.bottom -= statusY;
-    }
+        wxStatusBar *statbar = GetStatusBar();
+        if ( statbar && statbar->IsShown() )
+        {
+            height -= statbar->GetClientSize().y;
+        }
 #endif // wxUSE_STATUSBAR
 
-    if ( GetToolBar() && GetToolBar()->IsShown() )
-    {
         int tw, th;
-        GetToolBar()->GetSize(&tw, &th);
+        toolbar->GetSize(&tw, &th);
 
-        if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
+        if ( toolbar->GetWindowStyleFlag() & wxTB_VERTICAL )
         {
-            th = rect.bottom;
+            th = height;
         }
         else
         {
-            tw = rect.right;
+            tw = width;
         }
 
-        // Use the 'real' MSW position here
-        GetToolBar()->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS);
+        // use the 'real' MSW position here, don't offset relativly to the
+        // client area origin
+        toolbar->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS);
     }
 }
+
 #endif // wxUSE_TOOLBAR
 
 // ----------------------------------------------------------------------------
index a7b917f9f112a95a58380147ff72a91930bb289f..9aacc560173886664a59185f5c239b9ad794a003 100644 (file)
@@ -387,39 +387,30 @@ wxTopLevelWindowMSW::~wxTopLevelWindowMSW()
 }
 
 // ----------------------------------------------------------------------------
-// wxTopLevelWindowMSW geometry
+// wxTopLevelWindowMSW client size
 // ----------------------------------------------------------------------------
 
 void wxTopLevelWindowMSW::DoSetClientSize(int width, int height)
 {
-    HWND hWnd = GetHwnd();
-
-    RECT rectClient;
-    ::GetClientRect(hWnd, &rectClient);
+    // call GetClientAreaOrigin() to take the toolbar into account
+    wxPoint pt = GetClientAreaOrigin();
+    width += pt.x;
+    height += pt.y;
 
-    RECT rectTotal;
-    ::GetWindowRect(hWnd, &rectTotal);
+    wxWindow::DoSetClientSize(width, height);
+}
 
-    // 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
-    width += rectTotal.right - rectTotal.left - rectClient.right;
-    height += rectTotal.bottom - rectTotal.top - rectClient.bottom;
+void wxTopLevelWindowMSW::DoGetClientSize(int *x, int *y) const
+{
+    wxWindow::DoGetClientSize(x, y);
 
-    // note that calling GetClientAreaOrigin() takes the toolbar into account
     wxPoint pt = GetClientAreaOrigin();
-    width += pt.x;
-    height += pt.y;
 
-    if ( !::MoveWindow(hWnd, rectTotal.left, rectTotal.top,
-                       width, height, TRUE /* redraw */) )
-    {
-        wxLogLastError(_T("MoveWindow"));
-    }
+    if ( x )
+        *x -= pt.x;
 
-    wxSizeEvent event(wxSize(width, height), m_windowId);
-    event.SetEventObject(this);
-    (void)GetEventHandler()->ProcessEvent(event);
+    if ( y )
+        *y -= pt.y;
 }
 
 // ----------------------------------------------------------------------------
index 2979f857d53402b70a0413ec1c853225fed2ad18..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