diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index 1a6af48f5b..8ea5f8725d 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -729,8 +729,27 @@ private: bool MSWSafeIsDialogMessage(WXMSG* msg); #endif // __WXUNIVERSAL__ -#if wxUSE_DEFERRED_SIZING + static inline bool MSWIsPositionDirectlySupported(int x, int y) + { + // The supported coordinate intervals for various functions are: + // - MoveWindow, DeferWindowPos: [-32768, 32767] a.k.a. [SHRT_MIN, SHRT_MAX]; + // - CreateWindow, CreateWindowEx: [-32768, 32554]. + // CreateXXX will _sometimes_ manage to create the window at higher coordinates + // like 32580, 32684, 32710, but that was not consistent and the lowest common + // limit was 32554 (so far at least). + return (x >= SHRT_MIN && x <= 32554 && y >= SHRT_MIN && y <= 32554); + } + protected: + WXHWND MSWCreateWindowAtAnyPosition(WXDWORD exStyle, const wxChar* clName, + const wxChar* title, WXDWORD style, + int x, int y, int width, int height, + WXHWND parent, wxWindowID id); + + void MSWMoveWindowToAnyPosition(WXHWND hwnd, int x, int y, + int width, int height, bool bRepaint); + +#if wxUSE_DEFERRED_SIZING // this function is called after the window was resized to its new size virtual void MSWEndDeferWindowPos() { diff --git a/src/msw/control.cpp b/src/msw/control.cpp index e253935c23..f3be7cd0be 100644 --- a/src/msw/control.cpp +++ b/src/msw/control.cpp @@ -132,27 +132,19 @@ bool wxControl::MSWCreateControl(const wxChar *classname, // ... and adjust it to account for a possible parent frames toolbar AdjustForParentClientOrigin(x, y); - m_hWnd = (WXHWND)::CreateWindowEx - ( - exstyle, // extended style - classname, // the kind of control to create - label.t_str(), // the window name - style, // the window style - x, y, w, h, // the window position and size - GetHwndOf(GetParent()), // parent - (HMENU)wxUIntToPtr(GetId()), // child id - wxGetInstance(), // app instance - NULL // creation parameters - ); + m_hWnd = MSWCreateWindowAtAnyPosition + ( + exstyle, // extended style + classname, // the kind of control to create + label.t_str(), // the window name + style, // the window style + x, y, w, h, // the window position and size + GetHwndOf(GetParent()), // parent + GetId() // child id + ); if ( !m_hWnd ) { - wxLogLastError(wxString::Format - ( - wxT("CreateWindowEx(\"%s\", flags=%08lx, ex=%08lx)"), - classname, style, exstyle - )); - return false; } diff --git a/src/msw/spinctrl.cpp b/src/msw/spinctrl.cpp index a692a5044e..adc534b01a 100644 --- a/src/msw/spinctrl.cpp +++ b/src/msw/spinctrl.cpp @@ -298,19 +298,17 @@ bool wxSpinCtrl::Create(wxWindow *parent, // create the text window - m_hwndBuddy = (WXHWND)::CreateWindowEx - ( - exStyle, // sunken border - wxT("EDIT"), // window class - NULL, // no window title - msStyle, // style (will be shown later) - pos.x, pos.y, // position - 0, 0, // size (will be set later) - GetHwndOf(parent), // parent - (HMENU)-1, // control id - wxGetInstance(), // app instance - NULL // unused client data - ); + m_hwndBuddy = MSWCreateWindowAtAnyPosition + ( + exStyle, // sunken border + wxT("EDIT"), // window class + NULL, // no window title + msStyle, // style (will be shown later) + pos.x, pos.y, // position + 0, 0, // size (will be set later) + GetHwndOf(parent), // parent + -1 // control id + ); if ( !m_hwndBuddy ) { diff --git a/src/msw/statbmp.cpp b/src/msw/statbmp.cpp index 4add948108..66d2f37e02 100644 --- a/src/msw/statbmp.cpp +++ b/src/msw/statbmp.cpp @@ -333,7 +333,7 @@ void wxStaticBitmap::SetImageNoCopy( wxGDIImage* image) w = width; h = height; - ::MoveWindow(GetHwnd(), x, y, width, height, FALSE); + MSWMoveWindowToAnyPosition(GetHwnd(), x, y, width, height, false); } } diff --git a/src/msw/window.cpp b/src/msw/window.cpp index ab5f008a14..f55b8be586 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -1955,10 +1955,9 @@ wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height) } #if wxUSE_DEFERRED_SIZING - else + else if ( MSWIsPositionDirectlySupported(x, y) ) { - // if our parent had prepared a defer window handle for us, use it (unless - // we are a top level window) + // if our parent had prepared a defer window handle for us, use it wxWindowMSW * const parent = GetParent(); HDWP hdwp = parent ? (HDWP)parent->m_hDWP : NULL; @@ -1989,16 +1988,36 @@ wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height) } #endif // wxUSE_DEFERRED_SIZING - if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) ) - { - wxLogLastError(wxT("MoveWindow")); - } + MSWMoveWindowToAnyPosition(hwnd, x, y, width, height, IsShown()); // if wxUSE_DEFERRED_SIZING, indicates that we didn't use deferred move, // ignored otherwise return false; } +void wxWindowMSW::MSWMoveWindowToAnyPosition(WXHWND hwnd, int x, int y, int width, int height, bool bRepaint) +{ + bool scroll = GetParent() && !MSWIsPositionDirectlySupported(x, y); + + if ( scroll ) + { + // scroll to the actual position (looks like there is no need to Freeze() the parent) + ::ScrollWindow(GetHwndOf(GetParent()), -x, -y, NULL, NULL); + } + + // move to relative coordinates + if ( !::MoveWindow(hwnd, (scroll ? 0 : x), (scroll ? 0 : y), width, height, bRepaint) ) + { + wxLogLastError(wxT("MoveWindow")); + } + + if ( scroll ) + { + // scroll back + ::ScrollWindow(GetHwndOf(GetParent()), x, y, NULL, NULL); + } +} + void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height) { // TODO: is this consistent with other platforms? @@ -2171,15 +2190,9 @@ void wxWindowMSW::DoSetClientSize(int width, int height) // and not defer it here as otherwise the value returned by // GetClient/WindowRect() wouldn't change as the window wouldn't be // really resized - if ( !::MoveWindow(GetHwnd(), - rectWin.left, - rectWin.top, - width + widthWin - rectClient.right, - height + heightWin - rectClient.bottom, - TRUE) ) - { - wxLogLastError(wxT("MoveWindow")); - } + MSWMoveWindowToAnyPosition(GetHwnd(), rectWin.left, rectWin.top, + width + widthWin - rectClient.right, + height + heightWin - rectClient.bottom, true); } } @@ -3900,23 +3913,19 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, // do create the window wxWindowCreationHook hook(this); - m_hWnd = (WXHWND)::CreateWindowEx - ( - extendedStyle, - wclass, - title ? title : m_windowName.t_str(), - style, - x, y, w, h, - (HWND)MSWGetParent(), - (HMENU)wxUIntToPtr(controlId), - wxGetInstance(), - NULL // no extra data - ); + m_hWnd = MSWCreateWindowAtAnyPosition + ( + extendedStyle, + wclass, + title ? title : m_windowName.t_str(), + style, + x, y, w, h, + MSWGetParent(), + controlId + ); if ( !m_hWnd ) { - wxLogSysError(_("Can't create window of class %s"), wclass); - return false; } @@ -3925,6 +3934,32 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, return true; } +WXHWND wxWindowMSW::MSWCreateWindowAtAnyPosition(WXDWORD exStyle, const wxChar* clName, + const wxChar* title, WXDWORD style, + int x, int y, int width, int height, + WXHWND parent, wxWindowID id) +{ + WXHWND hWnd = ::CreateWindowEx(exStyle, clName, title, style, x, y, width, height, + parent, (HMENU)wxUIntToPtr(id), wxGetInstance(), + NULL); // no extra data + + if ( !hWnd ) + { + wxLogLastError(wxString::Format + ( + wxT("CreateWindowEx(\"%s\", flags=%08lx, ex=%08lx)"), + clName, style, exStyle + )); + } + else if ( !IsTopLevel() && !MSWIsPositionDirectlySupported(x, y) ) + { + // fix position if limited by Short range + MSWMoveWindowToAnyPosition(hWnd, x, y, width, height, IsShown()); + } + + return hWnd; +} + // =========================================================================== // MSW message handlers // ===========================================================================