X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c3723477cc6149a73a60f5e0a7e0038d45bc2a41..921c65ed3d889117c600387cebb0bce2470cff8e:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 5899ca485a..031585be7c 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -47,6 +47,7 @@ #include "wx/msgdlg.h" #include "wx/settings.h" #include "wx/statbox.h" + #include "wx/sizer.h" #endif #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__) @@ -120,6 +121,7 @@ #endif // everything needed for TrackMouseEvent() #define USE_DEFERRED_SIZING 1 +#define USE_DEFER_BUG_WORKAROUND 1 // --------------------------------------------------------------------------- // global variables @@ -463,6 +465,9 @@ void wxWindowMSW::Init() m_lastMouseY = -1; m_lastMouseEvent = -1; #endif // wxUSE_MOUSEEVENT_HACK + + m_pendingPosition = wxDefaultPosition; + m_pendingSize = wxDefaultSize; } // Destructor @@ -470,12 +475,6 @@ wxWindowMSW::~wxWindowMSW() { m_isBeingDeleted = true; - if (m_windowReserved) - { - delete (wxExtraWindowData*) m_windowReserved; - m_windowReserved = NULL; - } - #ifndef __WXUNIVERSAL__ // VS: make sure there's no wxFrame with last focus set to us: for ( wxWindow *win = GetParent(); win; win = win->GetParent() ) @@ -516,6 +515,7 @@ wxWindowMSW::~wxWindowMSW() } delete m_childrenDisabled; + } // real construction (Init() must have been called before!) @@ -1370,7 +1370,8 @@ void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect) pRect = NULL; } -#ifndef __SMARTPHONE__ + // RedrawWindow not available on SmartPhone or eVC++ 3 +#if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400) UINT flags = RDW_INVALIDATE | RDW_ALLCHILDREN; if ( eraseBack ) flags |= RDW_ERASE; @@ -1451,14 +1452,6 @@ void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip) // Get total size void wxWindowMSW::DoGetSize(int *x, int *y) const { - wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved; - if (extraData && extraData->m_deferring && GetParent() && GetParent()->m_hDWP) - { - *x = extraData->m_size.x; - *y = extraData->m_size.y; - return; - } - RECT rect = wxGetWindowRect(GetHwnd()); if ( x ) @@ -1470,14 +1463,6 @@ void wxWindowMSW::DoGetSize(int *x, int *y) const // Get size *available for subwindows* i.e. excluding menu bar etc. void wxWindowMSW::DoGetClientSize(int *x, int *y) const { - wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved; - if (extraData && extraData->m_deferring && GetParent() && GetParent()->m_hDWP) - { - *x = extraData->m_pos.x; - *y = extraData->m_pos.y; - return; - } - RECT rect = wxGetClientRect(GetHwnd()); if ( x ) @@ -1575,26 +1560,15 @@ void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height) HDWP hdwp = parent && !IsTopLevel() ? (HDWP)parent->m_hDWP : NULL; #else HDWP hdwp = 0; -#endif +#endif wxMoveWindowDeferred(hdwp, this, GetHwnd(), x, y, width, height); - if ( hdwp ) - { - // Store the size so we can report it accurately - wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved; - if (!extraData) - { - extraData = new wxExtraWindowData; - m_windowReserved = (void*) extraData; - } - extraData->m_pos = wxPoint(x, y); - extraData->m_size = wxSize(width, height); - extraData->m_deferring = true; - +#if USE_DEFERRED_SIZING + if ( parent ) // hdwp must be updated as it may have been changed parent->m_hDWP = (WXHANDLE)hdwp; - } +#endif } // set the size of the window: if the dimensions are positive, just use them, @@ -1609,9 +1583,28 @@ void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags) { // get the current size and position... int currentX, currentY; + int currentW, currentH; + +#if USE_DEFER_BUG_WORKAROUND + currentX = m_pendingPosition.x; + if (currentX == wxDefaultCoord) + GetPosition(¤tX, NULL); + + currentY = m_pendingPosition.y; + if (currentY == wxDefaultCoord) + GetPosition(NULL, ¤tY); + + currentW = m_pendingSize.x; + if (currentW == wxDefaultCoord) + GetSize(¤tW, NULL); + + currentH = m_pendingSize.y; + if (currentH == wxDefaultCoord) + GetSize(NULL, ¤tH); +#else GetPosition(¤tX, ¤tY); - int currentW,currentH; GetSize(¤tW, ¤tH); +#endif // ... and don't do anything (avoiding flicker) if it's already ok if ( x == currentX && y == currentY && @@ -1661,6 +1654,24 @@ void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags) } } +#if USE_DEFER_BUG_WORKAROUND + // We don't actually use the hdwp here, but we need to know whether to + // save the pending dimensions or not. This isn't done in DoMoveWindow + // (where the hdwp is used) because some controls have thier own + // DoMoveWindow so it is easier to catch it here. + HDWP hdwp = GetParent() && !IsTopLevel() ? (HDWP)GetParent()->m_hDWP : NULL; + if (hdwp) + { + m_pendingPosition = wxPoint(x, y); + m_pendingSize = wxSize(width, height); + } + else + { + m_pendingPosition = wxDefaultPosition; + m_pendingSize = wxDefaultSize; + } +#endif + DoMoveWindow(x, y, width, height); } @@ -1760,7 +1771,7 @@ void wxWindowMSW::GetTextExtent(const wxString& string, SIZE sizeRect; TEXTMETRIC tm; - GetTextExtentPoint(hdc, string, string.length(), &sizeRect); + ::GetTextExtentPoint32(hdc, string, string.length(), &sizeRect); GetTextMetrics(hdc, &tm); if ( x ) @@ -2341,6 +2352,31 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l break; #endif // !__WXWINCE__ + case WM_WINDOWPOSCHANGED: + { + WINDOWPOS *lpPos = (WINDOWPOS *)lParam; + + if ( !(lpPos->flags & SWP_NOSIZE) ) + { + RECT rc; + ::GetClientRect(GetHwnd(), &rc); + + AutoHRGN hrgnClient(::CreateRectRgnIndirect(&rc)); + AutoHRGN hrgnNew(::CreateRectRgn(lpPos->x, lpPos->y, + lpPos->cx, lpPos->cy)); + AutoHRGN hrgn(::CreateRectRgn(0, 0, 0, 0)); + + // we need to invalidate any new exposed areas here + // to force them to repaint + if ( ::CombineRgn(hrgn, hrgnNew, hrgnClient, RGN_DIFF) != NULLREGION ) + ::InvalidateRgn(GetHwnd(), hrgn, TRUE); + if ( ::CombineRgn(hrgn, hrgnClient, hrgnNew, RGN_DIFF) != NULLREGION ) + ::InvalidateRgn(GetHwnd(), hrgn, TRUE); + + } + } + break; + #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) case WM_ACTIVATEAPP: // This implicitly sends a wxEVT_ACTIVATE_APP event @@ -3542,7 +3578,7 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), if ( !::GetCursorPosWinCE(&pt)) #else if ( !::GetCursorPos(&pt) ) -#endif +#endif { wxLogLastError(wxT("GetCursorPos")); } @@ -3896,6 +3932,7 @@ extern wxCOLORMAP *wxGetStdColourMap() // we want to avoid Windows' "help" and for this we need to have a // reference bitmap which can tell us what the RGB values change // to. + wxLogNull logNo; // suppress error if we couldn't load the bitmap wxBitmap stdColourBitmap(_T("wxBITMAP_STD_COLOURS")); if ( stdColourBitmap.Ok() ) { @@ -4108,6 +4145,10 @@ bool wxWindowMSW::HandlePrintClient(WXHDC hDC) // // also note that in this case lParam == PRF_CLIENT but we're // clearly expected to paint the background and nothing else! + + if ( IsTopLevel() || InheritsBackgroundColour() ) + return false; + for ( wxWindow *win = GetParent(); win; win = win->GetParent() ) { if ( win->MSWPrintChild(hDC, (wxWindow *)this) ) @@ -4162,8 +4203,6 @@ bool wxWindowMSW::HandleMoving(wxRect& rect) bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam) { - // when we resize this window, its children are probably going to be - // repositioned as well, prepare to use DeferWindowPos() for them #if USE_DEFERRED_SIZING // when we resize this window, its children are probably going to be // repositioned as well, prepare to use DeferWindowPos() for them @@ -4175,13 +4214,13 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam) numChildren ++; } - // Protect against valid m_hDWP being overwritten + // Protect against valid m_hDWP being overwritten bool useDefer = false; if ( numChildren > 1 ) { if (!m_hDWP) - { + { m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren); if ( !m_hDWP ) { @@ -4234,32 +4273,24 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam) // may have depending on what the users EVT_SIZE handler does...) HDWP hDWP = (HDWP)m_hDWP; m_hDWP = NULL; - + // do put all child controls in place at once if ( !::EndDeferWindowPos(hDWP) ) { wxLogLastError(_T("EndDeferWindowPos")); } - // Seems to be a bug in DeferWindowPos such that going from (a) to (b) to (a) - // doesn't work (omits last position/size). So check if there's a disparity, - // and correct. +#if USE_DEFER_BUG_WORKAROUND + // Reset our children's pending pos/size values. for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext() ) { wxWindow *child = node->GetData(); - wxExtraWindowData* extraData = (wxExtraWindowData*) child->m_windowReserved; - if (extraData && extraData->m_deferring) - { - wxPoint pos = child->GetPosition(); - - if (extraData->m_pos != pos) - child->Move(extraData->m_pos); - - extraData->m_deferring = false; - } + child->m_pendingPosition = wxDefaultPosition; + child->m_pendingSize = wxDefaultSize; } +#endif } #endif @@ -5999,7 +6030,7 @@ bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam) #endif // wxUSE_HOTKEY // Moves a window by deferred method or normal method -bool wxMoveWindowDeferred(HDWP& hdwp, wxWindow* win, HWND hWnd, int x, int y, int width, int height) +bool wxMoveWindowDeferred(HDWP& hdwp, wxWindowBase* win, HWND hWnd, int x, int y, int width, int height) { if ( hdwp ) {