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
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,
// 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);
}
}