fix window position under MSW when limited by short range

This commit is contained in:
Cătălin Răceanu
2018-04-18 20:19:45 +03:00
parent f751f15b9f
commit 578474526f
5 changed files with 107 additions and 63 deletions

View File

@@ -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()
{

View File

@@ -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;
}

View File

@@ -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 )
{

View File

@@ -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);
}
}

View File

@@ -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
// ===========================================================================