#define HAVE_TRACKMOUSEEVENT
#endif // everything needed for TrackMouseEvent()
+// if this is set to 1, we use deferred window sizing to reduce flicker when
+// resizing complicated window hierarchies, but this can in theory result in
+// different behaviour than the old code so we keep the possibility to use it
+// by setting this to 0 (in the future this should be removed completely)
#define USE_DEFERRED_SIZING 1
-#define USE_DEFER_BUG_WORKAROUND 1
// ---------------------------------------------------------------------------
// global variables
// Get total size
void wxWindowMSW::DoGetSize(int *x, int *y) const
{
- RECT rect = wxGetWindowRect(GetHwnd());
+ // if SetSize() had been called at wx level but not realized at Windows
+ // level yet (i.e. EndDeferWindowPos() not called), we still should return
+ // the new and not the old position to the other wx code
+ if ( m_pendingSize != wxDefaultSize )
+ {
+ if ( x )
+ *x = m_pendingSize.x;
+ if ( y )
+ *y = m_pendingSize.y;
+ }
+ else // use current size
+ {
+ RECT rect = wxGetWindowRect(GetHwnd());
- if ( x )
- *x = rect.right - rect.left;
- if ( y )
- *y = rect.bottom - rect.top;
+ if ( x )
+ *x = rect.right - rect.left;
+ if ( y )
+ *y = rect.bottom - rect.top;
+ }
}
// Get size *available for subwindows* i.e. excluding menu bar etc.
void wxWindowMSW::DoGetClientSize(int *x, int *y) const
{
+ // this is only for top level windows whose resizing is never deferred, so
+ // we can safely use the current size here
RECT rect = wxGetClientRect(GetHwnd());
if ( x )
void wxWindowMSW::DoGetPosition(int *x, int *y) const
{
- RECT rect = wxGetWindowRect(GetHwnd());
-
- POINT point;
- point.x = rect.left;
- point.y = rect.top;
+ wxWindow * const parent = GetParent();
- // we do the adjustments with respect to the parent only for the "real"
- // children, not for the dialogs/frames
- if ( !IsTopLevel() )
+ wxPoint pos;
+ if ( m_pendingPosition != wxDefaultPosition )
{
- HWND hParentWnd = 0;
- wxWindow *parent = GetParent();
- if ( parent )
- hParentWnd = GetWinHwnd(parent);
+ pos = m_pendingPosition;
+ }
+ else // use current position
+ {
+ RECT rect = wxGetWindowRect(GetHwnd());
- // Since we now have the absolute screen coords, if there's a parent we
- // must subtract its top left corner
- if ( hParentWnd )
- {
- ::ScreenToClient(hParentWnd, &point);
- }
+ POINT point;
+ point.x = rect.left;
+ point.y = rect.top;
- if ( parent )
+ // we do the adjustments with respect to the parent only for the "real"
+ // children, not for the dialogs/frames
+ if ( !IsTopLevel() )
{
- // We may be faking the client origin. So a window that's really at (0,
- // 30) may appear (to wxWin apps) to be at (0, 0).
- wxPoint pt(parent->GetClientAreaOrigin());
- point.x -= pt.x;
- point.y -= pt.y;
+ // Since we now have the absolute screen coords, if there's a
+ // parent we must subtract its top left corner
+ if ( parent )
+ {
+ ::ScreenToClient(GetHwndOf(parent), &point);
+ }
}
+
+ pos.x = point.x;
+ pos.y = point.y;
+ }
+
+ // we also must adjust by the client area offset: a control which is just
+ // under a toolbar could be at (0, 30) in Windows but at (0, 0) in wx
+ if ( parent && !IsTopLevel() )
+ {
+ const wxPoint pt(parent->GetClientAreaOrigin());
+ pos.x -= pt.x;
+ pos.y -= pt.y;
}
if ( x )
- *x = point.x;
+ *x = pos.x;
if ( y )
- *y = point.y;
+ *y = pos.y;
}
void wxWindowMSW::DoScreenToClient(int *x, int *y) const
*y = pt.y;
}
+bool
+wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height)
+{
+#if USE_DEFERRED_SIZING
+ // if our parent had prepared a defer window handle for us, use it (unless
+ // we are a top level window)
+ wxWindowMSW * const parent = IsTopLevel() ? NULL : GetParent();
+
+ HDWP hdwp = parent ? (HDWP)parent->m_hDWP : NULL;
+ if ( hdwp )
+ {
+ hdwp = ::DeferWindowPos(hdwp, (HWND)hwnd, NULL, x, y, width, height,
+ SWP_NOZORDER);
+ if ( !hdwp )
+ {
+ wxLogLastError(_T("DeferWindowPos"));
+ }
+ }
+
+ if ( parent )
+ {
+ // hdwp must be updated as it may have been changed
+ parent->m_hDWP = (WXHANDLE)hdwp;
+ }
+
+ if ( hdwp )
+ {
+ // did deferred move, remember new coordinates of the window as they're
+ // different from what Windows would return for it
+ return true;
+ }
+
+ // otherwise (or if deferring failed) move the window in place immediately
+#endif // USE_DEFERRED_SIZING
+ if ( !::MoveWindow((HWND)hwnd, x, y, width, height, IsShown()) )
+ {
+ wxLogLastError(wxT("MoveWindow"));
+ }
+
+ // if USE_DEFERRED_SIZING, indicates that we didn't use deferred move,
+ // ignored otherwise
+ return false;
+}
+
void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
{
// TODO: is this consistent with other platforms?
if (height < 0)
height = 0;
- // 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;
-#else
- HDWP hdwp = 0;
-#endif
-
- wxMoveWindowDeferred(hdwp, this, GetHwnd(), x, y, width, height);
-
+ if ( DoMoveSibling(m_hWnd, 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;
-#endif
+ m_pendingPosition = wxPoint(x, y);
+ m_pendingSize = wxSize(width, height);
+#endif // USE_DEFERRED_SIZING
+ }
}
// set the size of the window: if the dimensions are positive, just use them,
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);
GetSize(¤tW, ¤tH);
-#endif
// ... and don't do anything (avoiding flicker) if it's already ok
if ( x == currentX && y == currentY &&
}
}
-#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.
- wxWindowMSW *parent = GetParent();
- HDWP hdwp = parent && !IsTopLevel() ? (HDWP)parent->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);
}
wxLogLastError(_T("EndDeferWindowPos"));
}
-#if USE_DEFER_BUG_WORKAROUND
// Reset our children's pending pos/size values.
for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
node;
child->m_pendingPosition = wxDefaultPosition;
child->m_pendingSize = wxDefaultSize;
}
-#endif
}
-#endif
+#endif // USE_DEFERRED_SIZING
return processed;
}
bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
{
#if wxUSE_MOUSEWHEEL
+ // notice that WM_MOUSEWHEEL position is in screen coords (as it's
+ // forwarded up to the parent by DefWindowProc()) and not in the client
+ // ones as all the other messages, translate them to the client coords for
+ // consistency
+ const wxPoint
+ pt = ScreenToClient(wxPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
wxMouseEvent event(wxEVT_MOUSEWHEEL);
- InitMouseEvent(event,
- GET_X_LPARAM(lParam),
- GET_Y_LPARAM(lParam),
- LOWORD(wParam));
+ InitMouseEvent(event, pt.x, pt.y, LOWORD(wParam));
event.m_wheelRotation = (short)HIWORD(wParam);
event.m_wheelDelta = WHEEL_DELTA;
#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__