+ LONG styleOld = ::GetWindowLong(hwnd, GWL_EXSTYLE);
+
+ LONG styleNew = styleOld;
+ switch ( dir )
+ {
+ case wxLayout_LeftToRight:
+ styleNew &= ~WS_EX_LAYOUTRTL;
+ break;
+
+ case wxLayout_RightToLeft:
+ styleNew |= WS_EX_LAYOUTRTL;
+ break;
+
+ default:
+ wxFAIL_MSG(_T("unsupported layout direction"));
+ break;
+ }
+
+ if ( styleNew != styleOld )
+ {
+ ::SetWindowLong(hwnd, GWL_EXSTYLE, styleNew);
+ }
+#endif
+}
+
+wxLayoutDirection wxWindowMSW::GetLayoutDirection() const
+{
+#ifdef __WXWINCE__
+ return wxLayout_Default;
+#else
+ const HWND hwnd = GetHwnd();
+ wxCHECK_MSG( hwnd, wxLayout_Default, _T("invalid window") );
+
+ return ::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL
+ ? wxLayout_RightToLeft
+ : wxLayout_LeftToRight;
+#endif
+}
+
+wxCoord
+wxWindowMSW::AdjustForLayoutDirection(wxCoord x,
+ wxCoord WXUNUSED(width),
+ wxCoord WXUNUSED(widthTotal)) const
+{
+ // Win32 mirrors the coordinates of RTL windows automatically, so don't
+ // redo it ourselves
+ return x;
+}
+
+// ---------------------------------------------------------------------------
+// subclassing
+// ---------------------------------------------------------------------------
+
+void wxWindowMSW::SubclassWin(WXHWND hWnd)
+{
+ wxASSERT_MSG( !m_oldWndProc, wxT("subclassing window twice?") );
+
+ HWND hwnd = (HWND)hWnd;
+ wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in SubclassWin") );
+
+ wxAssociateWinWithHandle(hwnd, this);
+
+ m_oldWndProc = (WXFARPROC)wxGetWindowProc((HWND)hWnd);
+
+ // we don't need to subclass the window of our own class (in the Windows
+ // sense of the word)
+ if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) )
+ {
+ wxSetWindowProc(hwnd, wxWndProc);
+ }
+ else
+ {
+ // don't bother restoring it either: this also makes it easy to
+ // implement IsOfStandardClass() method which returns true for the
+ // standard controls and false for the wxWidgets own windows as it can
+ // simply check m_oldWndProc
+ m_oldWndProc = NULL;
+ }
+
+ // we're officially created now, send the event
+ wxWindowCreateEvent event((wxWindow *)this);
+ (void)GetEventHandler()->ProcessEvent(event);
+}
+
+void wxWindowMSW::UnsubclassWin()
+{
+ wxRemoveHandleAssociation(this);
+
+ // Restore old Window proc
+ HWND hwnd = GetHwnd();
+ if ( hwnd )
+ {
+ SetHWND(0);
+
+ wxCHECK_RET( ::IsWindow(hwnd), wxT("invalid HWND in UnsubclassWin") );
+
+ if ( m_oldWndProc )
+ {
+ if ( !wxCheckWindowWndProc((WXHWND)hwnd, m_oldWndProc) )
+ {
+ wxSetWindowProc(hwnd, (WNDPROC)m_oldWndProc);
+ }
+
+ m_oldWndProc = NULL;
+ }
+ }
+}
+
+void wxWindowMSW::AssociateHandle(WXWidget handle)
+{
+ if ( m_hWnd )
+ {
+ if ( !::DestroyWindow(GetHwnd()) )
+ wxLogLastError(wxT("DestroyWindow"));
+ }
+
+ WXHWND wxhwnd = (WXHWND)handle;
+
+ SetHWND(wxhwnd);
+ SubclassWin(wxhwnd);
+}
+
+void wxWindowMSW::DissociateHandle()
+{
+ // this also calls SetHWND(0) for us
+ UnsubclassWin();
+}
+
+
+bool wxCheckWindowWndProc(WXHWND hWnd,
+ WXFARPROC WXUNUSED(wndProc))
+{
+// TODO: This list of window class names should be factored out so they can be
+// managed in one place and then accessed from here and other places, such as
+// wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses()
+
+#ifdef __WXWINCE__
+ extern wxChar *wxCanvasClassName;
+ extern wxChar *wxCanvasClassNameNR;
+#else
+ extern const wxChar *wxCanvasClassName;
+ extern const wxChar *wxCanvasClassNameNR;
+#endif
+ extern const wxChar *wxMDIFrameClassName;
+ extern const wxChar *wxMDIFrameClassNameNoRedraw;
+ extern const wxChar *wxMDIChildFrameClassName;
+ extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
+ wxString str(wxGetWindowClass(hWnd));
+ if (str == wxCanvasClassName ||
+ str == wxCanvasClassNameNR ||
+#if wxUSE_GLCANVAS
+ str == _T("wxGLCanvasClass") ||
+ str == _T("wxGLCanvasClassNR") ||
+#endif // wxUSE_GLCANVAS
+ str == wxMDIFrameClassName ||
+ str == wxMDIFrameClassNameNoRedraw ||
+ str == wxMDIChildFrameClassName ||
+ str == wxMDIChildFrameClassNameNoRedraw ||
+ str == _T("wxTLWHiddenParent"))
+ return true; // Effectively means don't subclass
+ else
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+// Style handling
+// ----------------------------------------------------------------------------
+
+void wxWindowMSW::SetWindowStyleFlag(long flags)
+{
+ long flagsOld = GetWindowStyleFlag();
+ if ( flags == flagsOld )
+ return;
+
+ // update the internal variable
+ wxWindowBase::SetWindowStyleFlag(flags);
+
+ // and the real window flags
+ MSWUpdateStyle(flagsOld, GetExtraStyle());
+}
+
+void wxWindowMSW::SetExtraStyle(long exflags)
+{
+ long exflagsOld = GetExtraStyle();
+ if ( exflags == exflagsOld )
+ return;
+
+ // update the internal variable
+ wxWindowBase::SetExtraStyle(exflags);
+
+ // and the real window flags
+ MSWUpdateStyle(GetWindowStyleFlag(), exflagsOld);
+}
+
+void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld)
+{
+ // now update the Windows style as well if needed - and if the window had
+ // been already created
+ if ( !GetHwnd() )
+ return;
+
+ // we may need to call SetWindowPos() when we change some styles
+ bool callSWP = false;
+
+ WXDWORD exstyle;
+ long style = MSWGetStyle(GetWindowStyleFlag(), &exstyle);
+
+ // this is quite a horrible hack but we need it because MSWGetStyle()
+ // doesn't take exflags as parameter but uses GetExtraStyle() internally
+ // and so we have to modify the window exflags temporarily to get the
+ // correct exstyleOld
+ long exflagsNew = GetExtraStyle();
+ wxWindowBase::SetExtraStyle(exflagsOld);
+
+ WXDWORD exstyleOld;
+ long styleOld = MSWGetStyle(flagsOld, &exstyleOld);
+
+ wxWindowBase::SetExtraStyle(exflagsNew);
+
+
+ if ( style != styleOld )
+ {
+ // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
+ // this function so instead of simply setting the style to the new
+ // value we clear the bits which were set in styleOld but are set in
+ // the new one and set the ones which were not set before
+ long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE);
+ styleReal &= ~styleOld;
+ styleReal |= style;
+
+ ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal);
+
+ // we need to call SetWindowPos() if any of the styles affecting the
+ // frame appearance have changed
+ callSWP = ((styleOld ^ style ) & (WS_BORDER |
+ WS_THICKFRAME |
+ WS_CAPTION |
+ WS_DLGFRAME |
+ WS_MAXIMIZEBOX |
+ WS_MINIMIZEBOX |
+ WS_SYSMENU) ) != 0;
+ }
+
+ // and the extended style
+ long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
+
+ if ( exstyle != exstyleOld )
+ {
+ exstyleReal &= ~exstyleOld;
+ exstyleReal |= exstyle;
+
+ ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
+
+ // ex style changes don't take effect without calling SetWindowPos
+ callSWP = true;
+ }
+
+ if ( callSWP )
+ {
+ // we must call SetWindowPos() to flush the cached extended style and
+ // also to make the change to wxSTAY_ON_TOP style take effect: just
+ // setting the style simply doesn't work
+ if ( !::SetWindowPos(GetHwnd(),
+ exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST
+ : HWND_NOTOPMOST,
+ 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED) )
+ {
+ wxLogLastError(_T("SetWindowPos"));
+ }
+ }
+}
+
+WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
+{
+ // translate common wxWidgets styles to Windows ones
+
+ // most of windows are child ones, those which are not (such as
+ // wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle()
+ WXDWORD style = WS_CHILD;
+
+ // using this flag results in very significant reduction in flicker,
+ // especially with controls inside the static boxes (as the interior of the
+ // box is not redrawn twice), but sometimes results in redraw problems, so
+ // optionally allow the old code to continue to use it provided a special
+ // system option is turned on
+ if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children"))
+ || (flags & wxCLIP_CHILDREN) )
+ style |= WS_CLIPCHILDREN;
+
+ // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially
+ // don't support overlapping windows and it only makes sense for them and,
+ // presumably, gives the system some extra work (to manage more clipping
+ // regions), so avoid it alltogether
+
+
+ if ( flags & wxVSCROLL )
+ style |= WS_VSCROLL;
+
+ if ( flags & wxHSCROLL )
+ style |= WS_HSCROLL;
+
+ const wxBorder border = GetBorder(flags);
+
+ // WS_BORDER is only required for wxBORDER_SIMPLE
+ if ( border == wxBORDER_SIMPLE )
+ style |= WS_BORDER;
+
+ // now deal with ext style if the caller wants it
+ if ( exstyle )
+ {
+ *exstyle = 0;
+
+#ifndef __WXWINCE__
+ if ( flags & wxTRANSPARENT_WINDOW )
+ *exstyle |= WS_EX_TRANSPARENT;
+#endif
+
+ switch ( border )
+ {
+ default:
+ case wxBORDER_DEFAULT:
+ wxFAIL_MSG( _T("unknown border style") );
+ // fall through
+
+ case wxBORDER_NONE:
+ case wxBORDER_SIMPLE:
+ break;
+
+ case wxBORDER_STATIC:
+ *exstyle |= WS_EX_STATICEDGE;
+ break;
+
+ case wxBORDER_RAISED:
+ *exstyle |= WS_EX_DLGMODALFRAME;
+ break;
+
+ case wxBORDER_SUNKEN:
+ *exstyle |= WS_EX_CLIENTEDGE;
+ style &= ~WS_BORDER;
+ break;
+
+ case wxBORDER_DOUBLE:
+ *exstyle |= WS_EX_DLGMODALFRAME;
+ break;
+ }
+
+ // wxUniv doesn't use Windows dialog navigation functions at all
+#if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__)
+ // to make the dialog navigation work with the nested panels we must
+ // use this style (top level windows such as dialogs don't need it)
+ if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() )
+ {
+ *exstyle |= WS_EX_CONTROLPARENT;
+ }
+#endif // __WXUNIVERSAL__
+ }
+
+ return style;
+}
+
+// Setup background and foreground colours correctly
+void wxWindowMSW::SetupColours()
+{
+ if ( GetParent() )
+ SetBackgroundColour(GetParent()->GetBackgroundColour());
+}
+
+bool wxWindowMSW::IsMouseInWindow() const
+{
+ // get the mouse position
+ POINT pt;
+#ifdef __WXWINCE__
+ ::GetCursorPosWinCE(&pt);
+#else
+ ::GetCursorPos(&pt);
+#endif
+
+ // find the window which currently has the cursor and go up the window
+ // chain until we find this window - or exhaust it
+ HWND hwnd = ::WindowFromPoint(pt);
+ while ( hwnd && (hwnd != GetHwnd()) )
+ hwnd = ::GetParent(hwnd);
+
+ return hwnd != NULL;
+}
+
+void wxWindowMSW::OnInternalIdle()
+{
+#ifndef HAVE_TRACKMOUSEEVENT
+ // Check if we need to send a LEAVE event
+ if ( m_mouseInWindow )
+ {
+ // note that we should generate the leave event whether the window has
+ // or doesn't have mouse capture
+ if ( !IsMouseInWindow() )
+ {
+ GenerateMouseLeave();
+ }
+ }
+#endif // !HAVE_TRACKMOUSEEVENT
+
+ if (wxUpdateUIEvent::CanUpdate(this))
+ UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
+}
+
+// Set this window to be the child of 'parent'.
+bool wxWindowMSW::Reparent(wxWindowBase *parent)
+{
+ if ( !wxWindowBase::Reparent(parent) )
+ return false;
+
+ HWND hWndChild = GetHwnd();
+ HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0;
+
+ ::SetParent(hWndChild, hWndParent);
+
+#ifndef __WXWINCE__
+ if ( ::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
+ {
+ EnsureParentHasControlParentStyle(GetParent());
+ }
+#endif // !__WXWINCE__
+
+ return true;
+}
+
+static inline void SendSetRedraw(HWND hwnd, bool on)
+{
+#ifndef __WXMICROWIN__
+ ::SendMessage(hwnd, WM_SETREDRAW, (WPARAM)on, 0);
+#endif
+}
+
+void wxWindowMSW::Freeze()
+{
+ if ( !m_frozenness++ )
+ {
+ if ( IsShown() )
+ SendSetRedraw(GetHwnd(), false);
+ }
+}
+
+void wxWindowMSW::Thaw()
+{
+ wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") );
+
+ if ( --m_frozenness == 0 )
+ {
+ if ( IsShown() )
+ {
+ SendSetRedraw(GetHwnd(), true);
+
+ // we need to refresh everything or otherwise the invalidated area
+ // is not going to be repainted
+ Refresh();
+ }
+ }
+}
+
+void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
+{
+ HWND hWnd = GetHwnd();
+ if ( hWnd )
+ {
+ RECT mswRect;
+ const RECT *pRect;
+ if ( rect )
+ {
+ mswRect.left = rect->x;
+ mswRect.top = rect->y;
+ mswRect.right = rect->x + rect->width;
+ mswRect.bottom = rect->y + rect->height;
+
+ pRect = &mswRect;
+ }
+ else
+ {
+ pRect = NULL;
+ }
+
+ // RedrawWindow not available on SmartPhone or eVC++ 3
+#if !defined(__SMARTPHONE__) && !(defined(_WIN32_WCE) && _WIN32_WCE < 400)
+ UINT flags = RDW_INVALIDATE | RDW_ALLCHILDREN;
+ if ( eraseBack )
+ flags |= RDW_ERASE;
+
+ ::RedrawWindow(hWnd, pRect, NULL, flags);
+#else
+ ::InvalidateRect(hWnd, pRect, eraseBack);
+#endif
+ }
+}
+
+void wxWindowMSW::Update()
+{
+ if ( !::UpdateWindow(GetHwnd()) )
+ {
+ wxLogLastError(_T("UpdateWindow"));
+ }
+
+#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
+ // just calling UpdateWindow() is not enough, what we did in our WM_PAINT
+ // handler needs to be really drawn right now
+ (void)::GdiFlush();
+#endif // __WIN32__
+}
+
+// ---------------------------------------------------------------------------
+// drag and drop
+// ---------------------------------------------------------------------------
+
+#if wxUSE_DRAG_AND_DROP || !defined(__WXWINCE__)
+
+#if wxUSE_STATBOX
+
+// we need to lower the sibling static boxes so controls contained within can be
+// a drop target
+static void AdjustStaticBoxZOrder(wxWindow *parent)
+{
+ // no sibling static boxes if we have no parent (ie TLW)
+ if ( !parent )
+ return;
+
+ for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ wxStaticBox *statbox = wxDynamicCast(node->GetData(), wxStaticBox);
+ if ( statbox )
+ {
+ ::SetWindowPos(GetHwndOf(statbox), HWND_BOTTOM, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ }
+ }
+}
+
+#else // !wxUSE_STATBOX
+
+static inline void AdjustStaticBoxZOrder(wxWindow * WXUNUSED(parent))
+{
+}
+
+#endif // wxUSE_STATBOX/!wxUSE_STATBOX
+
+#endif // drag and drop is used
+
+#if wxUSE_DRAG_AND_DROP
+void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
+{
+ if ( m_dropTarget != 0 ) {
+ m_dropTarget->Revoke(m_hWnd);
+ delete m_dropTarget;
+ }
+
+ m_dropTarget = pDropTarget;
+ if ( m_dropTarget != 0 )
+ {
+ AdjustStaticBoxZOrder(GetParent());
+ m_dropTarget->Register(m_hWnd);
+ }
+}
+#endif // wxUSE_DRAG_AND_DROP
+
+// old-style file manager drag&drop support: we retain the old-style
+// DragAcceptFiles in parallel with SetDropTarget.
+void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept))
+{
+#ifndef __WXWINCE__
+ HWND hWnd = GetHwnd();
+ if ( hWnd )
+ {
+ AdjustStaticBoxZOrder(GetParent());
+ ::DragAcceptFiles(hWnd, (BOOL)accept);
+ }
+#endif
+}
+
+// ----------------------------------------------------------------------------
+// tooltips
+// ----------------------------------------------------------------------------
+
+#if wxUSE_TOOLTIPS
+
+void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip)
+{
+ wxWindowBase::DoSetToolTip(tooltip);
+
+ if ( m_tooltip )
+ m_tooltip->SetWindow((wxWindow *)this);
+}
+
+#endif // wxUSE_TOOLTIPS
+
+// ---------------------------------------------------------------------------
+// moving and resizing
+// ---------------------------------------------------------------------------
+
+bool wxWindowMSW::IsSizeDeferred() const
+{
+#if USE_DEFERRED_SIZING
+ if ( m_pendingPosition != wxDefaultPosition ||
+ m_pendingSize != wxDefaultSize )
+ return true;
+#endif // USE_DEFERRED_SIZING
+
+ return false;
+}
+
+// Get total size
+void wxWindowMSW::DoGetSize(int *x, int *y) const
+{
+#if USE_DEFERRED_SIZING
+ // 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
+#endif // USE_DEFERRED_SIZING
+ {
+ RECT rect = wxGetWindowRect(GetHwnd());
+
+ 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
+{
+#if USE_DEFERRED_SIZING
+ if ( m_pendingSize != wxDefaultSize )
+ {
+ // we need to calculate the client size corresponding to pending size
+ RECT rect;
+ rect.left = m_pendingPosition.x;
+ rect.top = m_pendingPosition.y;
+ rect.right = rect.left + m_pendingSize.x;
+ rect.bottom = rect.top + m_pendingSize.y;
+
+ ::SendMessage(GetHwnd(), WM_NCCALCSIZE, FALSE, (LPARAM)&rect);
+
+ if ( x )
+ *x = rect.right - rect.left;
+ if ( y )
+ *y = rect.bottom - rect.top;
+ }
+ else
+#endif // USE_DEFERRED_SIZING
+ {
+ RECT rect = wxGetClientRect(GetHwnd());
+
+ if ( x )
+ *x = rect.right;
+ if ( y )
+ *y = rect.bottom;
+ }
+}
+
+void wxWindowMSW::DoGetPosition(int *x, int *y) const
+{
+ wxWindow * const parent = GetParent();
+
+ wxPoint pos;
+ if ( m_pendingPosition != wxDefaultPosition )
+ {
+ pos = m_pendingPosition;
+ }
+ else // use current position
+ {
+ RECT rect = wxGetWindowRect(GetHwnd());
+
+ POINT point;
+ point.x = rect.left;
+ point.y = rect.top;
+
+ // we do the adjustments with respect to the parent only for the "real"
+ // children, not for the dialogs/frames
+ if ( !IsTopLevel() )
+ {
+ if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
+ {
+ // In RTL mode, we want the logical left x-coordinate,
+ // which would be the physical right x-coordinate.
+ point.x = rect.right;
+ }
+
+ // 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 = pos.x;
+ if ( y )
+ *y = pos.y;
+}
+
+void wxWindowMSW::DoScreenToClient(int *x, int *y) const
+{
+ POINT pt;
+ if ( x )
+ pt.x = *x;
+ if ( y )
+ pt.y = *y;
+
+ ::ScreenToClient(GetHwnd(), &pt);
+
+ if ( x )
+ *x = pt.x;
+ if ( y )
+ *y = pt.y;
+}
+
+void wxWindowMSW::DoClientToScreen(int *x, int *y) const
+{
+ POINT pt;
+ if ( x )
+ pt.x = *x;
+ if ( y )
+ pt.y = *y;
+
+ ::ClientToScreen(GetHwnd(), &pt);
+
+ if ( x )
+ *x = pt.x;
+ if ( y )
+ *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 | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
+ 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?
+ // Still, negative width or height shouldn't be allowed
+ if (width < 0)
+ width = 0;
+ if (height < 0)
+ height = 0;
+
+ if ( DoMoveSibling(m_hWnd, x, y, width, height) )
+ {
+#if USE_DEFERRED_SIZING
+ 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,
+// but if any of them is equal to -1, it means that we must find the value for
+// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
+// which case -1 is a valid value for x and y)
+//
+// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
+// the width/height to best suit our contents, otherwise we reuse the current
+// width/height
+void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags)
+{
+ // get the current size and position...
+ int currentX, currentY;
+ int currentW, currentH;
+
+ GetPosition(¤tX, ¤tY);
+ GetSize(¤tW, ¤tH);
+
+ // ... and don't do anything (avoiding flicker) if it's already ok unless
+ // we're forced to resize the window
+ if ( x == currentX && y == currentY &&
+ width == currentW && height == currentH &&
+ !(sizeFlags & wxSIZE_FORCE) )
+ {
+ return;
+ }
+
+ if ( x == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
+ x = currentX;
+ if ( y == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
+ y = currentY;
+
+ AdjustForParentClientOrigin(x, y, sizeFlags);
+
+ wxSize size = wxDefaultSize;
+ if ( width == wxDefaultCoord )
+ {
+ if ( sizeFlags & wxSIZE_AUTO_WIDTH )
+ {
+ size = DoGetBestSize();
+ width = size.x;
+ }
+ else
+ {
+ // just take the current one
+ width = currentW;
+ }
+ }
+
+ if ( height == wxDefaultCoord )
+ {
+ if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
+ {
+ if ( size.x == wxDefaultCoord )
+ {
+ size = DoGetBestSize();
+ }
+ //else: already called DoGetBestSize() above
+
+ height = size.y;
+ }
+ else
+ {
+ // just take the current one
+ height = currentH;
+ }
+ }
+
+ DoMoveWindow(x, y, width, height);
+}
+
+void wxWindowMSW::DoSetClientSize(int width, int height)
+{
+ // setting the client size is less obvious than it could have been
+ // because in the result of changing the total size the window scrollbar
+ // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect()
+ // doesn't take neither into account) and so the client size will not be
+ // correct as the difference between the total and client size changes --
+ // so we keep changing it until we get it right
+ //
+ // normally this loop shouldn't take more than 3 iterations (usually 1 but
+ // if scrollbars [dis]appear as the result of the first call, then 2 and it
+ // may become 3 if the window had 0 size originally and so we didn't
+ // calculate the scrollbar correction correctly during the first iteration)
+ // but just to be on the safe side we check for it instead of making it an
+ // "infinite" loop (i.e. leaving break inside as the only way to get out)
+ for ( int i = 0; i < 4; i++ )
+ {
+ RECT rectClient;
+ ::GetClientRect(GetHwnd(), &rectClient);
+
+ // if the size is already ok, stop here (NB: rectClient.left = top = 0)
+ if ( (rectClient.right == width || width == wxDefaultCoord) &&
+ (rectClient.bottom == height || height == wxDefaultCoord) )
+ {
+ break;