changed the code to be really sure that exactly one update event is sent when SetValue() is called
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30781 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -247,9 +247,9 @@ protected:
|
|||||||
int m_verRichEdit;
|
int m_verRichEdit;
|
||||||
#endif // wxUSE_RICHEDIT
|
#endif // wxUSE_RICHEDIT
|
||||||
|
|
||||||
// if true, SendUpdateEvent() will eat the next event (see comments in the
|
// number of EN_UPDATE events sent by Windows when we change the controls
|
||||||
// code as to why this is needed)
|
// text ourselves: we want this to be exactly 1
|
||||||
bool m_suppressNextUpdate;
|
int m_updatesCount;
|
||||||
|
|
||||||
virtual wxVisualAttributes GetDefaultAttributes() const;
|
virtual wxVisualAttributes GetDefaultAttributes() const;
|
||||||
|
|
||||||
|
@@ -102,6 +102,36 @@ IMPLEMENT_DYNAMIC_CLASS(wxRichEditModule, wxModule)
|
|||||||
|
|
||||||
#endif // wxUSE_RICHEDIT
|
#endif // wxUSE_RICHEDIT
|
||||||
|
|
||||||
|
// a small class used to set m_updatesCount to 0 (to filter duplicate events if
|
||||||
|
// necessary) and to reset it back to -1 afterwards
|
||||||
|
class UpdatesCountFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UpdatesCountFilter(int& count)
|
||||||
|
: m_count(count)
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( m_count == -1, _T("wrong initial m_updatesCount value") );
|
||||||
|
|
||||||
|
m_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~UpdatesCountFilter()
|
||||||
|
{
|
||||||
|
m_count = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if an event has been received
|
||||||
|
bool GotUpdate() const
|
||||||
|
{
|
||||||
|
return m_count == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int& m_count;
|
||||||
|
|
||||||
|
DECLARE_NO_COPY_CLASS(UpdatesCountFilter)
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// event tables and other macros
|
// event tables and other macros
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -218,7 +248,7 @@ void wxTextCtrl::Init()
|
|||||||
#endif // wxUSE_RICHEDIT
|
#endif // wxUSE_RICHEDIT
|
||||||
|
|
||||||
m_privateContextMenu = NULL;
|
m_privateContextMenu = NULL;
|
||||||
m_suppressNextUpdate = false;
|
m_updatesCount = -1;
|
||||||
m_isNativeCaretShown = true;
|
m_isNativeCaretShown = true;
|
||||||
m_isCaretAtEnd = true;
|
m_isCaretAtEnd = true;
|
||||||
}
|
}
|
||||||
@@ -751,13 +781,8 @@ wxTextCtrl::StreamIn(const wxString& value,
|
|||||||
// the cast below is needed for broken (very) old mingw32 headers
|
// the cast below is needed for broken (very) old mingw32 headers
|
||||||
eds.pfnCallback = (EDITSTREAMCALLBACK)wxRichEditStreamIn;
|
eds.pfnCallback = (EDITSTREAMCALLBACK)wxRichEditStreamIn;
|
||||||
|
|
||||||
// we're going to receive 2 EN_CHANGE notifications if we got any selection
|
// same problem as in DoWriteText(): we can get multiple events here
|
||||||
// (same problem as in DoWriteText())
|
UpdatesCountFilter ucf(m_updatesCount);
|
||||||
if ( selectionOnly && HasSelection() )
|
|
||||||
{
|
|
||||||
// so suppress one of them
|
|
||||||
m_suppressNextUpdate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
::SendMessage(GetHwnd(), EM_STREAMIN,
|
::SendMessage(GetHwnd(), EM_STREAMIN,
|
||||||
SF_TEXT |
|
SF_TEXT |
|
||||||
@@ -765,6 +790,8 @@ wxTextCtrl::StreamIn(const wxString& value,
|
|||||||
(selectionOnly ? SFF_SELECTION : 0),
|
(selectionOnly ? SFF_SELECTION : 0),
|
||||||
(LPARAM)&eds);
|
(LPARAM)&eds);
|
||||||
|
|
||||||
|
wxASSERT_MSG( ucf.GotUpdate(), _T("EM_STREAMIN didn't send EN_UPDATE?") );
|
||||||
|
|
||||||
if ( eds.dwError )
|
if ( eds.dwError )
|
||||||
{
|
{
|
||||||
wxLogLastError(_T("EM_STREAMIN"));
|
wxLogLastError(_T("EM_STREAMIN"));
|
||||||
@@ -906,36 +933,20 @@ void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly)
|
|||||||
#endif // wxUSE_RICHEDIT
|
#endif // wxUSE_RICHEDIT
|
||||||
{
|
{
|
||||||
// in some cases we get 2 EN_CHANGE notifications after the SendMessage
|
// in some cases we get 2 EN_CHANGE notifications after the SendMessage
|
||||||
// call below which is confusing for the client code and so should be
|
// call (this happens for plain EDITs with EM_REPLACESEL and under some
|
||||||
// avoided
|
// -- undetermined -- conditions with rich edit) and sometimes we don't
|
||||||
//
|
// get any events at all (plain EDIT with WM_SETTEXT), so ensure that
|
||||||
// these cases are: (a) plain EDIT controls if EM_REPLACESEL is used
|
// we generate exactly one of them by ignoring all but the first one in
|
||||||
// and there is a non empty selection currently and (b) rich text
|
// SendUpdateEvent() and generating one ourselves if we hadn't got any
|
||||||
// controls in any case
|
// notifications from Windows
|
||||||
if (
|
UpdatesCountFilter ucf(m_updatesCount);
|
||||||
#if wxUSE_RICHEDIT
|
|
||||||
IsRich() ||
|
|
||||||
#endif // wxUSE_RICHEDIT
|
|
||||||
(selectionOnly && HasSelection()) )
|
|
||||||
{
|
|
||||||
m_suppressNextUpdate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
::SendMessage(GetHwnd(), selectionOnly ? EM_REPLACESEL : WM_SETTEXT,
|
::SendMessage(GetHwnd(), selectionOnly ? EM_REPLACESEL : WM_SETTEXT,
|
||||||
0, (LPARAM)valueDos.c_str());
|
0, (LPARAM)valueDos.c_str());
|
||||||
|
|
||||||
// OTOH, non rich text controls don't generate any events at all when
|
if ( !ucf.GotUpdate() )
|
||||||
// we use WM_SETTEXT -- have to emulate them here
|
|
||||||
if ( !selectionOnly
|
|
||||||
#if wxUSE_RICHEDIT
|
|
||||||
&& !IsRich()
|
|
||||||
#endif // wxUSE_RICHEDIT
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Windows already sends an update event for single-line
|
SendUpdateEvent();
|
||||||
// controls.
|
|
||||||
if ( m_windowStyle & wxTE_MULTILINE )
|
|
||||||
SendUpdateEvent();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1801,13 +1812,25 @@ WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
|
|||||||
|
|
||||||
bool wxTextCtrl::SendUpdateEvent()
|
bool wxTextCtrl::SendUpdateEvent()
|
||||||
{
|
{
|
||||||
// is event reporting suspended?
|
switch ( m_updatesCount )
|
||||||
if ( m_suppressNextUpdate )
|
|
||||||
{
|
{
|
||||||
// do process the next one
|
case 0:
|
||||||
m_suppressNextUpdate = false;
|
// remember that we've got an update
|
||||||
|
m_updatesCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
return false;
|
case 1:
|
||||||
|
// we had already sent one event since the last control modification
|
||||||
|
return false;
|
||||||
|
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG( _T("unexpected wxTextCtrl::m_updatesCount value") );
|
||||||
|
// fall through
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
// we hadn't updated the control ourselves, this event comes from
|
||||||
|
// the user, don't need to ignore it nor update the count
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
|
wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
|
||||||
|
Reference in New Issue
Block a user