]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
Fix to preserve alpha channel in Rotate90
[wxWidgets.git] / src / msw / window.cpp
index f0964a9120459b087e2e6d6e45f50cd79099b038..031585be7c91008497c3525232f69ad784d2a165 100644 (file)
@@ -47,6 +47,7 @@
     #include "wx/msgdlg.h"
     #include "wx/settings.h"
     #include "wx/statbox.h"
     #include "wx/msgdlg.h"
     #include "wx/settings.h"
     #include "wx/statbox.h"
+    #include "wx/sizer.h"
 #endif
 
 #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
 #endif
 
 #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
     #include <windowsx.h>
 #endif
 
     #include <windowsx.h>
 #endif
 
-#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__)
-    #ifdef __WIN95__
-        #include <commctrl.h>
-    #endif
-#elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler
-    #include "wx/msw/gnuwin32/extra.h"
-#endif
+#include <commctrl.h>
 
 #include "wx/msw/missing.h"
 
 
 #include "wx/msw/missing.h"
 
     #define HAVE_TRACKMOUSEEVENT
 #endif // everything needed for TrackMouseEvent()
 
     #define HAVE_TRACKMOUSEEVENT
 #endif // everything needed for TrackMouseEvent()
 
+#define USE_DEFERRED_SIZING 1
+#define USE_DEFER_BUG_WORKAROUND 1
+
 // ---------------------------------------------------------------------------
 // global variables
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 // global variables
 // ---------------------------------------------------------------------------
@@ -218,6 +216,21 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent)
 
 #endif // !__WXWINCE__
 
 
 #endif // !__WXWINCE__
 
+#ifdef __WXWINCE__
+// On Windows CE, GetCursorPos can return an error, so use this function
+// instead
+bool GetCursorPosWinCE(POINT* pt)
+{
+    if (!GetCursorPos(pt))
+    {
+        DWORD pos = GetMessagePos();
+        pt->x = LOWORD(pos);
+        pt->y = HIWORD(pos);
+    }
+    return true;
+}
+#endif
+
 // ---------------------------------------------------------------------------
 // event tables
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 // event tables
 // ---------------------------------------------------------------------------
@@ -452,6 +465,9 @@ void wxWindowMSW::Init()
     m_lastMouseY = -1;
     m_lastMouseEvent = -1;
 #endif // wxUSE_MOUSEEVENT_HACK
     m_lastMouseY = -1;
     m_lastMouseEvent = -1;
 #endif // wxUSE_MOUSEEVENT_HACK
+
+    m_pendingPosition = wxDefaultPosition;
+    m_pendingSize = wxDefaultSize;
 }
 
 // Destructor
 }
 
 // Destructor
@@ -470,7 +486,12 @@ wxWindowMSW::~wxWindowMSW()
             {
                 frame->SetLastFocus(NULL);
             }
             {
                 frame->SetLastFocus(NULL);
             }
-            break;
+
+            // apparently sometimes we can end up with our grand parent
+            // pointing to us as well: this is surely a bug in focus handling
+            // code but it's not clear where it happens so for now just try to
+            // fix it here by not breaking out of the loop
+            //break;
         }
     }
 #endif // __WXUNIVERSAL__
         }
     }
 #endif // __WXUNIVERSAL__
@@ -494,6 +515,7 @@ wxWindowMSW::~wxWindowMSW()
     }
 
     delete m_childrenDisabled;
     }
 
     delete m_childrenDisabled;
+
 }
 
 // real construction (Init() must have been called before!)
 }
 
 // real construction (Init() must have been called before!)
@@ -757,7 +779,11 @@ bool wxWindowMSW::SetCursor(const wxCursor& cursor)
 
         // Change the cursor NOW if we're within the correct window
         POINT point;
 
         // Change the cursor NOW if we're within the correct window
         POINT point;
+#ifdef __WXWINCE__
+        ::GetCursorPosWinCE(&point);
+#else
         ::GetCursorPos(&point);
         ::GetCursorPos(&point);
+#endif
 
         RECT rect = wxGetWindowRect(hWnd);
 
 
         RECT rect = wxGetWindowRect(hWnd);
 
