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 // implement the geometry-related methods for a top level window
virtual void DoSetClientSize(int width, int height); virtual void DoSetClientSize(int width, int height);
virtual void DoGetClientSize(int *width, int *height) const;
// get the MSW window flags corresponding to wxWindows ones // get the MSW window flags corresponding to wxWindows ones
// //

View File

@@ -47,9 +47,9 @@ enum
wxFULLSCREEN_NOSTATUSBAR = 0x0004, wxFULLSCREEN_NOSTATUSBAR = 0x0004,
wxFULLSCREEN_NOBORDER = 0x0008, wxFULLSCREEN_NOBORDER = 0x0008,
wxFULLSCREEN_NOCAPTION = 0x0010, wxFULLSCREEN_NOCAPTION = 0x0010,
wxFULLSCREEN_ALL = wxFULLSCREEN_NOMENUBAR | wxFULLSCREEN_NOTOOLBAR | wxFULLSCREEN_ALL = wxFULLSCREEN_NOMENUBAR | wxFULLSCREEN_NOTOOLBAR |
wxFULLSCREEN_NOSTATUSBAR | wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOSTATUSBAR | wxFULLSCREEN_NOBORDER |
wxFULLSCREEN_NOCAPTION wxFULLSCREEN_NOCAPTION
}; };
@@ -105,7 +105,7 @@ public:
// maximize the window to cover entire screen // maximize the window to cover entire screen
virtual bool ShowFullScreen(bool show, long style = wxFULLSCREEN_ALL) = 0; virtual bool ShowFullScreen(bool show, long style = wxFULLSCREEN_ALL) = 0;
// return TRUE if the frame is in fullscreen mode // return TRUE if the frame is in fullscreen mode
virtual bool IsFullScreen() const = 0; virtual bool IsFullScreen() const = 0;
@@ -122,7 +122,7 @@ public:
bool Iconized() const { return IsIconized(); } bool Iconized() const { return IsIconized(); }
#endif // WXWIN_COMPATIBILITY_2 #endif // WXWIN_COMPATIBILITY_2
#ifdef __WXUNIVERSAL__ #ifdef __WXUNIVERSAL__
// move/resize the frame interactively, i.e. let the user do it // move/resize the frame interactively, i.e. let the user do it
virtual void InteractiveMove(int flags = wxINTERACTIVE_MOVE); virtual void InteractiveMove(int flags = wxINTERACTIVE_MOVE);

View File

