X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fb7e28db37a94b6c0207b1c2c75b857295d05ed6..921c65ed3d889117c600387cebb0bce2470cff8e:/src/msw/window.cpp?ds=inline diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 9dc2e5922d..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__) @@ -107,13 +108,7 @@ #include #endif -#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__) - #ifdef __WIN95__ - #include - #endif -#elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler - #include "wx/msw/gnuwin32/extra.h" -#endif +#include #include "wx/msw/missing.h" @@ -125,6 +120,9 @@ #define HAVE_TRACKMOUSEEVENT #endif // everything needed for TrackMouseEvent() +#define USE_DEFERRED_SIZING 1 +#define USE_DEFER_BUG_WORKAROUND 1 + // --------------------------------------------------------------------------- // global variables // --------------------------------------------------------------------------- @@ -218,6 +216,21 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent) #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 // --------------------------------------------------------------------------- @@ -452,6 +465,9 @@ void wxWindowMSW::Init() m_lastMouseY = -1; m_lastMouseEvent = -1; #endif // wxUSE_MOUSEEVENT_HACK + + m_pendingPosition = wxDefaultPosition; + m_pendingSize = wxDefaultSize; } // Destructor @@ -470,7 +486,12 @@ wxWindowMSW::~wxWindowMSW() { 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__ @@ -494,6 +515,7 @@ wxWindowMSW::~wxWindowMSW() } delete m_childrenDisabled; + } // 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; +#ifdef __WXWINCE__ + ::GetCursorPosWinCE(&point); +#else ::GetCursorPos(&point); +#endif RECT rect = wxGetWindowRect(hWnd); @@ -782,12 +808,6 @@ void wxWindowMSW::WarpPointer (int x, int y) // scrolling stuff // --------------------------------------------------------------------------- -// convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT -static inline int wxDirToWinStyle(int orient) -{ - return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT; -} - inline int GetScrollPosition(HWND hWnd, int wOrient) { #ifdef __WXMICROWIN__ @@ -1052,6 +1072,8 @@ bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc) // On WinCE (at least), the wndproc comparison doesn't work, // so have to use something like this. #ifdef __WXWINCE__ + wxUnusedVar(wndProc); + extern wxChar *wxCanvasClassName; extern wxChar *wxCanvasClassNameNR; extern const wxChar *wxMDIFrameClassName; @@ -1126,7 +1148,7 @@ void wxWindowMSW::SetWindowStyleFlag(long flags) ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal); - // we must call SetWindowPos() to flash the cached extended style and + // we must call SetWindowPos() to flush the cached extended style and // also to make the change to wxSTAY_ON_TOP style take effect: just // setting the style simply doesn't work if ( !::SetWindowPos(GetHwnd(), @@ -1150,9 +1172,11 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const // using this flag results in very significant reduction in flicker, // especially with controls inside the static boxes (as the interior of the - // box is not redrawn twice). - // wxCLIP_CHILDREN support is for compatibility with old applications only. - if ((!wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) == 1) || (flags & wxCLIP_CHILDREN)) + // box is not redrawn twice).but sometimes results in redraw problems, so + // optionally allow the old code to continue to use it provided a special + // system option is turned on + if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) + || (flags & wxCLIP_CHILDREN) ) style |= WS_CLIPCHILDREN; // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially @@ -1237,7 +1261,11 @@ bool wxWindowMSW::IsMouseInWindow() const { // get the mouse position POINT pt; +#ifdef __WXWINCE__ + ::GetCursorPosWinCE(&pt); +#else ::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 @@ -1299,7 +1327,8 @@ void wxWindowMSW::Freeze() { if ( !m_frozenness++ ) { - SendSetRedraw(GetHwnd(), false); + if ( IsShown() ) + SendSetRedraw(GetHwnd(), false); } } @@ -1309,11 +1338,14 @@ void wxWindowMSW::Thaw() if ( !--m_frozenness ) { - SendSetRedraw(GetHwnd(), true); + if ( IsShown() ) + { + SendSetRedraw(GetHwnd(), true); - // we need to refresh everything or otherwise he invalidated area is not - // repainted - Refresh(); + // we need to refresh everything or otherwise the invalidated area + // is not going to be repainted + Refresh(); + } } } @@ -1322,18 +1354,32 @@ void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect) HWND hWnd = GetHwnd(); if ( hWnd ) { + RECT mswRect; + const RECT *pRect; if ( rect ) { - RECT mswRect; mswRect.left = rect->x; mswRect.top = rect->y; mswRect.right = rect->x + rect->width; mswRect.bottom = rect->y + rect->height; - ::InvalidateRect(hWnd, &mswRect, eraseBack); + pRect = &mswRect; } else - ::InvalidateRect(hWnd, NULL, eraseBack); + { + pRect = NULL; + } + + // 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 + ::InvalidateRect(hWnd, pRect, eraseBack); +#endif } } @@ -1509,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(); - 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")); - } +#if USE_DEFERRED_SIZING + HDWP hdwp = parent && !IsTopLevel() ? (HDWP)parent->m_hDWP : NULL; +#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; - } - - // 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, @@ -1546,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 && @@ -1598,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); } @@ -1697,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 ) @@ -2204,7 +2278,6 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l { bool allow; WXLRESULT result; - WXHICON hIcon; WXHBRUSH hBrush; } rc; @@ -2279,8 +2352,34 @@ 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 wxTheApp->SetActive(wParam != 0, FindFocus()); break; #endif @@ -2303,55 +2402,34 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l 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: - if ( GetParent() && - GetParent()->MSWPrintChild((wxWindow *)this, wParam, lParam) ) - { - processed = true; - } + processed = HandlePrintClient((WXHDC)wParam); 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(); } + else // no DC given + { + processed = HandlePaint(); + } 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(); - 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; -#endif break; case WM_SHOWWINDOW: @@ -3228,7 +3306,7 @@ bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl), bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd) { -#ifndef __WXWINCE__ +#ifdef ENDSESSION_LOGOFF wxCloseEvent event(wxEVT_QUERY_END_SESSION, wxID_ANY); event.SetEventObject(wxTheApp); event.SetCanVeto(true); @@ -3245,13 +3323,15 @@ bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd) return rc; #else + wxUnusedVar(logOff); + wxUnusedVar(mayEnd); return false; #endif } bool wxWindowMSW::HandleEndSession(bool endSession, long logOff) { -#ifndef __WXWINCE__ +#ifdef ENDSESSION_LOGOFF // do nothing if the session isn't ending if ( !endSession ) return false; @@ -3267,6 +3347,8 @@ bool wxWindowMSW::HandleEndSession(bool endSession, long logOff) return wxTheApp->ProcessEvent(event); #else + wxUnusedVar(endSession); + wxUnusedVar(logOff); return false; #endif } @@ -3492,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; +#ifdef __WXWINCE__ + if ( !::GetCursorPosWinCE(&pt)) +#else if ( !::GetCursorPos(&pt) ) +#endif { wxLogLastError(wxT("GetCursorPos")); } @@ -3577,7 +3663,11 @@ wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id), { 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 @@ -3635,7 +3725,15 @@ wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) { 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; @@ -3686,12 +3784,16 @@ bool wxWindowMSW::HandleDisplayChange() #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 ) - *brush = item->MSWControlColor(pDC); + *brush = item->MSWControlColor(hDC, hWnd); else #endif // wxUSE_CONTROLS *brush = NULL; @@ -3701,11 +3803,6 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC pDC, WXHWND pWnd) #endif // __WXMICROWIN__ -WXHBRUSH wxWindowMSW::MSWControlColor(WXHDC WXUNUSED(hDC)) -{ - return (WXHBRUSH)0; -} - bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange) { #if wxUSE_PALETTE @@ -3835,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() ) { @@ -3967,92 +4065,99 @@ void wxWindowMSW::OnEraseBackground(wxEraseEvent& event) // do default background painting - if ( !DoEraseBackground(*event.GetDC()) ) + if ( !DoEraseBackground(GetHdcOf(*event.GetDC())) ) { // 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; - RECT rc; - ::GetClientRect(GetHwnd(), &rc); - ::FillRect(GetHdcOf(dc), &rc, hBrush); + wxFillRect(GetHwnd(), (HDC)hDC, hbr); 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" - // 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; - // 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->m_hasBgCol && !win->m_inheritBgCol) ) + // background is not inherited beyond top level windows + if ( win->IsTopLevel() ) 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; } @@ -4098,17 +4203,34 @@ bool wxWindowMSW::HandleMoving(wxRect& rect) 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 - 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 ) { - 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; @@ -4141,8 +4263,9 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam) processed = GetEventHandler()->ProcessEvent(event); } +#if USE_DEFERRED_SIZING // 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 @@ -4156,7 +4279,20 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT wParam) { 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; } @@ -4268,18 +4404,27 @@ bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control) return GetEventHandler()->ProcessEvent(event); } -#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) else { +#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__) // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND // notifications to its parent which we want to reflect back to // wxSpinCtrl wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control); if ( spin && spin->ProcessTextCommand(cmd, id) ) return true; - } #endif // wxUSE_SPINCTRL +#if wxUSE_CHOICE && defined(__SMARTPHONE__) + // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND + // notifications to its parent which we want to reflect back to + // wxChoice + wxChoice *choice = wxChoice::GetChoiceForListBox(control); + if ( choice && choice->MSWCommand(cmd, id) ) + return true; +#endif + } + return false; } @@ -4512,7 +4657,11 @@ void wxWindowMSW::GenerateMouseLeave() state |= MK_RBUTTON; POINT pt; +#ifdef __WXWINCE__ + if ( !::GetCursorPosWinCE(&pt) ) +#else if ( !::GetCursorPos(&pt) ) +#endif { wxLogLastError(_T("GetCursorPos")); } @@ -4559,7 +4708,11 @@ wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, // translate the position to client coords POINT pt; +#ifdef __WXWINCE__ + GetCursorPosWinCE(&pt); +#else GetCursorPos(&pt); +#endif RECT rect; GetWindowRect(GetHwnd(),&rect); pt.x -= rect.left; @@ -5133,6 +5286,9 @@ bool wxGetKeyState(wxKeyCode key) { bool bVirtual; + wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key != + WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons")); + //High order with GetAsyncKeyState only available on WIN32 #ifdef __WIN32__ //If the requested key is a LED key, return @@ -5777,13 +5933,36 @@ wxWindow* wxFindWindowAtPoint(const wxPoint& pt) wxPoint wxGetMousePosition() { POINT pt; +#ifdef __WXWINCE__ + GetCursorPosWinCE(&pt); +#else GetCursorPos( & pt ); +#endif return wxPoint(pt.x, pt.y); } #if wxUSE_HOTKEY +#if defined(__SMARTPHONE__) || defined(__POCKETPC__) +static void WinCEUnregisterHotKey(int modifiers, int id) +{ + // Register hotkeys for the hardware buttons + HINSTANCE hCoreDll; + typedef BOOL (WINAPI *UnregisterFunc1Proc)(UINT, UINT); + + UnregisterFunc1Proc procUnregisterFunc; + hCoreDll = LoadLibrary(_T("coredll.dll")); + if (hCoreDll) + { + procUnregisterFunc = (UnregisterFunc1Proc)GetProcAddress(hCoreDll, _T("UnregisterFunc1")); + if (procUnregisterFunc) + procUnregisterFunc(modifiers, id); + FreeLibrary(hCoreDll); + } +} +#endif + bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode) { UINT win_modifiers=0; @@ -5796,6 +5975,12 @@ bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode) if ( modifiers & wxMOD_WIN ) win_modifiers |= MOD_WIN; +#if defined(__SMARTPHONE__) || defined(__POCKETPC__) + // Required for PPC and Smartphone hardware buttons + if (keycode >= WXK_SPECIAL1 && keycode <= WXK_SPECIAL20) + WinCEUnregisterHotKey(win_modifiers, hotkeyId); +#endif + if ( !::RegisterHotKey(GetHwnd(), hotkeyId, win_modifiers, keycode) ) { wxLogLastError(_T("RegisterHotKey")); @@ -5808,6 +5993,10 @@ bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode) bool wxWindowMSW::UnregisterHotKey(int hotkeyId) { +#if defined(__SMARTPHONE__) || defined(__POCKETPC__) + WinCEUnregisterHotKey(MOD_WIN, hotkeyId); +#endif + if ( !::UnregisterHotKey(GetHwnd(), hotkeyId) ) { wxLogLastError(_T("UnregisterHotKey")); @@ -5840,6 +6029,31 @@ bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam) #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__