@@ -1235,7 +1261,11 @@ bool wxWindowMSW::IsMouseInWindow() const
 {
     // get the mouse position
     POINT pt;
 {
     // get the mouse position
     POINT pt;
+#ifdef __WXWINCE__
+    ::GetCursorPosWinCE(&pt);
+#else
     ::GetCursorPos(&pt);
     ::GetCursorPos(&pt);
+#endif
 
     // find the window which currently has the cursor and go up the window
     // chain until we find this window - or exhaust it
 
     // find the window which currently has the cursor and go up the window
     // chain until we find this window - or exhaust it
@@ -1340,14 +1370,15 @@ void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
             pRect = NULL;
         }
 
             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;
 
         ::RedrawWindow(hWnd, pRect, NULL, flags);
 #else
         UINT flags = RDW_INVALIDATE | RDW_ALLCHILDREN;
         if ( eraseBack )
             flags |= RDW_ERASE;
 
         ::RedrawWindow(hWnd, pRect, NULL, flags);
 #else
-        wxUnusedVar( eraseBack );
+        ::InvalidateRect(hWnd, pRect, eraseBack);
 #endif
     }
 }
 #endif
     }
 }
@@ -1524,29 +1555,20 @@ void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
     // if our parent had prepared a defer window handle for us, use it (unless
     // we are a top level window)
     wxWindowMSW *parent = GetParent();
     // if our parent had prepared a defer window handle for us, use it (unless
     // we are a top level window)
     wxWindowMSW *parent = GetParent();
+
+#if USE_DEFERRED_SIZING
     HDWP hdwp = parent && !IsTopLevel() ? (HDWP)parent->m_hDWP : NULL;
     HDWP hdwp = parent && !IsTopLevel() ? (HDWP)parent->m_hDWP : NULL;
-    if ( hdwp )
-    {
-        hdwp = ::DeferWindowPos(hdwp, GetHwnd(), NULL,
-                            x, y, width, height,
-                            SWP_NOZORDER);
-        if ( !hdwp )
-        {
-            wxLogLastError(_T("DeferWindowPos"));
-        }
+#else
+    HDWP hdwp = 0;
+#endif
 
 
+    wxMoveWindowDeferred(hdwp, this, GetHwnd(), x, y, width, height);
+
+#if USE_DEFERRED_SIZING
+    if ( parent )
         // hdwp must be updated as it may have been changed
         parent->m_hDWP = (WXHANDLE)hdwp;
         // hdwp must be updated as it may have been changed
         parent->m_hDWP = (WXHANDLE)hdwp;
-    }
-
-    // otherwise (or if deferring failed) move the window in place immediately
-    if ( !hdwp )
-    {
-        if ( !::MoveWindow(GetHwnd(), x, y, width, height, IsShown()) )
-        {
-            wxLogLastError(wxT("MoveWindow"));
-        }
-    }
+#endif
 }
 
 // set the size of the window: if the dimensions are positive, just use them,
 }
 
 // set the size of the window: if the dimensions are positive, just use them,
@@ -1561,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;
 {
     // 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(&currentX, NULL);
+
+    currentY = m_pendingPosition.y;
+    if (currentY == wxDefaultCoord)
+        GetPosition(NULL, &currentY);
+
+    currentW = m_pendingSize.x;
+    if (currentW == wxDefaultCoord)
+        GetSize(&currentW, NULL);
+
+    currentH = m_pendingSize.y;
+    if (currentH == wxDefaultCoord)
+        GetSize(NULL, &currentH);
+#else
     GetPosition(&currentX, &currentY);
     GetPosition(&currentX, &currentY);
-    int currentW,currentH;
     GetSize(&currentW, &currentH);
     GetSize(&currentW, &currentH);
+#endif
 
     // ... and don't do anything (avoiding flicker) if it's already ok
     if ( x == currentX && y == currentY &&
 
     // ... and don't do anything (avoiding flicker) if it's already ok
     if ( x == currentX && y == currentY &&
@@ -1613,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);
 }
 
     DoMoveWindow(x, y, width, height);
 }
 
