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); bool MSWSafeIsDialogMessage(WXMSG* msg);
#endif // __WXUNIVERSAL__ #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: 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 // this function is called after the window was resized to its new size
virtual void MSWEndDeferWindowPos() 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 // ... and adjust it to account for a possible parent frames toolbar
AdjustForParentClientOrigin(x, y); AdjustForParentClientOrigin(x, y);
m_hWnd = (WXHWND)::CreateWindowEx m_hWnd = MSWCreateWindowAtAnyPosition
( (
exstyle, // extended style exstyle, // extended style
classname, // the kind of control to create classname, // the kind of control to create
label.t_str(), // the window name label.t_str(), // the window name
style, // the window style style, // the window style
x, y, w, h, // the window position and size x, y, w, h, // the window position and size
GetHwndOf(GetParent()), // parent GetHwndOf(GetParent()), // parent
(HMENU)wxUIntToPtr(GetId()), // child id GetId() // child id
wxGetInstance(), // app instance );
NULL // creation parameters
);
if ( !m_hWnd ) if ( !m_hWnd )
{ {
wxLogLastError(wxString::Format
(
wxT("CreateWindowEx(\"%s\", flags=%08lx, ex=%08lx)"),
classname, style, exstyle
));
return false; return false;
} }

View File

@@ -298,19 +298,17 @@ bool wxSpinCtrl::Create(wxWindow *parent,
// create the text window // create the text window
m_hwndBuddy = (WXHWND)::CreateWindowEx m_hwndBuddy = MSWCreateWindowAtAnyPosition
( (
exStyle, // sunken border exStyle, // sunken border
wxT("EDIT"), // window class wxT("EDIT"), // window class
NULL, // no window title NULL, // no window title
msStyle, // style (will be shown later) msStyle, // style (will be shown later)
pos.x, pos.y, // position pos.x, pos.y, // position
0, 0, // size (will be set later) 0, 0, // size (will be set later)
GetHwndOf(parent), // parent GetHwndOf(parent), // parent
(HMENU)-1, // control id -1 // control id
wxGetInstance(), // app instance );
NULL // unused client data
);
if ( !m_hwndBuddy ) if ( !m_hwndBuddy )
{ {

View File

@@ -333,7 +333,7 @@ void wxStaticBitmap::SetImageNoCopy( wxGDIImage* image)
w = width; w = width;
h = height; 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 #if wxUSE_DEFERRED_SIZING
else else if ( MSWIsPositionDirectlySupported(x, y) )
{ {
// if our parent had prepared a defer window handle for us, use it (unless // if our parent had prepared a defer window handle for us, use it
// we are a top level window)
wxWindowMSW * const parent = GetParent(); wxWindowMSW * const parent = GetParent();
HDWP hdwp = parent ? (HDWP)parent->m_hDWP : NULL; 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 #endif // wxUSE_DEFERRED_SIZING
if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) ) MSWMoveWindowToAnyPosition(hwnd, x, y, width, height, IsShown());
{
wxLogLastError(wxT("MoveWindow"));
}
// if wxUSE_DEFERRED_SIZING, indicates that we didn't use deferred move, // if wxUSE_DEFERRED_SIZING, indicates that we didn't use deferred move,
// ignored otherwise // ignored otherwise
return false; 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) void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
{ {
// TODO: is this consistent with other platforms? // 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 // and not defer it here as otherwise the value returned by
// GetClient/WindowRect() wouldn't change as the window wouldn't be // GetClient/WindowRect() wouldn't change as the window wouldn't be
// really resized // really resized
if ( !::MoveWindow(GetHwnd(), MSWMoveWindowToAnyPosition(GetHwnd(), rectWin.left, rectWin.top,
rectWin.left, width + widthWin - rectClient.right,
rectWin.top, height + heightWin - rectClient.bottom, true);
width + widthWin - rectClient.right,
height + heightWin - rectClient.bottom,
TRUE) )
{
wxLogLastError(wxT("MoveWindow"));
}
} }
} }
@@ -3900,23 +3913,19 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
// do create the window // do create the window
wxWindowCreationHook hook(this); wxWindowCreationHook hook(this);
m_hWnd = (WXHWND)::CreateWindowEx m_hWnd = MSWCreateWindowAtAnyPosition
( (
extendedStyle, extendedStyle,
wclass, wclass,
title ? title : m_windowName.t_str(), title ? title : m_windowName.t_str(),
style, style,
x, y, w, h, x, y, w, h,
(HWND)MSWGetParent(), MSWGetParent(),
(HMENU)wxUIntToPtr(controlId), controlId
wxGetInstance(), );
NULL // no extra data
);
if ( !m_hWnd ) if ( !m_hWnd )
{ {
wxLogSysError(_("Can't create window of class %s"), wclass);
return false; return false;
} }
@@ -3925,6 +3934,32 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
return true; 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 // MSW message handlers
// =========================================================================== // ===========================================================================