@@ -148,12 +148,13 @@ wxPoint wxFrameBase::GetClientAreaOrigin() const
wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin(); wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin();
#if wxUSE_TOOLBAR #if wxUSE_TOOLBAR
if ( GetToolBar() && GetToolBar()->IsShown() ) wxToolBar *toolbar = GetToolBar();
if ( toolbar && toolbar->IsShown() )
{ {
int w, h; int w, h;
GetToolBar()->GetSize(& w, & h); toolbar->GetSize(&w, &h);
if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL ) if ( toolbar->GetWindowStyleFlag() & wxTB_VERTICAL )
{ {
pt.x += w; pt.x += w;
} }
@@ -186,7 +187,7 @@ bool wxFrameBase::ProcessCommand(int id)
{ {
if (!item->IsEnabled()) if (!item->IsEnabled())
return TRUE; return TRUE;
if (item->IsCheckable()) if (item->IsCheckable())
{ {
item->Toggle(); item->Toggle();

View File

@@ -142,30 +142,9 @@ wxFrame::~wxFrame()
DeleteAllBars(); DeleteAllBars();
} }
// Get size *available for subwindows* i.e. excluding menu bar, toolbar etc. // ----------------------------------------------------------------------------
void wxFrame::DoGetClientSize(int *x, int *y) const // wxFrame client size calculations
{ // ----------------------------------------------------------------------------
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;
}
void wxFrame::DoSetClientSize(int width, int height) void wxFrame::DoSetClientSize(int width, int height)
{ {
@@ -181,6 +160,24 @@ void wxFrame::DoSetClientSize(int width, int height)
wxTopLevelWindow::DoSetClientSize(width, 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 // wxFrame: various geometry-related functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -234,7 +231,7 @@ wxStatusBar *wxFrame::OnCreateStatusBar(int number,
void wxFrame::PositionStatusBar() void wxFrame::PositionStatusBar()
{ {
if ( !m_frameStatusBar ) if ( !m_frameStatusBar || !m_frameStatusBar->IsShown() )
return; return;
int w, h; int w, h;
@@ -459,36 +456,40 @@ wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& nam
void wxFrame::PositionToolBar() void wxFrame::PositionToolBar()
{ {
RECT rect; wxToolBar *toolbar = GetToolBar();
::GetClientRect(GetHwnd(), &rect); 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 wxUSE_STATUSBAR
if ( GetStatusBar() ) wxStatusBar *statbar = GetStatusBar();
{ if ( statbar && statbar->IsShown() )
int statusX, statusY; {
GetStatusBar()->GetClientSize(&statusX, &statusY); height -= statbar->GetClientSize().y;
rect.bottom -= statusY; }
}
#endif // wxUSE_STATUSBAR #endif // wxUSE_STATUSBAR
if ( GetToolBar() && GetToolBar()->IsShown() )
{
int tw, th; 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 else
{ {
tw = rect.right; tw = width;
} }
// Use the 'real' MSW position here // use the 'real' MSW position here, don't offset relativly to the
GetToolBar()->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS); // client area origin
toolbar->SetSize(0, 0, tw, th, wxSIZE_NO_ADJUSTMENTS);
} }
} }
#endif // wxUSE_TOOLBAR #endif // wxUSE_TOOLBAR
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -387,39 +387,30 @@ wxTopLevelWindowMSW::~wxTopLevelWindowMSW()
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxTopLevelWindowMSW geometry // wxTopLevelWindowMSW client size
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxTopLevelWindowMSW::DoSetClientSize(int width, int height) void wxTopLevelWindowMSW::DoSetClientSize(int width, int height)
{ {
HWND hWnd = GetHwnd(); // call GetClientAreaOrigin() to take the toolbar into account
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
wxPoint pt = GetClientAreaOrigin(); wxPoint pt = GetClientAreaOrigin();
width += pt.x; width += pt.x;
height += pt.y; height += pt.y;
if ( !::MoveWindow(hWnd, rectTotal.left, rectTotal.top, wxWindow::DoSetClientSize(width, height);
width, height, TRUE /* redraw */) ) }
{
wxLogLastError(_T("MoveWindow"));
}
wxSizeEvent event(wxSize(width, height), m_windowId); void wxTopLevelWindowMSW::DoGetClientSize(int *x, int *y) const
event.SetEventObject(this); {
(void)GetEventHandler()->ProcessEvent(event); 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) void wxWindowMSW::DoSetClientSize(int width, int height)
{ {
wxWindow *parent = GetParent(); // setting the client size is less obvious than it it could have been
HWND hWnd = GetHwnd(); // because in the result of changing the total size the window scrollbar
HWND hParentWnd = (HWND) 0; // may [dis]appear and/or its menubar may [un]wrap and so the client size
if ( parent ) // will not be correct as the difference between the total and client size
hParentWnd = (HWND) parent->GetHWND(); // changes - so we keep changing it until we get it right
//
RECT rect; // normally this loop shouldn't take more than 2 iterations (usually 1 but
::GetClientRect(hWnd, &rect); // 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
RECT rect2; // "infinite" loop (i.e. leaving break inside as the only way to get out)
GetWindowRect(hWnd, &rect2); for ( int i = 0; i < 3; i++ )
// 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 )
{ {
::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 // For implementation purposes - sometimes decorations make the client area