@@ -1712,7 +1771,7 @@ void wxWindowMSW::GetTextExtent(const wxString& string,
 
     SIZE sizeRect;
     TEXTMETRIC tm;
 
     SIZE sizeRect;
     TEXTMETRIC tm;
-    GetTextExtentPoint(hdc, string, string.length(), &sizeRect);
+    ::GetTextExtentPoint32(hdc, string, string.length(), &sizeRect);
     GetTextMetrics(hdc, &tm);
 
     if ( x )
     GetTextMetrics(hdc, &tm);
 
     if ( x )
@@ -2293,6 +2352,31 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
             break;
 #endif // !__WXWINCE__
 
             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
 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
         case WM_ACTIVATEAPP:
             // This implicitly sends a wxEVT_ACTIVATE_APP event
@@ -2318,55 +2402,34 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
             processed = HandleKillFocus((WXHWND)(HWND)wParam);
             break;
 
             processed = HandleKillFocus((WXHWND)(HWND)wParam);
             break;
 
-        case WM_PAINT:
-            {
-                if ( wParam )
-                {
-                    // cast to wxWindow is needed for wxUniv
-                    wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
-                    processed = HandlePaint();
-                }
-                else
-                {
-                    processed = HandlePaint();
-                }
-                break;
-            }
-
-#ifdef WM_PRINT
         case WM_PRINTCLIENT:
         case WM_PRINTCLIENT:
-            if ( GetParent() &&
-                  GetParent()->MSWPrintChild((wxWindow *)this, wParam, lParam) )
-            {
-                processed = true;
-            }
+            processed = HandlePrintClient((WXHDC)wParam);
             break;
 
             break;
 
-        case WM_PRINT:
+        case WM_PAINT:
+            if ( wParam )
             {
             {
-                if ( lParam & PRF_ERASEBKGND )
-                    HandleEraseBkgnd((WXHDC)(HDC)wParam);
-
                 wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
 
                 processed = HandlePaint();
             }
                 wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
 
                 processed = HandlePaint();
             }
+            else // no DC given
+            {
+                processed = HandlePaint();
+            }
             break;
             break;
-#endif // WM_PRINT
 
         case WM_CLOSE:
 #ifdef __WXUNIVERSAL__
             // Universal uses its own wxFrame/wxDialog, so we don't receive
             // close events unless we have this.
             Close();
 
         case WM_CLOSE:
 #ifdef __WXUNIVERSAL__
             // Universal uses its own wxFrame/wxDialog, so we don't receive
             // close events unless we have this.
             Close();
-            processed = true;
-            rc.result = TRUE;
-#else
+#endif // __WXUNIVERSAL__
+
             // don't let the DefWindowProc() destroy our window - we'll do it
             // ourselves in ~wxWindow
             processed = true;
             rc.result = TRUE;
             // don't let the DefWindowProc() destroy our window - we'll do it
             // ourselves in ~wxWindow
             processed = true;
             rc.result = TRUE;
-#endif
             break;
 
         case WM_SHOWWINDOW:
             break;
 
         case WM_SHOWWINDOW:
@@ -3511,7 +3574,11 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd),
     // first ask the user code - it may wish to set the cursor in some very
     // specific way (for example, depending on the current position)
     POINT pt;
     // first ask the user code - it may wish to set the cursor in some very
     // specific way (for example, depending on the current position)
     POINT pt;
+#ifdef __WXWINCE__
+    if ( !::GetCursorPosWinCE(&pt))
+#else
     if ( !::GetCursorPos(&pt) )
     if ( !::GetCursorPos(&pt) )
+#endif
     {
         wxLogLastError(wxT("GetCursorPos"));
     }
     {
         wxLogLastError(wxT("GetCursorPos"));
     }
@@ -3596,7 +3663,11 @@ wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id),
     {
         wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
 
     {
         wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
 
-        wxCHECK_MSG( pMenuItem && pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)),
+        // see comment before the same test in MSWOnMeasureItem() below
+        if ( !pMenuItem )
+            return false;
+
+        wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
                          false, _T("MSWOnDrawItem: bad wxMenuItem pointer") );
 
         // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
                          false, _T("MSWOnDrawItem: bad wxMenuItem pointer") );
 
         // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
