#include "wx/spinctrl.h"
#include "wx/msw/private.h"
-#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) || defined(wxUSE_NORLANDER_HEADERS)
+#if defined(__WIN95__) && !(defined(__GNUWIN32_OLD__) || defined(__TWIN32__))
#include <commctrl.h>
#endif
// macros
// ----------------------------------------------------------------------------
-#if !USE_SHARED_LIBRARY
- IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
-#endif
+IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
+
+BEGIN_EVENT_TABLE(wxSpinCtrl, wxSpinButton)
+ EVT_SPIN(-1, wxSpinCtrl::OnSpinChange)
+END_EVENT_TABLE()
// ----------------------------------------------------------------------------
// constants
// implementation
// ============================================================================
+// ----------------------------------------------------------------------------
+// wnd proc for the buddy text ctrl
+// ----------------------------------------------------------------------------
+
+LRESULT APIENTRY _EXPORT wxBuddyTextWndProc(HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ wxSpinCtrl *spin = (wxSpinCtrl *)::GetWindowLong(hwnd, GWL_USERDATA);
+
+ // forward some messages (the key ones only so far) to the spin ctrl
+ switch ( message )
+ {
+ case WM_CHAR:
+ case WM_DEADCHAR:
+ case WM_KEYUP:
+ case WM_KEYDOWN:
+ spin->MSWWindowProc(message, wParam, lParam);
+ break;
+ }
+
+ return ::CallWindowProc(CASTWNDPROC spin->GetBuddyWndProc(),
+ hwnd, message, wParam, lParam);
+}
+
// ----------------------------------------------------------------------------
// construction
// ----------------------------------------------------------------------------
// before using DoGetBestSize(), have to set style to let the base class
// know whether this is a horizontal or vertical control (we're always
// vertical)
- SetWindowStyle(style | wxSP_VERTICAL);
+ style |= wxSP_VERTICAL;
+ SetWindowStyle(style);
// calculate the sizes: the size given is the toal size for both controls
// and we need to fit them both in the given width (height is the same)
WS_EX_CLIENTEDGE, // sunken border
_T("EDIT"), // window class
NULL, // no window title
- WS_CHILD | WS_BORDER, // style (will be shown later)
+ WS_CHILD | WS_BORDER /* | WS_CLIPSIBLINGS */, // style (will be shown later)
pos.x, pos.y, // position
0, 0, // size (will be set later)
GetHwndOf(parent), // parent
if ( !m_hwndBuddy )
{
- wxLogLastError("CreateWindow(buddy text window)");
+ wxLogLastError(wxT("CreateWindow(buddy text window)"));
return FALSE;
}
+ // subclass the text ctrl to be able to intercept some events
+ m_oldBuddyWndProc = (WXFARPROC)::GetWindowLong((HWND)m_hwndBuddy, GWL_WNDPROC);
+ ::SetWindowLong((HWND)m_hwndBuddy, GWL_USERDATA, (LONG)this);
+ ::SetWindowLong((HWND)m_hwndBuddy, GWL_WNDPROC, (LONG)wxBuddyTextWndProc);
+
// should have the same font as the other controls
SetFont(GetParent()->GetFont());
// couldn't call DoGetBestSize() before as font wasn't set
if ( sizeText.y <= 0 )
{
- // make it the same height as the button then
- sizeText.y = DoGetBestSize().y;
+ int cx, cy;
+ wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
+
+ sizeText.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
}
DoMoveWindow(pos.x, pos.y,
return TRUE;
}
+wxSpinCtrl::~wxSpinCtrl()
+{
+ // destroy the buddy window because this pointer which wxBuddyTextWndProc
+ // uses will not soon be valid any more
+ ::DestroyWindow((HWND)m_hwndBuddy);
+}
+
// ----------------------------------------------------------------------------
// wxTextCtrl-like methods
// ----------------------------------------------------------------------------
void wxSpinCtrl::SetValue(const wxString& text)
{
- if ( ::SetWindowText((HWND)m_hwndBuddy, text.c_str()) )
+ if ( !::SetWindowText((HWND)m_hwndBuddy, text.c_str()) )
{
- wxLogLastError("SetWindowText(buddy)");
+ wxLogLastError(wxT("SetWindowText(buddy)"));
}
}
}
// ----------------------------------------------------------------------------
-// when setting font, we need to do it for both controls
+// forward some methods to subcontrols
// ----------------------------------------------------------------------------
bool wxSpinCtrl::SetFont(const wxFont& font)
return TRUE;
}
+bool wxSpinCtrl::Show(bool show)
+{
+ if ( !wxControl::Show(show) )
+ {
+ return FALSE;
+ }
+
+ ::ShowWindow((HWND)m_hwndBuddy, show ? SW_SHOW : SW_HIDE);
+
+ return TRUE;
+}
+
+bool wxSpinCtrl::Enable(bool enable)
+{
+ if ( !wxControl::Enable(enable) )
+ {
+ return FALSE;
+ }
+
+ ::EnableWindow((HWND)m_hwndBuddy, enable);
+
+ return TRUE;
+}
+
+void wxSpinCtrl::SetFocus()
+{
+ ::SetFocus((HWND)m_hwndBuddy);
+}
+
+// ----------------------------------------------------------------------------
+// event processing
+// ----------------------------------------------------------------------------
+
+void wxSpinCtrl::OnSpinChange(wxSpinEvent& eventSpin)
+{
+ wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, GetId());
+ event.SetEventObject(this);
+ event.SetInt(eventSpin.GetPosition());
+
+ (void)GetEventHandler()->ProcessEvent(event);
+
+ if ( eventSpin.GetSkipped() )
+ {
+ event.Skip();
+ }
+}
+
// ----------------------------------------------------------------------------
// size calculations
// ----------------------------------------------------------------------------
-wxSize wxSpinCtrl::DoGetBestSize()
+wxSize wxSpinCtrl::DoGetBestSize() const
{
wxSize sizeBtn = wxSpinButton::DoGetBestSize();
sizeBtn.x += DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN;
if ( !::MoveWindow((HWND)m_hwndBuddy, x, y, widthText, height, TRUE) )
{
- wxLogLastError("MoveWindow(buddy)");
+ wxLogLastError(wxT("MoveWindow(buddy)"));
}
x += widthText + MARGIN_BETWEEN;
if ( !::MoveWindow(GetHwnd(), x, y, widthBtn, height, TRUE) )
{
- wxLogLastError("MoveWindow");
+ wxLogLastError(wxT("MoveWindow"));
}
}
+// get total size of the control
+void wxSpinCtrl::DoGetSize(int *x, int *y) const
+{
+ RECT spinrect, textrect, ctrlrect;
+ GetWindowRect(GetHwnd(), &spinrect);
+ GetWindowRect((HWND)m_hwndBuddy, &textrect);
+ UnionRect(&ctrlrect,&textrect, &spinrect);
+
+ if ( x )
+ *x = ctrlrect.right - ctrlrect.left;
+ if ( y )
+ *y = ctrlrect.bottom - ctrlrect.top;
+}
+
+void wxSpinCtrl::DoGetPosition(int *x, int *y) const
+{
+ // hack: pretend that our HWND is the text control just for a moment
+ WXHWND hWnd = GetHWND();
+ wxConstCast(this, wxSpinCtrl)->m_hWnd = m_hwndBuddy;
+
+ wxSpinButton::DoGetPosition(x, y);
+
+ wxConstCast(this, wxSpinCtrl)->m_hWnd = hWnd;
+}
+
#endif // __WIN95__
#endif