fixed bugs with setting the client size when the difference between the total and client size changes as the result (e.g. because the scrollbars [dis]appear or the menu bar [un]wraps

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@12934 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2001-12-08 23:13:27 +00:00
parent 8810d43125
commit d4597e138e
6 changed files with 125 additions and 106 deletions

View 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
//

View 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);

View 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();

View 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
// ----------------------------------------------------------------------------

View 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);
RECT rectTotal;
::GetWindowRect(hWnd, &rectTotal);
// 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;
// note that calling GetClientAreaOrigin() takes the toolbar into account
// call GetClientAreaOrigin() to take 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"));
}
wxWindow::DoSetClientSize(width, height);
}
wxSizeEvent event(wxSize(width, height), m_windowId);
event.SetEventObject(this);
(void)GetEventHandler()->ProcessEvent(event);
void wxTopLevelWindowMSW::DoGetClientSize(int *x, int *y) const
{
wxWindow::DoGetClientSize(x, y);
wxPoint pt = GetClientAreaOrigin();
if ( x )
*x -= pt.x;
if ( y )
*y -= pt.y;
}
// ----------------------------------------------------------------------------

View 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();
RECT rect;
::GetClientRect(hWnd, &rect);
RECT rect2;
GetWindowRect(hWnd, &rect2);
// 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;
// If there's a parent, must subtract the parent's top left corner
// since MoveWindow moves relative to the parent
POINT point;
point.x = rect2.left;
point.y = rect2.top;
if ( parent )
// 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++ )
{
::ScreenToClient(hParentWnd, &point);
RECT rectClient;
::GetClientRect(GetHwnd(), &rectClient);
// 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") );
break;
}
int widthClient = width,
heightClient = 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
RECT rectWin;
::GetWindowRect(GetHwnd(), &rectWin);
widthClient += rectWin.right - rectWin.left - rectClient.right;
heightClient += rectWin.bottom - rectWin.top - rectClient.bottom;
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);
}
DoMoveWindow(point.x, point.y, actual_width, actual_height);
wxSizeEvent event(wxSize(width, height), m_windowId);
event.SetEventObject(this);
GetEventHandler()->ProcessEvent(event);
}
// For implementation purposes - sometimes decorations make the client area