@@ -3654,7 +3725,15 @@ wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct)
     {
         wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
 
     {
         wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
 
-        wxCHECK_MSG( pMenuItem && pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)),
+        // according to Carsten Fuchs the pointer may be NULL under XP if an
+        // MDI child frame is initially maximized, see this for more info:
+        // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745
+        //
+        // so silently ignore it instead of asserting
+        if ( !pMenuItem )
+            return false;
+
+        wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
                         false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") );
 
         size_t w, h;
                         false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") );
 
         size_t w, h;
@@ -3705,12 +3784,16 @@ bool wxWindowMSW::HandleDisplayChange()
 
 #ifndef __WXMICROWIN__
 
 
 #ifndef __WXMICROWIN__
 
-bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC pDC, WXHWND pWnd)
+bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC hDC, WXHWND hWnd)
 {
 {
-#if wxUSE_CONTROLS
-    wxWindow *item = FindItemByHWND(pWnd, true);
+#if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__)
+    wxUnusedVar(hDC);
+    wxUnusedVar(hWnd);
+#else
+    wxControl *item = wxDynamicCast(FindItemByHWND(hWnd, true), wxControl);
+
     if ( item )
     if ( item )
-        *brush = item->MSWControlColor(pDC);
+        *brush = item->MSWControlColor(hDC, hWnd);
     else
 #endif // wxUSE_CONTROLS
         *brush = NULL;
     else
 #endif // wxUSE_CONTROLS
         *brush = NULL;
@@ -3720,11 +3803,6 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC pDC, WXHWND pWnd)
 
 #endif // __WXMICROWIN__
 
 
 #endif // __WXMICROWIN__
 
-WXHBRUSH wxWindowMSW::MSWControlColor(WXHDC WXUNUSED(hDC))
-{
-    return (WXHBRUSH)0;
-}
-
 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
 {
 #if wxUSE_PALETTE
 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
 {
 #if wxUSE_PALETTE
@@ -3854,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.
             // 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() )
             {
             wxBitmap stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
             if ( stdColourBitmap.Ok() )
             {
@@ -3986,92 +4065,99 @@ void wxWindowMSW::OnEraseBackground(wxEraseEvent& event)
 
 
     // do default background painting
 
 
     // do default background painting
-    if ( !DoEraseBackground(*event.GetDC()) )
+    if ( !DoEraseBackground(GetHdcOf(*event.GetDC())) )
     {
         // let the system paint the background
         event.Skip();
     }
 }
 
     {
         // let the system paint the background
         event.Skip();
     }
 }
 
-bool wxWindowMSW::DoEraseBackground(wxDC& dc)
+bool wxWindowMSW::DoEraseBackground(WXHDC hDC)
 {
 {
-    HBRUSH hBrush = (HBRUSH)MSWGetBgBrush(dc.GetHDC());
-    if ( !hBrush )
+    HBRUSH hbr = (HBRUSH)MSWGetBgBrush(hDC);
+    if ( !hbr )
         return false;
 
         return false;
 
-    RECT rc;
-    ::GetClientRect(GetHwnd(), &rc);
-    ::FillRect(GetHdcOf(dc), &rc, hBrush);
+    wxFillRect(GetHwnd(), (HDC)hDC, hbr);
 
     return true;
 }
 
 
     return true;
 }
 
-WXHBRUSH wxWindowMSW::MSWGetSolidBgBrushForChild(wxWindow *child)
-{
-    wxColour col = MSWGetBgColourForChild(child);
-    if ( col.Ok() )
-    {
-        // draw children with the same colour as the parent
-        wxBrush *brush = wxTheBrushList->FindOrCreateBrush(col, wxSOLID);
-
-        return (WXHBRUSH)brush->GetResourceHandle();
-    }
-
-    return 0;
-}
-
-wxColour wxWindowMSW::MSWGetBgColourForChild(wxWindow *child)
+WXHBRUSH
+wxWindowMSW::MSWGetBgBrushForChild(WXHDC WXUNUSED(hDC), WXHWND hWnd)
 {
     if ( m_hasBgCol )
     {
         // our background colour applies to:
         //  1. this window itself, always
         //  2. all children unless the colour is "not inheritable"
 {
     if ( m_hasBgCol )
     {
         // our background colour applies to:
         //  1. this window itself, always
         //  2. all children unless the colour is "not inheritable"
-        //  3. immediate transparent children which should show the same
-        //     background as we do, but not for transparent grandchildren
-        //     which use the background of their immediate parent instead
-        if ( m_inheritBgCol ||
-                child == this ||
-                    (child->HasTransparentBackground() &&
-                        child->GetParent() == this) )
+        //  3. even if it is not inheritable, our immediate transparent
+        //     children should still inherit it -- but not any transparent
+        //     children because it would look wrong if a child of non
+        //     transparent child would show our bg colour when the child itself
+        //     does not
+        wxWindow *win = wxFindWinFromHandle(hWnd);
+        if ( win == this ||
+                m_inheritBgCol ||
+                    (win && win->HasTransparentBackground() &&
+                        win->GetParent() == this) )
         {
         {
-            return GetBackgroundColour();
+            // draw children with the same colour as the parent
+            wxBrush *
+                brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour());
+
+            return (WXHBRUSH)GetHbrushOf(*brush);
         }
     }
 
         }
     }
 
-    return wxNullColour;
+    return 0;
 }
 
 }
 
-WXHBRUSH wxWindowMSW::MSWGetBgBrushForSelf(wxWindow *parent, WXHDC hDC)
+WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC, WXHWND hWndToPaint)
 {
 {
-    return parent->MSWGetBgBrushForChild(hDC, (wxWindow *)this);
-}
+    if ( !hWndToPaint )
+        hWndToPaint = GetHWND();
 
 
-WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC)
-{
-    for ( wxWindow *win = (wxWindow *)this; win; win = win->GetParent() )
+    for ( wxWindowMSW *win = this; win; win = win->GetParent() )
     {
     {
-        WXHBRUSH hBrush = MSWGetBgBrushForSelf(win, hDC);
+        WXHBRUSH hBrush = win->MSWGetBgBrushForChild(hDC, hWndToPaint);
         if ( hBrush )
             return hBrush;
 
         if ( hBrush )
             return hBrush;
 
-        // background is not inherited beyond the windows which have their own
-        // fixed background such as top level windows and notebooks and for
-        // windows for which a custom colour had been explicitly set with
-        // SetOwnBackgroundColour() and so shouldn't affect its children
-        if ( win->ProvidesBackground() ||
-                (win->UseBgCol() && !win->InheritsBackgroundColour()) )
+        // background is not inherited beyond top level windows
+        if ( win->IsTopLevel() )
             break;
     }
 
     return 0;
 }
 
             break;
     }
 
     return 0;
 }
 
