wxMSW:
-- Fixed erroneous selection of content in wxComboBox when within a wxStaticBox.
+- Fixed erroneous selection of content in wxComboBox when within a wxStaticBox
+ (checking for selection caused by WM_STYLECHANGED).
+- Worked around an apparent bug in Windows whereby some deferred positioning
+ failed: specifically when changing a position from x, to y, to x again.
+- Added deferred positioning to wxRadioBox, wxSlider and wxSpinCtrl and thereby
+ eliminated some refresh glitches when resizing.
+- Eliminated further refresh glitches caused by wxRadioBox (to nearby controls)
+ by refreshing parent when the radio box moves.
+- Added ability set the system option "msw.staticbox.optimized-paint" to 0 to
+ allow a panel to paint graphics around controls within a static box.
wxMac:
\twocolitem{msw.staticbitmap.htclient}{If set to 1, allows the static bitmap to respond to mouse
events. The default is 0, since a value of 1 can interfere with refresh in static boxes. Note that once set,
this option cannot be unset later in the application.}
+\twocolitem{msw.staticbox.optimized-paint}{If set to 0, switches off optimized wxStaticBox painting.
+Setting this to 0 causes more flicker, but allows applications to paint graphics on the parent of a static box
+(the optimized refresh causes any such drawing to disappear).}
\end{twocollist}
\wxheading{Mac}
wxSUNKEN_BORDER | wxDOUBLE_BORDER)) != 0;
}
+// Deferred window moving
+bool wxMoveWindowDeferred(HDWP& hdwp, wxWindow* win, HWND hWnd, int x, int y, int width, int height);
+
// ----------------------------------------------------------------------------
// functions mapping HWND to wxWindow
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxWindowMSW : public wxWindowBase
{
+ friend class wxSpinCtrl;
+ friend class wxSlider;
+ friend class wxRadioBox;
public:
wxWindowMSW() { Init(); }
extern wxWinHashTable *wxWinHandleHash;
+// ----------------------------------------------------------------------------
+// extra data needed for correcting problems with deferred positioning
+// ----------------------------------------------------------------------------
+
+struct wxExtraWindowData
+{
+ // Stored during deferred positioning
+ wxPoint m_pos;
+ wxSize m_size;
+ bool m_deferring:1;
+};
+
#endif
// _WX_WINDOW_H_
#include "wx/msw/subwin.h"
+#define USE_DEFERRED_SIZING 1
+
#if wxUSE_TOOLTIPS
#if !defined(__GNUWIN32_OLD__) || defined(__CYGWIN10__)
#include <commctrl.h>
height = heightOld;
}
- ::MoveWindow(GetHwnd(), xx, yy, width, height, TRUE);
+ // 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(), xx, yy, width, height);
// Now position all the buttons: the current button will be put at
// wxPoint(x_offset, y_offset) and the new row/column will start at
x_offset += widthBtn + cx1;
}
}
+ if (hdwp)
+ {
+ // Store the size so we can report it accurately
+ wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved;
+ if (!extraData)
+ {
+ extraData = new wxExtraWindowData;
+ m_windowReserved = (void*) extraData;
+ }
+ extraData->m_pos = wxPoint(xx, yy);
+ extraData->m_size = wxSize(width, height);
+ extraData->m_deferring = true;
+
+ // hdwp must be updated as it may have been changed
+ parent->m_hDWP = (WXHANDLE)hdwp;
+ }
}
// ----------------------------------------------------------------------------
return 0;
}
+ // FIXME: Without this, the radiobox corrupts other controls as it moves
+ // in a dynamic layout. Refreshing causes flicker, but it's better than
+ // leaving droppings. Note that for some reason, wxStaticBox doesn't need
+ // this (perhaps because it has no real children?)
+ else if (nMsg == WM_MOVE && IsKindOf(CLASSINFO(wxRadioBox)))
+ {
+ WXLRESULT res = wxControl::MSWWindowProc(nMsg, wParam, lParam);
+ wxRect rect = GetRect();
+ GetParent()->Refresh(true, & rect);
+ return res;
+ }
return wxStaticBox::MSWWindowProc(nMsg, wParam, lParam);
}
#include <commctrl.h>
#endif
+#define USE_DEFERRED_SIZING 1
+
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
return;
}
+ // 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
+
// be careful to position the slider itself after moving the labels as
// otherwise our GetBoundingBox(), which is called from WM_SIZE handler,
// would return a wrong result and wrong size would be cached internally
// position all labels: min at the top, value in the middle and max at
// the bottom
- ::MoveWindow((*m_labels)[SliderLabel_Min],
- xLabel, y, wLabel, hLabel, TRUE);
+ wxMoveWindowDeferred(hdwp, this, (*m_labels)[SliderLabel_Min],
+ xLabel, y, wLabel, hLabel);
- ::MoveWindow((*m_labels)[SliderLabel_Value],
- xLabel, y + (height - hLabel)/2, wLabel, hLabel, TRUE);
+ wxMoveWindowDeferred(hdwp, this, (*m_labels)[SliderLabel_Value],
+ xLabel, y + (height - hLabel)/2, wLabel, hLabel);
- ::MoveWindow((*m_labels)[SliderLabel_Max],
- xLabel, y + height - hLabel, wLabel, hLabel, TRUE);
+ wxMoveWindowDeferred(hdwp, this, (*m_labels)[SliderLabel_Max],
+ xLabel, y + height - hLabel, wLabel, hLabel);
// position the slider itself along the left/right edge
- ::MoveWindow(GetHwnd(),
+ wxMoveWindowDeferred(hdwp, this, GetHwnd(),
HasFlag(wxSL_LEFT) ? x : x + wLabel + HGAP,
y + hLabel/2,
width - wLabel - HGAP,
- height - hLabel,
- TRUE);
+ height - hLabel);
}
else // horizontal
{
// position all labels: min on the left, value in the middle and max to
// the right
- ::MoveWindow((*m_labels)[SliderLabel_Min],
- x, yLabel, wLabel, hLabel, TRUE);
+ wxMoveWindowDeferred(hdwp, this, (*m_labels)[SliderLabel_Min],
+ x, yLabel, wLabel, hLabel);
- ::MoveWindow((*m_labels)[SliderLabel_Value],
- x + (width - wLabel)/2, yLabel, wLabel, hLabel, TRUE);
+ wxMoveWindowDeferred(hdwp, this, (*m_labels)[SliderLabel_Value],
+ x + (width - wLabel)/2, yLabel, wLabel, hLabel);
- ::MoveWindow((*m_labels)[SliderLabel_Max],
- x + width - wLabel, yLabel, wLabel, hLabel, TRUE);
+ wxMoveWindowDeferred(hdwp, this, (*m_labels)[SliderLabel_Max],
+ x + width - wLabel, yLabel, wLabel, hLabel);
// position the slider itself along the top/bottom edge
- ::MoveWindow(GetHwnd(),
+ wxMoveWindowDeferred(hdwp, this, GetHwnd(),
x,
HasFlag(wxSL_TOP) ? y : y + hLabel,
width,
- height - hLabel,
- TRUE);
+ height - hLabel);
+ }
+ if ( hdwp )
+ {
+ // Store the size so we can report it accurately
+ wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved;
+ if (!extraData)
+ {
+ extraData = new wxExtraWindowData;
+ m_windowReserved = (void*) extraData;
+ }
+ extraData->m_pos = wxPoint(x, y);
+ extraData->m_size = wxSize(width, height);
+ extraData->m_deferring = true;
+
+ // hdwp must be updated as it may have been changed
+ parent->m_hDWP = (WXHANDLE)hdwp;
}
}
#include <limits.h> // for INT_MIN
+#define USE_DEFERRED_SIZING 1
+
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
wxLogDebug(_T("not enough space for wxSpinCtrl!"));
}
- if ( !::MoveWindow(GetBuddyHwnd(), x, y, widthText, height, TRUE) )
- {
- wxLogLastError(wxT("MoveWindow(buddy)"));
- }
+ // if our parent had prepared a defer window handle for us, use it (unless
+ // we are a top level window)
+ wxWindowMSW *parent = GetParent();
+ int originalX = x;
+
+#if USE_DEFERRED_SIZING
+ HDWP hdwp = parent && !IsTopLevel() ? (HDWP)parent->m_hDWP : NULL;
+#else
+ HDWP hdwp = 0;
+#endif
+
+ // 1) The buddy window
+ wxMoveWindowDeferred(hdwp, this, GetBuddyHwnd(),
+ x, y, widthText, height);
+ // 2) The button window
x += widthText + MARGIN_BETWEEN;
- if ( !::MoveWindow(GetHwnd(), x, y, widthBtn, height, TRUE) )
+ wxMoveWindowDeferred(hdwp, this, GetHwnd(),
+ x, y, widthBtn, height);
+
+ if (hdwp)
{
- wxLogLastError(wxT("MoveWindow"));
+ // Store the size so we can report it accurately
+ wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved;
+ if (!extraData)
+ {
+ extraData = new wxExtraWindowData;
+ m_windowReserved = (void*) extraData;
+ }
+ extraData->m_pos = wxPoint(originalX, y);
+ extraData->m_size = wxSize(width, height);
+ extraData->m_deferring = true;
+
+ // hdwp must be updated as it may have been changed
+ parent->m_hDWP = (WXHANDLE)hdwp;
}
}
// get total size of the control
void wxSpinCtrl::DoGetSize(int *x, int *y) const
{
+ wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved;
+ if (extraData && extraData->m_deferring && GetParent() && GetParent()->m_hDWP)
+ {
+ *x = extraData->m_size.x;
+ *y = extraData->m_size.y;
+ return;
+ }
+
RECT spinrect, textrect, ctrlrect;
GetWindowRect(GetHwnd(), &spinrect);
GetWindowRect(GetBuddyHwnd(), &textrect);
void wxSpinCtrl::DoGetPosition(int *x, int *y) const
{
+ wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved;
+ if (extraData && extraData->m_deferring && GetParent() && GetParent()->m_hDWP)
+ {
+ *x = extraData->m_pos.x;
+ *y = extraData->m_pos.y;
+ return;
+ }
+
// hack: pretend that our HWND is the text control just for a moment
WXHWND hWnd = GetHWND();
wxConstCast(this, wxSpinCtrl)->m_hWnd = m_hwndBuddy;
#define HAVE_TRACKMOUSEEVENT
#endif // everything needed for TrackMouseEvent()
+#define USE_DEFERRED_SIZING 1
+
// ---------------------------------------------------------------------------
// global variables
// ---------------------------------------------------------------------------
{
m_isBeingDeleted = true;
+ if (m_windowReserved)
+ {
+ delete (wxExtraWindowData*) m_windowReserved;
+ m_windowReserved = NULL;
+ }
+
#ifndef __WXUNIVERSAL__
// VS: make sure there's no wxFrame with last focus set to us:
for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
// Get total size
void wxWindowMSW::DoGetSize(int *x, int *y) const
{
+ wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved;
+ if (extraData && extraData->m_deferring && GetParent() && GetParent()->m_hDWP)
+ {
+ *x = extraData->m_size.x;
+ *y = extraData->m_size.y;
+ return;
+ }
+
RECT rect = wxGetWindowRect(GetHwnd());
if ( x )
// Get size *available for subwindows* i.e. excluding menu bar etc.
void wxWindowMSW::DoGetClientSize(int *x, int *y) const
{
+ wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved;
+ if (extraData && extraData->m_deferring && GetParent() && GetParent()->m_hDWP)
+ {
+ *x = extraData->m_pos.x;
+ *y = extraData->m_pos.y;
+ return;
+ }
+
RECT rect = wxGetClientRect(GetHwnd());
if ( x )
// 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 ( hdwp )
{
- hdwp = ::DeferWindowPos(hdwp, GetHwnd(), NULL,
- x, y, width, height,
- SWP_NOZORDER);
- if ( !hdwp )
+ // Store the size so we can report it accurately
+ wxExtraWindowData* extraData = (wxExtraWindowData*) m_windowReserved;
+ if (!extraData)
{
- wxLogLastError(_T("DeferWindowPos"));
+ extraData = new wxExtraWindowData;
+ m_windowReserved = (void*) extraData;
}
+ extraData->m_pos = wxPoint(x, y);
+ extraData->m_size = wxSize(width, height);
+ extraData->m_deferring = true;
// 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"));
- }
- }
}
// set the size of the window: if the dimensions are positive, just use them,
#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__