diff --git a/include/wx/msw/private.h b/include/wx/msw/private.h index abba5ac998..5632e4e241 100644 --- a/include/wx/msw/private.h +++ b/include/wx/msw/private.h @@ -1013,6 +1013,58 @@ inline long wxSetWindowExStyle(const wxWindowMSW *win, long style) return ::SetWindowLong(GetHwndOf(win), GWL_EXSTYLE, style); } +// Update layout direction flag for an EDIT control. +// +// Returns true if anything changed or false if the direction flag was already +// set to the desired direction (which can't be wxLayout_Default). +inline bool wxUpdateEditLayoutDirection(WXHWND hWnd, wxLayoutDirection dir) +{ + wxCHECK_MSG( hWnd, false, + wxS("Can't set layout direction for invalid window") ); + + static const LONG_PTR + EDIT_RTL_EX_FLAGS = WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR; + + const LONG_PTR styleOld = ::GetWindowLongPtr(hWnd, GWL_EXSTYLE); + + LONG_PTR styleNew = styleOld; + switch ( dir ) + { + case wxLayout_LeftToRight: + styleNew &= ~EDIT_RTL_EX_FLAGS; + break; + + case wxLayout_RightToLeft: + styleNew |= EDIT_RTL_EX_FLAGS; + break; + + case wxLayout_Default: + wxFAIL_MSG(wxS("Invalid layout direction")); + } + + if ( styleNew == styleOld ) + return false; + + ::SetWindowLongPtr(hWnd, GWL_EXSTYLE, styleNew); + + return true; +} + +// Companion of the above function checking if an EDIT control uses RTL. +inline wxLayoutDirection wxGetEditLayoutDirection(WXHWND hWnd) +{ + wxCHECK_MSG( hWnd, wxLayout_Default, wxS("invalid window") ); + + // While we set 3 style bits above, we're only really interested in one of + // them here. In particularly, don't check for WS_EX_RIGHT as it can be set + // for a right-aligned control even if it doesn't use RTL. And while we + // could test WS_EX_LEFTSCROLLBAR, this doesn't really seem useful. + const LONG_PTR style = ::GetWindowLongPtr(hWnd, GWL_EXSTYLE); + + return style & WS_EX_RTLREADING ? wxLayout_RightToLeft + : wxLayout_LeftToRight; +} + // ---------------------------------------------------------------------------- // functions mapping HWND to wxWindow // ---------------------------------------------------------------------------- diff --git a/include/wx/msw/textctrl.h b/include/wx/msw/textctrl.h index 6f55ce4ca6..4aefbdff10 100644 --- a/include/wx/msw/textctrl.h +++ b/include/wx/msw/textctrl.h @@ -101,6 +101,11 @@ public: return wxTextCtrlBase::HitTest(pt, col, row); } +#ifndef __WXWINCE__ + virtual void SetLayoutDirection(wxLayoutDirection dir) wxOVERRIDE; + virtual wxLayoutDirection GetLayoutDirection() const wxOVERRIDE; +#endif // !__WXWINCE__ + // Caret handling (Windows only) bool ShowNativeCaret(bool show = true); bool HideNativeCaret() { return ShowNativeCaret(false); } diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index 05f6eabe26..9df871c5f0 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -1793,6 +1793,41 @@ void wxTextCtrl::SetMaxLength(unsigned long len) } } +#ifndef __WXWINCE__ + +// ---------------------------------------------------------------------------- +// RTL support +// ---------------------------------------------------------------------------- + +void wxTextCtrl::SetLayoutDirection(wxLayoutDirection dir) +{ + // We only need to handle this specifically for plain EDIT controls, rich + // edit ones behave like any other window. + if ( IsRich() ) + { + wxTextCtrlBase::SetLayoutDirection(dir); + } + else + { + if ( wxUpdateEditLayoutDirection(GetHwnd(), dir) ) + { + // Update text layout by forcing the control to redo it, a simple + // Refresh() is not enough. + SendSizeEvent(); + Refresh(); + } + } +} + +wxLayoutDirection wxTextCtrl::GetLayoutDirection() const +{ + // Just as above, we need to handle plain EDIT controls specially. + return IsRich() ? wxTextCtrlBase::GetLayoutDirection() + : wxGetEditLayoutDirection(GetHwnd()); +} + +#endif // !__WXWINCE__ + // ---------------------------------------------------------------------------- // Undo/redo // ----------------------------------------------------------------------------