-bool
-wxWindowMSW::MSWPrintChild(wxWindow * WXUNUSED(win),
-                           WXWPARAM WXUNUSED(wParam),
-                           WXLPARAM WXUNUSED(lParam))
+bool wxWindowMSW::HandlePrintClient(WXHDC hDC)
 {
 {
+    // we receive this message when DrawThemeParentBackground() is
+    // called from def window proc of several controls under XP and we
+    // must draw properly themed background here
+    //
+    // note that naively I'd expect filling the client rect with the
+    // brush returned by MSWGetBgBrush() work -- but for some reason it
+    // doesn't and we have to call parents MSWPrintChild() which is
+    // supposed to call DrawThemeBackground() with appropriate params
+    //
+    // 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) )
+            return true;
+
+        if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
+            break;
+    }
+
     return false;
 }
 
     return false;
 }
 
@@ -4117,17 +4203,34 @@ bool wxWindowMSW::HandleMoving(wxRect& rect)
 
 bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
 {
 
 bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
 {
+#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
     // when we resize this window, its children are probably going to be
     // repositioned as well, prepare to use DeferWindowPos() for them
-    const int numChildren = GetChildren().GetCount();
+    int numChildren = 0;
+    for ( HWND child = ::GetWindow(GetHwndOf(this), GW_CHILD);
+          child;
+          child = ::GetWindow(child, GW_HWNDNEXT) )
+    {
+        numChildren ++;
+    }
+
+    // Protect against valid m_hDWP being overwritten
+    bool useDefer = false;
+
     if ( numChildren > 1 )
     {
     if ( numChildren > 1 )
     {
-        m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
-        if ( !m_hDWP )
+        if (!m_hDWP)
         {
         {
-            wxLogLastError(_T("BeginDeferWindowPos"));
+            m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
+            if ( !m_hDWP )
+            {
+                wxLogLastError(_T("BeginDeferWindowPos"));
+            }
+            if (m_hDWP)
+                useDefer = true;
         }
     }
         }
     }
+#endif
 
     // update this window size
     bool processed = false;
 
     // update this window size
     bool processed = false;
@@ -4160,8 +4263,9 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
             processed = GetEventHandler()->ProcessEvent(event);
     }
 
             processed = GetEventHandler()->ProcessEvent(event);
     }
 
