#include "wx/msgdlg.h"
#include "wx/settings.h"
#include "wx/statbox.h"
+ #include "wx/sizer.h"
#endif
#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__)
#define HAVE_TRACKMOUSEEVENT
#endif // everything needed for TrackMouseEvent()
+#define USE_DEFERRED_SIZING 1
+#define USE_DEFER_BUG_WORKAROUND 1
+
// ---------------------------------------------------------------------------
// global variables
// ---------------------------------------------------------------------------
// 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;
- 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;
- }
-
- // 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,
{
// 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();
+#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
+ 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 )
- {
- wxLogLastError(_T("BeginDeferWindowPos"));
+ if (!m_hDWP)
+ {
+ m_hDWP = (WXHANDLE)::BeginDeferWindowPos(numChildren);
+ if ( !m_hDWP )
+ {
+ wxLogLastError(_T("BeginDeferWindowPos"));
+ }
+ if (m_hDWP)
+ useDefer = true;
}
}
+#endif
// update this window size
bool processed = false;
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
// may have depending on what the users EVT_SIZE handler does...)
HDWP hDWP = (HDWP)m_hDWP;
m_hDWP = NULL;
-
+
// do put all child controls in place at once
if ( !::EndDeferWindowPos(hDWP) )
{
wxLogLastError(_T("EndDeferWindowPos"));
}
+
+#if USE_DEFER_BUG_WORKAROUND
+ // Seems to be a bug in DeferWindowPos such that going from (a) to (b) to (a)
+ // doesn't work (omits last position/size). So check if there's a disparity,
+ // and correct.
+ for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxWindow *child = node->GetData();
+ wxSizer* sizer = child->GetContainingSizer();
+ if (sizer)
+ {
+ wxSizerItem* item = sizer->GetItem(child, true);
+ if (item->GetRect().GetPosition() != child->GetPosition())
+ {
+ child->Move(item->GetRect().GetPosition());
+ }
+ }
+ }
+#endif
}
+#endif
return processed;
}
#endif // wxUSE_HOTKEY
+// Moves a window by deferred method or normal method
+bool wxMoveWindowDeferred(HDWP& hdwp, wxWindow* 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__