the value in the text field upon kill focus.
 Documented this behaviour.
 This is in line with the GTK+ control.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41316 
c3d73ce0-8a6f-49c7-b76d-
6d57e0e08775
 the user modifies the text in the edit part of the spin control directly, the
 {\tt EVT\_TEXT} is generated, like for the \helpref{wxTextCtrl}{wxtextctrl}.
 
 the user modifies the text in the edit part of the spin control directly, the
 {\tt EVT\_TEXT} is generated, like for the \helpref{wxTextCtrl}{wxtextctrl}.
 
+When the use enters text into the text area, the text is not
+validated until the control loses focus (e.g. by using the TAB
+key). The value is then adjusted to the range and a 
+\helpref{wxSpinEvent}{wxspinevent} sent then if the value
+is different from the last value sent.
+
 \wxheading{See also}
 
 \helpref{Event handling overview}{eventhandlingoverview},
 \wxheading{See also}
 
 \helpref{Event handling overview}{eventhandlingoverview},
 
    virtual wxSize DoGetBestSize() const;
 
    // ensure that the control displays a value in the current range
    virtual wxSize DoGetBestSize() const;
 
    // ensure that the control displays a value in the current range
-   void NormalizeValue() { SetValue(GetValue()); }
+   virtual void NormalizeValue();
 
 private:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxSpinButton)
 
 private:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxSpinButton)
 
     void OnSetFocus(wxFocusEvent& event);
     void OnKillFocus(wxFocusEvent& event);
 
     void OnSetFocus(wxFocusEvent& event);
     void OnKillFocus(wxFocusEvent& event);
 
+    int m_oldValue;
+    virtual void NormalizeValue();
+   
     // the data for the "buddy" text ctrl
     WXHWND     m_hwndBuddy;
     WXFARPROC  m_wndProcBuddy;
     // the data for the "buddy" text ctrl
     WXHWND     m_hwndBuddy;
     WXFARPROC  m_wndProcBuddy;
 
+void wxSpinButton::NormalizeValue()
+{ 
+    SetValue( GetValue() );
+}
+
 void wxSpinButton::SetRange(int minVal, int maxVal)
 {
     const bool hadRange = m_min < m_max;
 void wxSpinButton::SetRange(int minVal, int maxVal)
 {
     const bool hadRange = m_min < m_max;
 
+void wxSpinCtrl::NormalizeValue()
+{
+    int value = GetValue();
+    SetValue( value );
+    if (value != m_oldValue)
+    {
+        wxCommandEvent event( wxEVT_COMMAND_SPINCTRL_UPDATED, GetId() );
+        event.SetEventObject( this );
+        event.SetInt( value );
+        GetEventHandler()->ProcessEvent( event );
+        m_oldValue = value;
+    }
+}
+
 // ----------------------------------------------------------------------------
 // construction
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // construction
 // ----------------------------------------------------------------------------
 
     SetRange(min, max);
     SetValue(initial);
 
     SetRange(min, max);
     SetValue(initial);
+    
+    m_oldValue = initial;
 
     // subclass the text ctrl to be able to intercept some events
     wxSetWindowUserData(GetBuddyHwnd(), this);
 
     // subclass the text ctrl to be able to intercept some events
     wxSetWindowUserData(GetBuddyHwnd(), this);
 {
     wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, GetId());
     event.SetEventObject(this);
 {
     wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, GetId());
     event.SetEventObject(this);
-    event.SetInt(eventSpin.GetPosition());
-
-    (void)GetEventHandler()->ProcessEvent(event);
+    int value = eventSpin.GetPosition();
+    event.SetInt( value );
+    
+    if (value != m_oldValue)
+        (void)GetEventHandler()->ProcessEvent(event);
 
     if ( eventSpin.GetSkipped() )
     {
         event.Skip();
     }
 
     if ( eventSpin.GetSkipped() )
     {
         event.Skip();
     }
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------