+#if USE_DEFERRED_SIZING
     // and finally change the positions of all child windows at once
     // and finally change the positions of all child windows at once
-    if ( m_hDWP )
+    if ( useDefer && m_hDWP )
     {
         // reset m_hDWP to NULL so that child windows don't try to use our
         // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
     {
         // reset m_hDWP to NULL so that child windows don't try to use our
         // m_hDWP after we call EndDeferWindowPos() on it (this shouldn't
@@ -4175,7 +4279,20 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam)
         {
             wxLogLastError(_T("EndDeferWindowPos"));
         }
         {
             wxLogLastError(_T("EndDeferWindowPos"));
         }
+
+#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();
+            child->m_pendingPosition = wxDefaultPosition;
+            child->m_pendingSize = wxDefaultSize;
+        }
+#endif
     }
     }
+#endif
 
     return processed;
 }
 
     return processed;
 }
@@ -4540,7 +4657,11 @@ void wxWindowMSW::GenerateMouseLeave()
         state |= MK_RBUTTON;
 
     POINT pt;
         state |= MK_RBUTTON;
 
     POINT pt;
+#ifdef __WXWINCE__
+    if ( !::GetCursorPosWinCE(&pt) )
+#else
     if ( !::GetCursorPos(&pt) )
     if ( !::GetCursorPos(&pt) )
+#endif
     {
         wxLogLastError(_T("GetCursorPos"));
     }
     {
         wxLogLastError(_T("GetCursorPos"));
     }
@@ -4587,7 +4708,11 @@ wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType,
 
     // translate the position to client coords
     POINT pt;
 
     // translate the position to client coords
     POINT pt;
+#ifdef __WXWINCE__
+    GetCursorPosWinCE(&pt);
+#else
     GetCursorPos(&pt);
     GetCursorPos(&pt);
+#endif
     RECT rect;
     GetWindowRect(GetHwnd(),&rect);
     pt.x -= rect.left;
     RECT rect;
     GetWindowRect(GetHwnd(),&rect);
     pt.x -= rect.left;
@@ -5808,7 +5933,11 @@ wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
 wxPoint wxGetMousePosition()
 {
     POINT pt;
 wxPoint wxGetMousePosition()
 {
     POINT pt;
+#ifdef __WXWINCE__
+    GetCursorPosWinCE(&pt);
+#else
     GetCursorPos( & pt );
     GetCursorPos( & pt );
+#endif
 
     return wxPoint(pt.x, pt.y);
 }
 
     return wxPoint(pt.x, pt.y);
 }
@@ -5900,6 +6029,31 @@ bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam)
 
 #endif // wxUSE_HOTKEY
 
 
 #endif // wxUSE_HOTKEY
 
+// Moves a window by deferred method or normal method
+bool wxMoveWindowDeferred(HDWP& hdwp, wxWindowBase* win, HWND hWnd, int x, int y, int width, int height)
+{
+    if ( hdwp )
+    {
+        hdwp = ::DeferWindowPos(hdwp, hWnd, NULL,
+                            x, y, width, height,
+                            SWP_NOZORDER);
+        if ( !hdwp )
+        {
+            wxLogLastError(_T("DeferWindowPos"));
+        }
+    }
+
+    // otherwise (or if deferring failed) move the window in place immediately
+    if ( !hdwp )
+    {
+        if ( !::MoveWindow(hWnd, x, y, width, height, win->IsShown()) )
+        {
+            wxLogLastError(wxT("MoveWindow"));
+        }
+    }
+    return hdwp != NULL;
+}
+
 // Not tested under WinCE
 #ifndef __WXWINCE__
 
 // Not tested under WinCE
 #ifndef __WXWINCE__