]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/spinctrl.cpp
Store menus titles in menus themselves in wxOSX.
[wxWidgets.git] / src / msw / spinctrl.cpp
index bb867d36a80e5dd1da47e7a6c453e79d18198e8c..b981c09afc5712361c364bcbd07e54cca1402e90 100644 (file)
@@ -29,6 +29,7 @@
 #include "wx/spinctrl.h"
 
 #ifndef WX_PRECOMP
+    #include "wx/hashmap.h"
     #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
     #include "wx/event.h"
     #include "wx/textctrl.h"
@@ -129,12 +130,28 @@ END_EVENT_TABLE()
 // font size?)
 static const int MARGIN_BETWEEN = 1;
 
+
+// ---------------------------------------------------------------------------
+// global vars
+// ---------------------------------------------------------------------------
+
+namespace
+{
+
+// Global hash used to find the spin control corresponding to the given buddy
+// text control HWND.
+WX_DECLARE_HASH_MAP(HWND, wxSpinCtrl *,
+                    wxPointerHash, wxPointerEqual,
+                    SpinForTextCtrl);
+
+SpinForTextCtrl gs_spinForTextCtrl;
+
+} // anonymous namespace
+
 // ============================================================================
 // implementation
 // ============================================================================
 
-wxArraySpins wxSpinCtrl::ms_allSpins;
-
 // ----------------------------------------------------------------------------
 // wnd proc for the buddy text ctrl
 // ----------------------------------------------------------------------------
@@ -144,7 +161,7 @@ LRESULT APIENTRY _EXPORT wxBuddyTextWndProc(HWND hwnd,
                                             WPARAM wParam,
                                             LPARAM lParam)
 {
-    wxSpinCtrl *spin = (wxSpinCtrl *)wxGetWindowUserData(hwnd);
+    wxSpinCtrl * const spin = wxSpinCtrl::GetSpinForTextCtrl(hwnd);
 
     // forward some messages (mostly the key and focus ones) to the spin ctrl
     switch ( message )
@@ -170,7 +187,7 @@ LRESULT APIENTRY _EXPORT wxBuddyTextWndProc(HWND hwnd,
             spin->MSWWindowProc(message, wParam, lParam);
 
             // The control may have been deleted at this point, so check.
-            if ( !::IsWindow(hwnd) || wxGetWindowUserData(hwnd) != spin )
+            if ( !::IsWindow(hwnd) )
                 return 0;
             break;
 
@@ -198,13 +215,13 @@ LRESULT APIENTRY _EXPORT wxBuddyTextWndProc(HWND hwnd,
 /* static */
 wxSpinCtrl *wxSpinCtrl::GetSpinForTextCtrl(WXHWND hwndBuddy)
 {
-    wxSpinCtrl *spin = (wxSpinCtrl *)wxGetWindowUserData((HWND)hwndBuddy);
-
-    int i = ms_allSpins.Index(spin);
-
-    if ( i == wxNOT_FOUND )
+    const SpinForTextCtrl::const_iterator
+        it = gs_spinForTextCtrl.find(hwndBuddy);
+    if ( it == gs_spinForTextCtrl.end() )
         return NULL;
 
+    wxSpinCtrl * const spin = it->second;
+
     // sanity check
     wxASSERT_MSG( spin->m_hwndBuddy == hwndBuddy,
                   wxT("wxSpinCtrl has incorrect buddy HWND!") );
@@ -399,7 +416,8 @@ bool wxSpinCtrl::Create(wxWindow *parent,
     wxSpinButtonBase::SetRange(min, max);
 
     // subclass the text ctrl to be able to intercept some events
-    wxSetWindowUserData(GetBuddyHwnd(), this);
+    gs_spinForTextCtrl[GetBuddyHwnd()] = this;
+
     m_wndProcBuddy = (WXFARPROC)wxSetWindowProc(GetBuddyHwnd(),
                                                 wxBuddyTextWndProc);
 
@@ -441,24 +459,16 @@ bool wxSpinCtrl::Create(wxWindow *parent,
         m_oldValue = initial;
     }
 
-    // do it after finishing with m_hwndBuddy creation to avoid generating
-    // initial wxEVT_COMMAND_TEXT_UPDATED message
-    ms_allSpins.Add(this);
-
     return true;
 }
 
 wxSpinCtrl::~wxSpinCtrl()
 {
-    ms_allSpins.Remove(this);
-
-    // This removes spurious memory leak reporting
-    if (ms_allSpins.GetCount() == 0)
-        ms_allSpins.Clear();
-
     // destroy the buddy window because this pointer which wxBuddyTextWndProc
     // uses will not soon be valid any more
-    ::DestroyWindow(GetBuddyHwnd());
+    ::DestroyWindow( GetBuddyHwnd() );
+
+    gs_spinForTextCtrl.erase(GetBuddyHwnd());
 }
 
 // ----------------------------------------------------------------------------
@@ -584,32 +594,37 @@ bool wxSpinCtrl::Reparent(wxWindowBase *newParent)
     // window normally, but we recreate the updown control and reassign its
     // buddy.
 
+    // Get the position before changing the parent as it would be offset after
+    // changing it.
+    const wxRect rect = GetRect();
+
     if ( !wxWindowBase::Reparent(newParent) )
         return false;
 
     newParent->GetChildren().DeleteObject(this);
 
-    // preserve the old values
-    const wxSize size = GetSize();
-    int value = GetValue();
-    const wxRect btnRect = wxRectFromRECT(wxGetWindowRect(GetHwnd()));
-
-    // destroy the old spin button
+    // destroy the old spin button after detaching it from this wxWindow object
+    // (notice that m_hWnd will be reset by UnsubclassWin() so save it first)
+    const HWND hwndOld = GetHwnd();
     UnsubclassWin();
-    if ( !::DestroyWindow(GetHwnd()) )
+    if ( !::DestroyWindow(hwndOld) )
     {
         wxLogLastError(wxT("DestroyWindow"));
     }
 
     // create and initialize the new one
     if ( !wxSpinButton::Create(GetParent(), GetId(),
-                               btnRect.GetPosition(), btnRect.GetSize(),
+                               rect.GetPosition(), rect.GetSize(),
                                GetWindowStyle(), GetName()) )
         return false;
 
-    SetValue(value);
+    // reapply our values to wxSpinButton
+    wxSpinButton::SetValue(GetValue());
     SetRange(m_min, m_max);
-    SetInitialSize(size);
+
+    // also set the size again with wxSIZE_ALLOW_MINUS_ONE flag: this is
+    // necessary if our original position used -1 for either x or y
+    SetSize(rect, wxSIZE_ALLOW_MINUS_ONE);
 
     // associate it with the buddy control again
     ::SetParent(GetBuddyHwnd(), GetHwndOf(GetParent()));