diff --git a/configure b/configure index fa8141305a..ca5b78ace9 100755 --- a/configure +++ b/configure @@ -32627,6 +32627,9 @@ $as_echo "$as_me: WARNING: I18n code requires wxFile... disabled" >&2;} fi if test "$wxUSE_XLOCALE" = "yes" ; then + $as_echo "#define wxUSE_XLOCALE 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for complete xlocale" >&5 $as_echo_n "checking for complete xlocale... " >&6; } if ${wx_cv_func_strtod_l+:} false; then : @@ -32676,7 +32679,7 @@ fi $as_echo "$wx_cv_func_strtod_l" >&6; } if test "$wx_cv_func_strtod_l" = "yes" ; then - $as_echo "#define wxUSE_XLOCALE 1" >>confdefs.h + $as_echo "#define HAVE_LOCALE_T 1" >>confdefs.h fi fi diff --git a/configure.in b/configure.in index 9b0bbd969e..8eb3571261 100644 --- a/configure.in +++ b/configure.in @@ -5747,6 +5747,8 @@ if test "$wxUSE_INTL" = "yes" ; then fi if test "$wxUSE_XLOCALE" = "yes" ; then + AC_DEFINE(wxUSE_XLOCALE) + dnl even if xlocale.h exists, it may not contain all that dnl wx needs. check if strtod_l() really is available. AC_CACHE_CHECK([for complete xlocale], @@ -5770,7 +5772,9 @@ if test "$wxUSE_XLOCALE" = "yes" ; then ]) if test "$wx_cv_func_strtod_l" = "yes" ; then - AC_DEFINE(wxUSE_XLOCALE) + dnl We don't test (just) for locale_t existence, but we still define + dnl this symbol to avoid changing the existing code using it. + AC_DEFINE(HAVE_LOCALE_T) fi fi diff --git a/docs/changes.txt b/docs/changes.txt index ef0fd9149e..6dfe7af896 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -443,6 +443,8 @@ wxMSW: - Fix UTF-32 conversion for non-BMP characters (ARATA Mizuki). - Use correct parent for the native modal dialogs (Andreas Falkenhahn). - Fix layout of wxSlider with wxSL_VALUE_LABEL only (gafatoa). +- Fix flicker when resizing columns of report-mode wxListCtrl. +- Implement wxTreeCtrl::SetDoubleBuffered() (Steve Browne). wxOSX/Cocoa: diff --git a/include/wx/msw/missing.h b/include/wx/msw/missing.h index 1b09f730e9..1443a1069e 100644 --- a/include/wx/msw/missing.h +++ b/include/wx/msw/missing.h @@ -141,6 +141,11 @@ #define QS_ALLPOSTMESSAGE 0 #endif +// Missing from MinGW 4.8 SDK headers. +#ifndef BS_TYPEMASK +#define BS_TYPEMASK 0xf +#endif + // ---------------------------------------------------------------------------- // menu stuff // ---------------------------------------------------------------------------- @@ -239,6 +244,10 @@ #define TV_FIRST 0x1100 #endif +#ifndef TVS_EX_DOUBLEBUFFER + #define TVS_EX_DOUBLEBUFFER 0x0004 +#endif + #ifndef TVS_FULLROWSELECT #define TVS_FULLROWSELECT 0x1000 #endif @@ -248,6 +257,11 @@ #define TVM_SETTEXTCOLOR (TV_FIRST + 30) #endif +#ifndef TVM_SETEXTENDEDSTYLE + #define TVM_SETEXTENDEDSTYLE (TV_FIRST + 44) + #define TVM_GETEXTENDEDSTYLE (TV_FIRST + 45) +#endif + // Various defines used by the webview library that are needed by mingw #ifndef DISPID_COMMANDSTATECHANGE diff --git a/include/wx/msw/private.h b/include/wx/msw/private.h index 0b1df5b3e5..69a36d0036 100644 --- a/include/wx/msw/private.h +++ b/include/wx/msw/private.h @@ -978,19 +978,9 @@ inline bool wxStyleHasBorder(long style) wxSUNKEN_BORDER | wxDOUBLE_BORDER)) != 0; } -inline long wxGetWindowExStyle(const wxWindowMSW *win) -{ - return ::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE); -} - inline bool wxHasWindowExStyle(const wxWindowMSW *win, long style) { - return (wxGetWindowExStyle(win) & style) != 0; -} - -inline long wxSetWindowExStyle(const wxWindowMSW *win, long style) -{ - return ::SetWindowLong(GetHwndOf(win), GWL_EXSTYLE, style); + return (::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) & style) != 0; } // Common helper of wxUpdate{,Edit}LayoutDirection() below: sets or clears the diff --git a/include/wx/msw/private/winstyle.h b/include/wx/msw/private/winstyle.h new file mode 100644 index 0000000000..ffb4a2e380 --- /dev/null +++ b/include/wx/msw/private/winstyle.h @@ -0,0 +1,134 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/msw/private/winstyle.h +// Purpose: Small helper class for updating MSW windows style +// Author: Vadim Zeitlin +// Created: 2017-12-09 +// Copyright: (c) 2017 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_MSW_PRIVATE_WINSTYLE_H_ +#define _WX_MSW_PRIVATE_WINSTYLE_H_ + +// ---------------------------------------------------------------------------- +// wxMSWWinLongUpdater +// ---------------------------------------------------------------------------- + +/* + This class is not used directly, but either as wxMSWWinStyleUpdater or + wxMSWWinExStyleUpdater, both of which inherit from it and can be used like + this: + + void SomeFunction() + { + wxMSWWinStyleUpdater updateStyle(GetHwndOf(m_win)); + if ( some-condition ) + updateStyle.TurnOn(XX_YYY); + + // Style update happens here implicitly -- or call Apply(). + } + */ +class wxMSWWinLongUpdater +{ +public: + // Get the current style. + LONG_PTR Get() const + { + return m_styleCurrent; + } + + // Check if the given style bit(s) is (are all) currently turned on. + bool IsOn(LONG_PTR style) const + { + return (m_styleCurrent & style) == style; + } + + // Turn on some bit(s) in the style. + wxMSWWinLongUpdater& TurnOn(LONG_PTR on) + { + m_style |= on; + return *this; + } + + // Turn off some bit(s) in the style. + wxMSWWinLongUpdater& TurnOff(LONG_PTR off) + { + m_style &= ~off; + return *this; + } + + // Turn some bit(s) on or off depending on the condition. + wxMSWWinLongUpdater& TurnOnOrOff(bool cond, LONG_PTR style) + { + return cond ? TurnOn(style) : TurnOff(style); + } + + // Perform the style update (only if necessary, i.e. if the style really + // changed). + // + // Notice that if this method is not called, it's still done from the dtor, + // so it's just a convenient way to do it sooner and avoid having to create + // a new scope for ensuring that the dtor runs at the right place, but + // otherwise is equivalent to do this. + bool Apply() + { + if ( m_style == m_styleCurrent ) + return false; + + ::SetWindowLongPtr(m_hwnd, m_gwlSlot, m_style); + + m_styleCurrent = m_style; + + return true; + } + + ~wxMSWWinLongUpdater() + { + Apply(); + } + +protected: + // Create the object for updating the style or extended style of the given + // window. + // + // Ctor is protected, this class can only be used as wxMSWWinStyleUpdater + // or wxMSWWinExStyleUpdater. + wxMSWWinLongUpdater(HWND hwnd, int gwlSlot) + : m_hwnd(hwnd), + m_gwlSlot(gwlSlot), + m_styleCurrent(::GetWindowLongPtr(hwnd, gwlSlot)), + m_style(m_styleCurrent) + { + } + +private: + const HWND m_hwnd; + const int m_gwlSlot; + + LONG_PTR m_styleCurrent; + LONG_PTR m_style; + + wxDECLARE_NO_COPY_CLASS(wxMSWWinLongUpdater); +}; + +// A variant of wxMSWWinLongUpdater which updates the extended style. +class wxMSWWinStyleUpdater : public wxMSWWinLongUpdater +{ +public: + explicit wxMSWWinStyleUpdater(HWND hwnd) + : wxMSWWinLongUpdater(hwnd, GWL_STYLE) + { + } +}; + +// A variant of wxMSWWinLongUpdater which updates the extended style. +class wxMSWWinExStyleUpdater : public wxMSWWinLongUpdater +{ +public: + explicit wxMSWWinExStyleUpdater(HWND hwnd) + : wxMSWWinLongUpdater(hwnd, GWL_EXSTYLE) + { + } +}; + +#endif // _WX_MSW_PRIVATE_WINSTYLE_H_ diff --git a/include/wx/msw/treectrl.h b/include/wx/msw/treectrl.h index 4a5eb1ea57..e2c1740b11 100644 --- a/include/wx/msw/treectrl.h +++ b/include/wx/msw/treectrl.h @@ -202,15 +202,14 @@ public: // returns true if the platform should explicitly apply a theme border virtual bool CanApplyThemeBorder() const wxOVERRIDE { return false; } + virtual bool IsDoubleBuffered() const wxOVERRIDE; + virtual void SetDoubleBuffered(bool on) wxOVERRIDE; + protected: // Implement "update locking" in a custom way for this control. virtual void DoFreeze() wxOVERRIDE; virtual void DoThaw() wxOVERRIDE; - virtual void DoSetSize(int x, int y, - int width, int height, - int sizeFlags = wxSIZE_AUTO) wxOVERRIDE; - virtual bool MSWShouldSetDefaultFont() const wxOVERRIDE { return false; } // SetImageList helper @@ -336,9 +335,6 @@ private: // whether we need to deselect other items on mouse up bool m_mouseUpDeselect; - // The size to restore the control to when it is thawed, see DoThaw(). - wxSize m_thawnSize; - friend class wxTreeItemIndirectData; friend class wxTreeSortHelper; diff --git a/src/common/intl.cpp b/src/common/intl.cpp index 1fc2b8d989..96dd2389d6 100644 --- a/src/common/intl.cpp +++ b/src/common/intl.cpp @@ -208,12 +208,17 @@ wxString wxLanguageInfo::GetLocaleName() const const char* const orig = wxSetlocale(LC_ALL, NULL); const char* const ret = TrySetLocale(); - if ( !ret ) - return wxString(); + wxString retval; + if ( ret ) + { + // Note that we must copy the returned value before calling setlocale() + // again as the string "ret" points to can (and, at least under Linux + // with glibc, actually always will) be changed by this call. + retval = ret; + wxSetlocale(LC_ALL, orig); + } - wxSetlocale(LC_ALL, orig); - - return ret; + return retval; } // ---------------------------------------------------------------------------- diff --git a/src/common/xlocale.cpp b/src/common/xlocale.cpp index 02c9d2ca2d..e8095a1132 100644 --- a/src/common/xlocale.cpp +++ b/src/common/xlocale.cpp @@ -90,12 +90,10 @@ wxXLocale& wxXLocale::GetCLocale() #if wxUSE_INTL wxXLocale::wxXLocale(wxLanguage lang) { + m_locale = NULL; + const wxLanguageInfo * const info = wxLocale::GetLanguageInfo(lang); - if ( !info ) - { - m_locale = NULL; - } - else + if ( info ) { Init(info->GetLocaleName().c_str()); } diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index 69c407acd3..bb30529579 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -1013,6 +1013,10 @@ wxCairoFontData::wxCairoFontData(wxGraphicsRenderer* renderer, int flags, const wxColour& col) : wxGraphicsObjectRefData(renderer) +#ifdef __WXGTK__ + , m_wxfont(wxFontInfo(wxSize(sizeInPixels, sizeInPixels)) + .AllFlags(flags).FaceName(facename)) +#endif { InitColour(col); diff --git a/src/msw/anybutton.cpp b/src/msw/anybutton.cpp index 9966d89ba4..2ffe67860f 100644 --- a/src/msw/anybutton.cpp +++ b/src/msw/anybutton.cpp @@ -44,6 +44,7 @@ #include "wx/stockitem.h" #include "wx/msw/private/button.h" #include "wx/msw/private/dc.h" +#include "wx/msw/private/winstyle.h" #include "wx/msw/uxtheme.h" #include "wx/private/window.h" @@ -387,15 +388,11 @@ void wxMSWButton::UpdateMultilineStyle(HWND hwnd, const wxString& label) // have to set it whenever the label becomes multi line as otherwise it // wouldn't be shown correctly as we don't use BS_MULTILINE when creating // the control unless it already has new lines in its label) - long styleOld = ::GetWindowLong(hwnd, GWL_STYLE), - styleNew; + wxMSWWinStyleUpdater updateStyle(hwnd); if ( label.find(wxT('\n')) != wxString::npos ) - styleNew = styleOld | BS_MULTILINE; + updateStyle.TurnOn(BS_MULTILINE); else - styleNew = styleOld & ~BS_MULTILINE; - - if ( styleNew != styleOld ) - ::SetWindowLong(hwnd, GWL_STYLE, styleNew); + updateStyle.TurnOff(BS_MULTILINE); } wxSize wxMSWButton::GetFittingSize(wxWindow *win, @@ -1177,11 +1174,7 @@ void wxAnyButton::MakeOwnerDrawn() if ( !IsOwnerDrawn() ) { // make it so - // note that BS_OWNERDRAW is not independent from other style bits - long style = GetWindowLong(GetHwnd(), GWL_STYLE); - style &= ~(BS_3STATE | BS_AUTO3STATE | BS_AUTOCHECKBOX | BS_AUTORADIOBUTTON | BS_CHECKBOX | BS_DEFPUSHBUTTON | BS_GROUPBOX | BS_PUSHBUTTON | BS_RADIOBUTTON | BS_PUSHLIKE); - style |= BS_OWNERDRAW; - SetWindowLong(GetHwnd(), GWL_STYLE, style); + wxMSWWinStyleUpdater(GetHwnd()).TurnOff(BS_TYPEMASK).TurnOn(BS_OWNERDRAW); } } diff --git a/src/msw/combobox.cpp b/src/msw/combobox.cpp index 8361c354c8..47b288f86b 100644 --- a/src/msw/combobox.cpp +++ b/src/msw/combobox.cpp @@ -40,6 +40,7 @@ #include "wx/clipbrd.h" #include "wx/wupdlock.h" #include "wx/msw/private.h" +#include "wx/msw/private/winstyle.h" #if wxUSE_UXTHEME #include "wx/msw/uxtheme.h" @@ -711,11 +712,10 @@ void wxComboBox::SetLayoutDirection(wxLayoutDirection dir) } else { - LONG_PTR style = ::GetWindowLongPtr(GetEditHWND(), GWL_STYLE); - if ( !(style & ES_CENTER) ) + wxMSWWinStyleUpdater styleUpdater(GetEditHWND()); + if ( !styleUpdater.IsOn(ES_CENTER) ) { - style &= ~ES_RIGHT; - ::SetWindowLongPtr(GetEditHWND(), GWL_STYLE, style); + styleUpdater.TurnOff(ES_RIGHT); } } } diff --git a/src/msw/control.cpp b/src/msw/control.cpp index 2f1dcc62a9..9622386229 100644 --- a/src/msw/control.cpp +++ b/src/msw/control.cpp @@ -35,6 +35,8 @@ #include "wx/log.h" #include "wx/settings.h" #include "wx/ctrlsub.h" + #include "wx/msw/private.h" + #include "wx/msw/missing.h" #endif #if wxUSE_LISTCTRL @@ -46,15 +48,10 @@ #endif // wxUSE_TREECTRL #include "wx/renderer.h" -#include "wx/msw/private.h" #include "wx/msw/uxtheme.h" #include "wx/msw/dc.h" // for wxDCTemp #include "wx/msw/ownerdrawnbutton.h" - -// Missing from MinGW 4.8 SDK headers. -#ifndef BS_TYPEMASK -#define BS_TYPEMASK 0xf -#endif +#include "wx/msw/private/winstyle.h" // ---------------------------------------------------------------------------- // wxWin macros @@ -425,14 +422,13 @@ bool wxMSWOwnerDrawnButtonBase::MSWIsOwnerDrawn() const void wxMSWOwnerDrawnButtonBase::MSWMakeOwnerDrawn(bool ownerDrawn) { - long style = ::GetWindowLong(GetHwndOf(m_win), GWL_STYLE); + wxMSWWinStyleUpdater updateStyle(GetHwndOf(m_win)); // note that BS_CHECKBOX & BS_OWNERDRAW != 0 so we can't operate on // them as on independent style bits if ( ownerDrawn ) { - style &= ~BS_TYPEMASK; - style |= BS_OWNERDRAW; + updateStyle.TurnOff(BS_TYPEMASK).TurnOn(BS_OWNERDRAW); m_win->Bind(wxEVT_ENTER_WINDOW, &wxMSWOwnerDrawnButtonBase::OnMouseEnterOrLeave, this); @@ -452,8 +448,7 @@ void wxMSWOwnerDrawnButtonBase::MSWMakeOwnerDrawn(bool ownerDrawn) } else // reset to default colour { - style &= ~BS_OWNERDRAW; - style |= MSWGetButtonStyle(); + updateStyle.TurnOff(BS_OWNERDRAW).TurnOn(MSWGetButtonStyle()); m_win->Unbind(wxEVT_ENTER_WINDOW, &wxMSWOwnerDrawnButtonBase::OnMouseEnterOrLeave, this); @@ -471,7 +466,7 @@ void wxMSWOwnerDrawnButtonBase::MSWMakeOwnerDrawn(bool ownerDrawn) &wxMSWOwnerDrawnButtonBase::OnFocus, this); } - ::SetWindowLong(GetHwndOf(m_win), GWL_STYLE, style); + updateStyle.Apply(); if ( !ownerDrawn ) MSWOnButtonResetOwnerDrawn(); diff --git a/src/msw/gauge.cpp b/src/msw/gauge.cpp index 67fb5b8a63..ac03441790 100644 --- a/src/msw/gauge.cpp +++ b/src/msw/gauge.cpp @@ -35,6 +35,7 @@ #include "wx/appprogress.h" #include "wx/msw/private.h" +#include "wx/msw/private/winstyle.h" // ---------------------------------------------------------------------------- // constants @@ -190,8 +191,7 @@ void wxGauge::SetIndeterminateMode() // Switch the control into indeterminate mode if necessary. if ( !IsInIndeterminateMode() ) { - const long style = ::GetWindowLong(GetHwnd(), GWL_STYLE); - ::SetWindowLong(GetHwnd(), GWL_STYLE, style | PBS_MARQUEE); + wxMSWWinStyleUpdater(GetHwnd()).TurnOn(PBS_MARQUEE); ::SendMessage(GetHwnd(), PBM_SETMARQUEE, TRUE, 0); } } @@ -200,9 +200,8 @@ void wxGauge::SetDeterminateMode() { if ( IsInIndeterminateMode() ) { - const long style = ::GetWindowLong(GetHwnd(), GWL_STYLE); ::SendMessage(GetHwnd(), PBM_SETMARQUEE, FALSE, 0); - ::SetWindowLong(GetHwnd(), GWL_STYLE, style & ~PBS_MARQUEE); + wxMSWWinStyleUpdater(GetHwnd()).TurnOff(PBS_MARQUEE); } } diff --git a/src/msw/headerctrl.cpp b/src/msw/headerctrl.cpp index f8c04f94c5..267775f582 100644 --- a/src/msw/headerctrl.cpp +++ b/src/msw/headerctrl.cpp @@ -38,6 +38,7 @@ #include "wx/msw/wrapcctl.h" #include "wx/msw/private.h" #include "wx/msw/private/customdraw.h" +#include "wx/msw/private/winstyle.h" #ifndef HDM_SETBITMAPMARGIN #define HDM_SETBITMAPMARGIN 0x1234 @@ -402,12 +403,8 @@ void wxHeaderCtrl::DoInsertItem(const wxHeaderColumn& col, unsigned int idx) } } - long controlStyle = ::GetWindowLong(GetHwnd(), GWL_STYLE); - if ( hasResizableColumns ) - controlStyle &= ~HDS_NOSIZING; - else - controlStyle |= HDS_NOSIZING; - ::SetWindowLong(GetHwnd(), GWL_STYLE, controlStyle); + wxMSWWinStyleUpdater(GetHwnd()) + .TurnOnOrOff(!hasResizableColumns, HDS_NOSIZING); } void wxHeaderCtrl::DoSetColumnsOrder(const wxArrayInt& order) diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index ba30bd6e05..d46e7f000d 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -334,6 +334,10 @@ void wxListCtrl::MSWSetExListStyles() // it seems better to enable it by default than disable LVS_EX_HEADERDRAGDROP ); + + // As we use LVS_EX_DOUBLEBUFFER above, we don't need to erase our + // background and doing it only results in flicker. + SetBackgroundStyle(wxBG_STYLE_PAINT); } WXDWORD wxListCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const diff --git a/src/msw/mdi.cpp b/src/msw/mdi.cpp index 514e4eedfe..47f70e1790 100644 --- a/src/msw/mdi.cpp +++ b/src/msw/mdi.cpp @@ -44,6 +44,7 @@ #include "wx/stockitem.h" #include "wx/msw/private.h" +#include "wx/msw/private/winstyle.h" #include @@ -1313,24 +1314,20 @@ bool wxMDIChildFrame::ResetWindowStyle(void *vrect) if (!pChild || (pChild == this)) { HWND hwndClient = GetWinHwnd(pFrameWnd->GetClientWindow()); - DWORD dwStyle = ::GetWindowLong(hwndClient, GWL_EXSTYLE); + + wxMSWWinStyleUpdater updateStyle(hwndClient); // we want to test whether there is a maximized child, so just set // dwThisStyle to 0 if there is no child at all DWORD dwThisStyle = pChild ? ::GetWindowLong(GetWinHwnd(pChild), GWL_STYLE) : 0; - DWORD dwNewStyle = dwStyle; - if ( dwThisStyle & WS_MAXIMIZE ) - dwNewStyle &= ~(WS_EX_CLIENTEDGE); - else - dwNewStyle |= WS_EX_CLIENTEDGE; + updateStyle.TurnOnOrOff(!(dwThisStyle & WS_MAXIMIZE), WS_EX_CLIENTEDGE); - if (dwStyle != dwNewStyle) + if ( updateStyle.Apply() ) { // force update of everything ::RedrawWindow(hwndClient, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN); - ::SetWindowLong(hwndClient, GWL_EXSTYLE, dwNewStyle); ::SetWindowPos(hwndClient, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | diff --git a/src/msw/spinctrl.cpp b/src/msw/spinctrl.cpp index b51c10a605..a692a5044e 100644 --- a/src/msw/spinctrl.cpp +++ b/src/msw/spinctrl.cpp @@ -36,6 +36,7 @@ #endif #include "wx/msw/private.h" +#include "wx/msw/private/winstyle.h" #if wxUSE_TOOLTIPS #include "wx/tooltip.h" @@ -549,15 +550,8 @@ void wxSpinCtrl::UpdateBuddyStyle() // otherwise this would become impossible and also if we don't use // hexadecimal as entering "x" of the "0x" prefix wouldn't be allowed // neither then - const DWORD styleOld = ::GetWindowLong(GetBuddyHwnd(), GWL_STYLE); - DWORD styleNew; - if ( m_min < 0 || GetBase() != 10 ) - styleNew = styleOld & ~ES_NUMBER; - else - styleNew = styleOld | ES_NUMBER; - - if ( styleNew != styleOld ) - ::SetWindowLong(GetBuddyHwnd(), GWL_STYLE, styleNew); + wxMSWWinStyleUpdater(GetBuddyHwnd()) + .TurnOnOrOff(m_min >= 0 && GetBase() == 10, ES_NUMBER); } // ---------------------------------------------------------------------------- diff --git a/src/msw/statbmp.cpp b/src/msw/statbmp.cpp index dbe99d8fd7..4add948108 100644 --- a/src/msw/statbmp.cpp +++ b/src/msw/statbmp.cpp @@ -36,6 +36,7 @@ #include "wx/msw/private.h" #include "wx/msw/dib.h" +#include "wx/msw/private/winstyle.h" #include "wx/sysopt.h" @@ -312,9 +313,9 @@ void wxStaticBitmap::SetImageNoCopy( wxGDIImage* image) } } #endif // wxUSE_WXDIB - LONG style = ::GetWindowLong( (HWND)GetHWND(), GWL_STYLE ) ; - ::SetWindowLong( (HWND)GetHWND(), GWL_STYLE, ( style & ~( SS_BITMAP|SS_ICON ) ) | - ( m_isIcon ? SS_ICON : SS_BITMAP ) ); + wxMSWWinStyleUpdater(GetHwnd()) + .TurnOff(SS_BITMAP | SS_ICON) + .TurnOn(m_isIcon ? SS_ICON : SS_BITMAP); MSWReplaceImageHandle((WXLPARAM)handle); diff --git a/src/msw/statbox.cpp b/src/msw/statbox.cpp index 5ba29f58f6..9ae5c230df 100644 --- a/src/msw/statbox.cpp +++ b/src/msw/statbox.cpp @@ -45,6 +45,7 @@ #include "wx/msw/private.h" #include "wx/msw/missing.h" #include "wx/msw/dc.h" +#include "wx/msw/private/winstyle.h" // the values coincide with those in tmschema.h #define BP_GROUPBOX 4 @@ -303,10 +304,10 @@ WXHRGN wxStaticBox::MSWGetRegionWithoutChildren() continue; } - LONG style = ::GetWindowLong(child, GWL_STYLE); + wxMSWWinStyleUpdater updateStyle(child); wxString str(wxGetWindowClass(child)); str.UpperCase(); - if ( str == wxT("BUTTON") && (style & BS_GROUPBOX) == BS_GROUPBOX ) + if ( str == wxT("BUTTON") && updateStyle.IsOn(BS_GROUPBOX) ) { if ( child == GetHwnd() ) foundThis = true; @@ -329,10 +330,9 @@ WXHRGN wxStaticBox::MSWGetRegionWithoutChildren() { // need to remove WS_CLIPSIBLINGS from all sibling windows // that are within this staticbox if set - if ( style & WS_CLIPSIBLINGS ) + if ( updateStyle.IsOn(WS_CLIPSIBLINGS) ) { - style &= ~WS_CLIPSIBLINGS; - ::SetWindowLong(child, GWL_STYLE, style); + updateStyle.TurnOff(WS_CLIPSIBLINGS).Apply(); // MSDN: "If you have changed certain window data using // SetWindowLong, you must call SetWindowPos to have the diff --git a/src/msw/stattext.cpp b/src/msw/stattext.cpp index 62dd20512b..97b28d06e8 100644 --- a/src/msw/stattext.cpp +++ b/src/msw/stattext.cpp @@ -28,6 +28,7 @@ #endif #include "wx/msw/private.h" +#include "wx/msw/private/winstyle.h" bool wxStaticText::Create(wxWindow *parent, wxWindowID id, @@ -155,25 +156,21 @@ void wxStaticText::SetLabel(const wxString& label) return; #ifdef SS_ENDELLIPSIS - long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE); + wxMSWWinStyleUpdater updateStyle(GetHwnd()); if ( HasFlag(wxST_ELLIPSIZE_END) ) { // adding SS_ENDELLIPSIS or SS_ENDELLIPSIS "disables" the correct // newline handling in static texts: the newlines in the labels are // shown as square. Thus we don't use it even on newer OS when // the static label contains a newline. - if ( label.Contains(wxT('\n')) ) - styleReal &= ~SS_ENDELLIPSIS; - else - styleReal |= SS_ENDELLIPSIS; - - ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal); + updateStyle.TurnOnOrOff(!label.Contains(wxT('\n')), SS_ENDELLIPSIS); } else // style not supported natively { - styleReal &= ~SS_ENDELLIPSIS; - ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal); + updateStyle.TurnOff(SS_ENDELLIPSIS); } + + updateStyle.Apply(); #endif // SS_ENDELLIPSIS // save the label in m_labelOrig with both the markup (if any) and @@ -181,7 +178,7 @@ void wxStaticText::SetLabel(const wxString& label) m_labelOrig = label; #ifdef SS_ENDELLIPSIS - if ( styleReal & SS_ENDELLIPSIS ) + if ( updateStyle.IsOn(SS_ENDELLIPSIS) ) DoSetLabel(GetLabel()); else #endif // SS_ENDELLIPSIS diff --git a/src/msw/textentry.cpp b/src/msw/textentry.cpp index cd33b0c120..97956296ab 100644 --- a/src/msw/textentry.cpp +++ b/src/msw/textentry.cpp @@ -34,6 +34,7 @@ #include "wx/dynlib.h" #include "wx/msw/private.h" +#include "wx/msw/private/winstyle.h" #if wxUSE_UXTHEME #include "wx/msw/uxtheme.h" @@ -913,9 +914,7 @@ void wxTextEntry::ForceUpper() { ConvertToUpperCase(); - const HWND hwnd = GetEditHwnd(); - const LONG styleOld = ::GetWindowLong(hwnd, GWL_STYLE); - ::SetWindowLong(hwnd, GWL_STYLE, styleOld | ES_UPPERCASE); + wxMSWWinStyleUpdater(GetEditHwnd()).TurnOn(ES_UPPERCASE); } // ---------------------------------------------------------------------------- diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 4d7e00cc54..4c96e1c13c 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -41,6 +41,7 @@ #include "wx/tooltip.h" #include "wx/msw/private.h" +#include "wx/msw/private/winstyle.h" #include "wx/msw/winundef.h" #include "wx/msw/missing.h" @@ -858,14 +859,14 @@ bool wxTopLevelWindowMSW::ShowFullScreen(bool show, long style) // zap the frame borders // save the 'normal' window style - m_fsOldWindowStyle = GetWindowLong(GetHwnd(), GWL_STYLE); + wxMSWWinStyleUpdater updateStyle(GetHwnd()); + m_fsOldWindowStyle = updateStyle.Get(); // save the old position, width & height, maximize state m_fsOldSize = GetRect(); m_fsIsMaximized = IsMaximized(); // decide which window style flags to turn off - LONG newStyle = m_fsOldWindowStyle; LONG offFlags = 0; if (style & wxFULLSCREEN_NOBORDER) @@ -876,16 +877,16 @@ bool wxTopLevelWindowMSW::ShowFullScreen(bool show, long style) if (style & wxFULLSCREEN_NOCAPTION) offFlags |= WS_CAPTION | WS_SYSMENU; - newStyle &= ~offFlags; + updateStyle.TurnOff(offFlags); // Full screen windows should logically be popups as they don't have // decorations (and are definitely not children) and while not using // this style doesn't seem to make any difference for most windows, it // breaks wxGLCanvas in some cases, see #15434, so just always use it. - newStyle |= WS_POPUP; + updateStyle.TurnOn(WS_POPUP); // change our window style to be compatible with full-screen mode - ::SetWindowLong(GetHwnd(), GWL_STYLE, newStyle); + updateStyle.Apply(); wxRect rect; #if wxUSE_DISPLAY @@ -1137,19 +1138,18 @@ wxMenu *wxTopLevelWindowMSW::MSWGetSystemMenu() const bool wxTopLevelWindowMSW::SetTransparent(wxByte alpha) { - LONG exstyle = GetWindowLong(GetHwnd(), GWL_EXSTYLE); + wxMSWWinExStyleUpdater updateExStyle(GetHwnd()); // if setting alpha to fully opaque then turn off the layered style if (alpha == 255) { - SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyle & ~WS_EX_LAYERED); + updateExStyle.TurnOff(WS_EX_LAYERED).Apply(); Refresh(); return true; } // Otherwise, set the layered style if needed and set the alpha value - if ((exstyle & WS_EX_LAYERED) == 0 ) - SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyle | WS_EX_LAYERED); + updateExStyle.TurnOn(WS_EX_LAYERED).Apply(); if ( ::SetLayeredWindowAttributes(GetHwnd(), 0, (BYTE)alpha, LWA_ALPHA) ) return true; diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index 1082912d9b..d7e9094a02 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -40,6 +40,7 @@ #include "wx/msw/private.h" #include "wx/msw/winundef.h" +#include "wx/msw/private/winstyle.h" #include "wx/imaglist.h" #include "wx/itemattr.h" @@ -795,6 +796,46 @@ bool wxTreeCtrl::Create(wxWindow *parent, return true; } +bool wxTreeCtrl::IsDoubleBuffered() const +{ + if ( !GetHwnd() ) + return false; + + // Notice that TVM_GETEXTENDEDSTYLE is supported since XP, so we can always + // send this message, no need for comctl32.dll version check here. + const LRESULT + exTreeStyle = ::SendMessage(GetHwnd(), TVM_GETEXTENDEDSTYLE, 0, 0); + + return (exTreeStyle & TVS_EX_DOUBLEBUFFER) != 0; +} + +void wxTreeCtrl::SetDoubleBuffered(bool on) +{ + if ( !GetHwnd() ) + return; + + // TVS_EX_DOUBLEBUFFER is only supported since Vista, don't try to set it + // under XP, who knows what could this do. + if ( wxApp::GetComCtl32Version() >= 610 ) + { + const HRESULT hr = ::SendMessage(GetHwnd(), + TVM_SETEXTENDEDSTYLE, + TVS_EX_DOUBLEBUFFER, + on ? TVS_EX_DOUBLEBUFFER : 0); + if ( hr == S_OK ) + { + // There is no need to erase background for a double-buffered + // window, so disable it when enabling double buffering and restore + // the default background style value when disabling it. + SetBackgroundStyle(on ? wxBG_STYLE_PAINT : wxBG_STYLE_ERASE); + } + else + { + wxLogApiError("TreeView_SetExtendedStyle(TVS_EX_DOUBLEBUFFER)", hr); + } + } +} + wxTreeCtrl::~wxTreeCtrl() { m_isBeingDeleted = true; @@ -3898,47 +3939,21 @@ void wxTreeCtrl::DoSetItemState(const wxTreeItemId& item, int state) // Update locking. // ---------------------------------------------------------------------------- -// Using WM_SETREDRAW with the native control is a bad idea as it's broken in -// some Windows versions (see http://support.microsoft.com/kb/130611) and -// doesn't seem to do anything in other ones (e.g. under Windows 7 the tree -// control keeps updating its scrollbars while the items are added to it, -// resulting in horrible flicker when adding even a couple of dozen items). -// So we resize it to the smallest possible size instead of freezing -- this -// still flickers, but actually not as badly as it would if we didn't do it. - void wxTreeCtrl::DoFreeze() { - if ( IsShown() ) - { - RECT rc; - ::GetWindowRect(GetHwnd(), &rc); - m_thawnSize = wxRectFromRECT(rc).GetSize(); + wxTreeCtrlBase::DoFreeze(); - ::SetWindowPos(GetHwnd(), 0, 0, 0, 1, 1, - SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); - } + // In addition to disabling redrawing, we also need to disable scrollbar + // updates that would still happen otherwise. + wxMSWWinStyleUpdater(GetHwnd()).TurnOn(TVS_NOSCROLL); } void wxTreeCtrl::DoThaw() { - if ( IsShown() ) - { - if ( m_thawnSize != wxDefaultSize ) - { - ::SetWindowPos(GetHwnd(), 0, 0, 0, m_thawnSize.x, m_thawnSize.y, - SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); - } - } -} + // Undo temporary TVS_NOSCROLL addition. + wxMSWWinStyleUpdater(GetHwnd()).TurnOff(TVS_NOSCROLL); -// We also need to override DoSetSize() to ensure that m_thawnSize is reset if -// the window is resized while being frozen -- in this case, we need to avoid -// resizing it back to its original, pre-freeze, size when it's thawed. -void wxTreeCtrl::DoSetSize(int x, int y, int width, int height, int sizeFlags) -{ - m_thawnSize = wxDefaultSize; - - wxTreeCtrlBase::DoSetSize(x, y, width, height, sizeFlags); + wxTreeCtrlBase::DoThaw(); } #endif // wxUSE_TREECTRL diff --git a/src/msw/window.cpp b/src/msw/window.cpp index c6abb2fce2..ea92c52ed0 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -79,6 +79,7 @@ #include "wx/msw/private.h" #include "wx/msw/private/keyboard.h" +#include "wx/msw/private/winstyle.h" #include "wx/msw/dcclient.h" #include "wx/msw/seh.h" #include "wx/private/textmeasure.h" @@ -341,12 +342,8 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent) */ while ( parent && !parent->IsTopLevel() ) { - LONG exStyle = wxGetWindowExStyle(parent); - if ( !(exStyle & WS_EX_CONTROLPARENT) ) - { - // force the parent to have this style - wxSetWindowExStyle(parent, exStyle | WS_EX_CONTROLPARENT); - } + // force the parent to have this style + wxMSWWinExStyleUpdater(GetHwndOf(parent)).TurnOn(WS_EX_CONTROLPARENT); parent = parent->GetParent(); } @@ -1406,11 +1403,8 @@ void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld) // 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); + wxMSWWinStyleUpdater updateStyle(GetHwnd()); + updateStyle.TurnOff(styleOld).TurnOn(style); // we need to call SetWindowPos() if any of the styles affecting the // frame appearance have changed @@ -1424,15 +1418,9 @@ void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld) } // and the extended style - long exstyleReal = wxGetWindowExStyle(this); - - if ( exstyle != exstyleOld ) + wxMSWWinExStyleUpdater updateExStyle(GetHwnd()); + if ( updateExStyle.TurnOff(exstyleOld).TurnOn(exstyle).Apply() ) { - exstyleReal &= ~exstyleOld; - exstyleReal |= exstyle; - - wxSetWindowExStyle(this, exstyleReal); - // ex style changes don't take effect without calling SetWindowPos callSWP = true; } @@ -1443,8 +1431,8 @@ void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld) // 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, + updateExStyle.IsOn(WS_EX_TOPMOST) ? HWND_TOPMOST + : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED) ) @@ -2434,7 +2422,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // must not call IsDialogMessage() then, it would simply hang (see #15458). if ( m_hWnd && HasFlag(wxTAB_TRAVERSAL) && - (wxGetWindowExStyle(this) & WS_EX_CONTROLPARENT) ) + wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) ) { // intercept dialog navigation keys MSG *msg = (MSG *)pMsg; @@ -4470,17 +4458,7 @@ bool wxWindowMSW::IsDoubleBuffered() const void wxWindowMSW::SetDoubleBuffered(bool on) { - // Get the current extended style bits - long exstyle = wxGetWindowExStyle(this); - - // Twiddle the bit as needed - if ( on ) - exstyle |= WS_EX_COMPOSITED; - else - exstyle &= ~WS_EX_COMPOSITED; - - // put it back - wxSetWindowExStyle(this, exstyle); + wxMSWWinExStyleUpdater(GetHwnd()).TurnOnOrOff(on, WS_EX_COMPOSITED); } // --------------------------------------------------------------------------- diff --git a/src/propgrid/manager.cpp b/src/propgrid/manager.cpp index 05872f8880..75acf2c64e 100644 --- a/src/propgrid/manager.cpp +++ b/src/propgrid/manager.cpp @@ -1508,10 +1508,8 @@ void wxPropertyGridManager::RecreateControls() #define WS_EX_COMPOSITED 0x02000000L #endif - HWND hWnd = (HWND)m_pToolbar->GetHWND(); - - ::SetWindowLong( hWnd, GWL_EXSTYLE, - ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED ); + wxMSWWinExStyleUpdater(GetHwndOf(m_pToolbar)) + .TurnOn(WS_EX_COMPOSITED); */ #endif diff --git a/tests/intl/intltest.cpp b/tests/intl/intltest.cpp index ecf8770640..4e39762a0f 100644 --- a/tests/intl/intltest.cpp +++ b/tests/intl/intltest.cpp @@ -42,7 +42,6 @@ private: CPPUNIT_TEST( Domain ); CPPUNIT_TEST( Headers ); CPPUNIT_TEST( DateTimeFmtFrench ); - CPPUNIT_TEST( DateTimeFmtC ); CPPUNIT_TEST( IsAvailable ); CPPUNIT_TEST_SUITE_END(); @@ -50,7 +49,6 @@ private: void Domain(); void Headers(); void DateTimeFmtFrench(); - void DateTimeFmtC(); void IsAvailable(); static wxString GetDecimalPoint() @@ -189,50 +187,27 @@ void IntlTestCase::DateTimeFmtFrench() #else static const char *FRENCH_DATE_FMT = "%d/%m/%Y"; static const char *FRENCH_LONG_DATE_FMT = "%A %d %B %Y"; -#ifdef __WXOSX__ - static const char *FRENCH_DATE_TIME_FMT = "%A %d %B %Y %H:%M:%S"; -#else static const char *FRENCH_DATE_TIME_FMT = "%d/%m/%Y %H:%M:%S"; -#endif #endif WX_ASSERT_EQUAL_FORMAT( "French short date", FRENCH_DATE_FMT, - m_locale->GetInfo(wxLOCALE_SHORT_DATE_FMT) ); + wxLocale::GetInfo(wxLOCALE_SHORT_DATE_FMT) ); WX_ASSERT_EQUAL_FORMAT( "French long date", FRENCH_LONG_DATE_FMT, - m_locale->GetInfo(wxLOCALE_LONG_DATE_FMT) ); - WX_ASSERT_EQUAL_FORMAT( "French date and time", FRENCH_DATE_TIME_FMT, - m_locale->GetInfo(wxLOCALE_DATE_TIME_FMT) ); - WX_ASSERT_EQUAL_FORMAT( "French time", "%H:%M:%S", - m_locale->GetInfo(wxLOCALE_TIME_FMT) ); -} + wxLocale::GetInfo(wxLOCALE_LONG_DATE_FMT) ); -void IntlTestCase::DateTimeFmtC() -{ - // again, glibc uses different defaults -#ifdef __GLIBC__ - static const char *C_DATE_FMT = "%m/%d/%y"; - static const char *C_LONG_DATE_FMT = "%a %b %d %Y"; - static const char *C_DATE_TIME_FMT = "%a %b %d %H:%M:%S %Y"; -#else - static const char *C_DATE_FMT = "%d/%m/%Y"; - static const char *C_LONG_DATE_FMT = "%A %d %B %Y"; + const wxString fmtDT = wxLocale::GetInfo(wxLOCALE_DATE_TIME_FMT); #ifdef __WXOSX__ - static const char *C_DATE_TIME_FMT = "%A %d %B %Y %H:%M:%S"; + // Things are difficult to test under macOS as the format keeps changing, + // e.g. at some time between 10.10 and 10.12 a new " à " string appeared in + // its middle, so test it piece-wise and hope it doesn't change too much. + INFO("French date and time format is \"" << fmtDT << "\""); + CHECK( fmtDT.StartsWith("%A %d %B %Y") ); + CHECK( fmtDT.EndsWith("%H:%M:%S") ); #else - static const char *C_DATE_TIME_FMT = "%d/%m/%Y %H:%M:%S"; + WX_ASSERT_EQUAL_FORMAT( "French date and time", FRENCH_DATE_TIME_FMT, fmtDT ); #endif -#endif - - setlocale(LC_ALL, "C"); - - WX_ASSERT_EQUAL_FORMAT( "C short date", C_DATE_FMT, - m_locale->GetInfo(wxLOCALE_SHORT_DATE_FMT) ); - WX_ASSERT_EQUAL_FORMAT( "C long date", C_LONG_DATE_FMT, - m_locale->GetInfo(wxLOCALE_LONG_DATE_FMT) ); - WX_ASSERT_EQUAL_FORMAT( "C date and time", C_DATE_TIME_FMT, - m_locale->GetInfo(wxLOCALE_DATE_TIME_FMT) ); - WX_ASSERT_EQUAL_FORMAT( "C time", "%H:%M:%S", - m_locale->GetInfo(wxLOCALE_TIME_FMT) ); + WX_ASSERT_EQUAL_FORMAT( "French time", "%H:%M:%S", + wxLocale::GetInfo(wxLOCALE_TIME_FMT) ); } void IntlTestCase::IsAvailable()