From 882a8f40e259edccf7ab628d8bddf08220fb3e2c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 29 Dec 1999 23:34:18 +0000 Subject: [PATCH] wxCalendarCtrl works under MSW too git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5149 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/generic/calctrl.h | 28 ++++-- include/wx/msw/choice.h | 2 +- include/wx/msw/combobox.h | 5 +- include/wx/msw/spinctrl.h | 7 +- src/generic/calctrl.cpp | 189 +++++++++++++++++++++++++++++------ src/msw/choice.cpp | 2 +- src/msw/combobox.cpp | 28 +++++- src/msw/spinbutt.cpp | 3 +- src/msw/spinctrl.cpp | 37 ++++++- src/msw/window.cpp | 7 ++ 10 files changed, 251 insertions(+), 57 deletions(-) diff --git a/include/wx/generic/calctrl.h b/include/wx/generic/calctrl.h index 5bde99940d..c685deeb48 100644 --- a/include/wx/generic/calctrl.h +++ b/include/wx/generic/calctrl.h @@ -40,7 +40,8 @@ public: const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxCalendarNameStr) - : wxControl(parent, id, pos, size, style, wxDefaultValidator, name) + : wxControl(parent, id, pos, size, + style | wxWANTS_CHARS, wxDefaultValidator, name) { Init(); @@ -55,6 +56,8 @@ public: long style = 0, const wxString& name = wxCalendarNameStr); + virtual ~wxCalendarCtrl(); + // set/get the current date void SetDate(const wxDateTime& date); const wxDateTime& GetDate() const { return m_date; } @@ -63,25 +66,34 @@ public: // value bool HitTest(const wxPoint& pos, wxDateTime *date); + // implementation only from now on + // ------------------------------- + + // forward these functions to all subcontrols + virtual bool Enable(bool enable = TRUE); + virtual bool Show(bool show = TRUE); + + // event handlers + void OnPaint(wxPaintEvent& event); + void OnClick(wxMouseEvent& event); + void OnChar(wxKeyEvent& event); + void OnMonthChange(wxCommandEvent& event); + void OnYearChange(wxSpinEvent& event); + private: // common part of all ctors void Init(); // override some base class virtuals virtual wxSize DoGetBestSize() const; + virtual void DoGetPosition(int *x, int *y) const; + virtual void DoGetSize(int *width, int *height) const; virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags); virtual void DoMoveWindow(int x, int y, int width, int height); // (re)calc m_widthCol and m_heightRow void RecalcGeometry(); - // event handlers - void OnPaint(wxPaintEvent& event); - void OnClick(wxMouseEvent& event); - void OnChar(wxKeyEvent& event); - void OnMonthChange(wxCommandEvent& event); - void OnYearChange(wxSpinEvent& event); - // set the date and send the notification void SetDateAndNotify(const wxDateTime& date); diff --git a/include/wx/msw/choice.h b/include/wx/msw/choice.h index 654f1af915..f60a023057 100644 --- a/include/wx/msw/choice.h +++ b/include/wx/msw/choice.h @@ -74,7 +74,7 @@ protected: virtual wxClientData* DoGetItemClientObject( int n ) const; // MSW implementation - virtual wxSize DoGetBestSize(); + virtual wxSize DoGetBestSize() const; virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); diff --git a/include/wx/msw/combobox.h b/include/wx/msw/combobox.h index 52e8a9d6db..1828e0045a 100644 --- a/include/wx/msw/combobox.h +++ b/include/wx/msw/combobox.h @@ -78,9 +78,8 @@ public: virtual bool MSWCommand(WXUINT param, WXWORD id); protected: - virtual void DoSetSize(int x, int y, - int width, int height, - int sizeFlags = wxSIZE_AUTO); + virtual void DoMoveWindow(int x, int y, int width, int height); + virtual wxSize DoGetBestSize() const; }; #endif // wxUSE_COMBOBOX diff --git a/include/wx/msw/spinctrl.h b/include/wx/msw/spinctrl.h index f6c8f8fd52..37f8e1c2e4 100644 --- a/include/wx/msw/spinctrl.h +++ b/include/wx/msw/spinctrl.h @@ -54,11 +54,16 @@ public: // because the base class already has one returning int!) void SetValue(const wxString& text); - // override some of the base class virtuals + // implementation only from now on + // ------------------------------- + virtual void SetValue(int val) { wxSpinButton::SetValue(val); } virtual int GetValue() const; virtual bool SetFont(const wxFont &font); + virtual bool Enable(bool enable = TRUE); + virtual bool Show(bool show = TRUE); + protected: virtual void DoMoveWindow(int x, int y, int width, int height); virtual wxSize DoGetBestSize() const; diff --git a/src/generic/calctrl.cpp b/src/generic/calctrl.cpp index 5419de38ce..ed540c9dd4 100644 --- a/src/generic/calctrl.cpp +++ b/src/generic/calctrl.cpp @@ -36,6 +36,38 @@ #include "wx/calctrl.h" +#define DEBUG_PAINT 0 + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +class wxMonthComboBox : public wxComboBox +{ +public: + wxMonthComboBox(wxCalendarCtrl *cal); + + void OnMonthChange(wxCommandEvent& event) { m_cal->OnMonthChange(event); } + +private: + wxCalendarCtrl *m_cal; + + DECLARE_EVENT_TABLE() +}; + +class wxYearSpinCtrl : public wxSpinCtrl +{ +public: + wxYearSpinCtrl(wxCalendarCtrl *cal); + + void OnYearChange(wxSpinEvent& event) { m_cal->OnYearChange(event); } + +private: + wxCalendarCtrl *m_cal; + + DECLARE_EVENT_TABLE() +}; + // ---------------------------------------------------------------------------- // wxWin macros // ---------------------------------------------------------------------------- @@ -46,9 +78,14 @@ BEGIN_EVENT_TABLE(wxCalendarCtrl, wxControl) EVT_CHAR(wxCalendarCtrl::OnChar) EVT_LEFT_DOWN(wxCalendarCtrl::OnClick) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(wxMonthComboBox, wxComboBox) + EVT_COMBOBOX(-1, wxMonthComboBox::OnMonthChange) +END_EVENT_TABLE() - EVT_COMBOBOX(-1, wxCalendarCtrl::OnMonthChange) - EVT_SPINCTRL(-1, wxCalendarCtrl::OnYearChange) +BEGIN_EVENT_TABLE(wxYearSpinCtrl, wxSpinCtrl) + EVT_SPINCTRL(-1, wxYearSpinCtrl::OnYearChange) END_EVENT_TABLE() IMPLEMENT_DYNAMIC_CLASS(wxCalendarCtrl, wxControl) @@ -57,6 +94,40 @@ IMPLEMENT_DYNAMIC_CLASS(wxCalendarCtrl, wxControl) // implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// wxMonthComboBox and wxYearSpinCtrl +// ---------------------------------------------------------------------------- + +wxMonthComboBox::wxMonthComboBox(wxCalendarCtrl *cal) + : wxComboBox(cal->GetParent(), -1, + wxEmptyString, + wxDefaultPosition, + wxDefaultSize, + 0, NULL, + wxCB_READONLY) +{ + m_cal = cal; + + wxDateTime::Month m; + for ( m = wxDateTime::Jan; m < wxDateTime::Inv_Month; wxNextMonth(m) ) + { + Append(wxDateTime::GetMonthName(m)); + } + + SetSelection(m_cal->GetDate().GetMonth()); +} + +wxYearSpinCtrl::wxYearSpinCtrl(wxCalendarCtrl *cal) + : wxSpinCtrl(cal->GetParent(), -1, + cal->GetDate().Format(_T("%Y")), + wxDefaultPosition, + wxDefaultSize, + wxSP_ARROW_KEYS, + -4300, 10000, cal->GetDate().GetYear()) +{ + m_cal = cal; +} + // ---------------------------------------------------------------------------- // wxCalendarCtrl // ---------------------------------------------------------------------------- @@ -84,32 +155,12 @@ bool wxCalendarCtrl::Create(wxWindow *parent, long style, const wxString& name) { - m_date = date.IsValid() ? date : wxDateTime::Today(); + SetWindowStyle(style | (wxBORDER | wxWANTS_CHARS)); - wxString monthNames[12]; - wxDateTime::Month m; - for ( m = wxDateTime::Jan; m < wxDateTime::Inv_Month; wxNextMonth(m) ) - { - monthNames[m] = wxDateTime::GetMonthName(m); - } - - m_comboMonth = new wxComboBox(parent, -1, - monthNames[m_date.GetMonth()], - wxDefaultPosition, - wxDefaultSize, - WXSIZEOF(monthNames), monthNames, - wxCB_READONLY); - - m_spinYear = new wxSpinCtrl(parent, -1, - m_date.Format(_T("%Y")), - wxDefaultPosition, - wxDefaultSize, - wxSP_ARROW_KEYS, - -4300, 10000, m_date.GetYear()); + m_date = date.IsValid() ? date : wxDateTime::Today(); - // we want to process the events from these controls - m_comboMonth->PushEventHandler(this); - m_spinYear->PushEventHandler(this); + m_comboMonth = new wxMonthComboBox(this); + m_spinYear = new wxYearSpinCtrl(this); wxSize sizeReal; if ( size.x == -1 || size.y == -1 ) @@ -133,6 +184,44 @@ bool wxCalendarCtrl::Create(wxWindow *parent, return TRUE; } +wxCalendarCtrl::~wxCalendarCtrl() +{ +#if 0 + m_comboMonth->PopEventHandler(); + m_spinYear->PopEventHandler(); +#endif // 0 +} + +// ---------------------------------------------------------------------------- +// forward wxWin functions to subcontrols +// ---------------------------------------------------------------------------- + +bool wxCalendarCtrl::Show(bool show) +{ + if ( !wxControl::Show(show) ) + { + return FALSE; + } + + m_comboMonth->Show(show); + m_spinYear->Show(show); + + return TRUE; +} + +bool wxCalendarCtrl::Enable(bool enable) +{ + if ( !wxControl::Enable(enable) ) + { + return FALSE; + } + + m_comboMonth->Enable(enable); + m_spinYear->Enable(enable); + + return TRUE; +} + // ---------------------------------------------------------------------------- // changing date // ---------------------------------------------------------------------------- @@ -270,7 +359,7 @@ void wxCalendarCtrl::DoMoveWindow(int x, int y, int width, int height) m_comboMonth->Move(x, y); int xDiff = sizeCombo.x + HORZ_MARGIN; - m_spinYear->SetSize(x + xDiff, y, width - xDiff, -1); + m_spinYear->SetSize(x + xDiff, y, width - xDiff, sizeCombo.y); wxSize sizeSpin = m_spinYear->GetSize(); int yDiff = wxMax(sizeSpin.y, sizeCombo.y) + VERT_MARGIN; @@ -278,6 +367,28 @@ void wxCalendarCtrl::DoMoveWindow(int x, int y, int width, int height) wxControl::DoMoveWindow(x, y + yDiff, width, height - yDiff); } +void wxCalendarCtrl::DoGetPosition(int *x, int *y) const +{ + wxControl::DoGetPosition(x, y); + + // our real top corner is not in this position + if ( y ) + { + *y -= m_comboMonth->GetSize().y + VERT_MARGIN; + } +} + +void wxCalendarCtrl::DoGetSize(int *width, int *height) const +{ + wxControl::DoGetSize(width, height); + + // our real height is bigger + if ( height ) + { + *height += m_comboMonth->GetSize().y + VERT_MARGIN; + } +} + void wxCalendarCtrl::RecalcGeometry() { if ( m_widthCol != 0 ) @@ -320,14 +431,18 @@ void wxCalendarCtrl::OnPaint(wxPaintEvent& event) RecalcGeometry(); +#if DEBUG_PAINT printf("--- starting to paint, selection: %s, week %u\n", m_date.Format("%a %d-%m-%Y %H:%M:%S").c_str(), GetWeek(m_date)); +#endif // first draw the week days if ( IsExposed(0, 0, 7*m_widthCol, m_heightRow) ) { +#if DEBUG_PAINT puts("painting the header"); +#endif dc.SetTextForeground(*wxBLUE); dc.SetBrush(wxBrush(*wxLIGHT_GREY, wxSOLID)); @@ -347,8 +462,10 @@ void wxCalendarCtrl::OnPaint(wxPaintEvent& event) wxCoord y = m_heightRow; wxDateTime date = GetStartDate(); +#if DEBUG_PAINT printf("starting calendar from %s\n", date.Format("%a %d-%m-%Y %H:%M:%S").c_str()); +#endif dc.SetBackgroundMode(wxSOLID); for ( size_t nWeek = 1; nWeek <= 6; nWeek++, y += m_heightRow ) @@ -360,13 +477,16 @@ void wxCalendarCtrl::OnPaint(wxPaintEvent& event) continue; } - + +#if DEBUG_PAINT printf("painting week %d at y = %d\n", nWeek, y); +#endif for ( wd = wxDateTime::Sun; wd < wxDateTime::Inv_WeekDay; wxNextWDay(wd) ) { if ( IsDateShown(date) ) { + // don't use wxDate::Format() which prepends 0s wxString day = wxString::Format(_T("%u"), date.GetDay()); wxCoord width; dc.GetTextExtent(day, &width, (wxCoord *)NULL); @@ -391,8 +511,9 @@ void wxCalendarCtrl::OnPaint(wxPaintEvent& event) date += wxDateSpan::Day(); } } - +#if DEBUG_PAINT puts("+++ finished painting"); +#endif } void wxCalendarCtrl::RefreshDate(const wxDateTime& date) @@ -409,10 +530,12 @@ void wxCalendarCtrl::RefreshDate(const wxDateTime& date) rect.width = 7*m_widthCol; rect.height = m_heightRow; +#if DEBUG_PAINT printf("*** refreshing week %d at (%d, %d)-(%d, %d)\n", GetWeek(date), rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); +#endif Refresh(TRUE, &rect); } @@ -513,12 +636,12 @@ void wxCalendarCtrl::OnChar(wxKeyEvent& event) SetDateAndNotify(m_date - wxDateSpan::Year()); break; - case WXK_PAGEDOWN: - SetDateAndNotify(m_date + wxDateSpan::Year()); + case WXK_PRIOR: + SetDateAndNotify(m_date - wxDateSpan::Month()); break; - case WXK_PAGEUP: - SetDateAndNotify(m_date - wxDateSpan::Year()); + case WXK_NEXT: + SetDateAndNotify(m_date + wxDateSpan::Month()); break; case WXK_RIGHT: diff --git a/src/msw/choice.cpp b/src/msw/choice.cpp index 2c5fd437f1..a6144b1da2 100644 --- a/src/msw/choice.cpp +++ b/src/msw/choice.cpp @@ -261,7 +261,7 @@ void wxChoice::DoSetSize(int x, int y, wxControl::DoSetSize(x, y, width, -1, sizeFlags); } -wxSize wxChoice::DoGetBestSize() +wxSize wxChoice::DoGetBestSize() const { // find the widest string int wLine; diff --git a/src/msw/combobox.cpp b/src/msw/combobox.cpp index d4ec3f017a..9bab1a0cdb 100644 --- a/src/msw/combobox.cpp +++ b/src/msw/combobox.cpp @@ -325,11 +325,31 @@ void wxComboBox::SetSelection(long from, long to) #endif } -void wxComboBox::DoSetSize(int x, int y, - int width, int height, - int sizeFlags) +void wxComboBox::DoMoveWindow(int x, int y, int width, int height) { - wxControl::DoSetSize(x, y, width, height, sizeFlags); + int cx, cy; + wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); + + int n = GetCount(); + if ( !n ) + n = 10; + + height = n * EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy); + + wxControl::DoMoveWindow(x, y, width, height); +} + +wxSize wxComboBox::DoGetBestSize() const +{ + // the choice calculates the horz size correctly, but not the vertical + // component: correct it + wxSize size = wxChoice::DoGetBestSize(); + + int cx, cy; + wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); + size.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy); + + return size; } #endif diff --git a/src/msw/spinbutt.cpp b/src/msw/spinbutt.cpp index 9c3b36bffb..cbd779d665 100644 --- a/src/msw/spinbutt.cpp +++ b/src/msw/spinbutt.cpp @@ -104,7 +104,8 @@ bool wxSpinButton::Create(wxWindow *parent, // translate the styles DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP | - UDS_SETBUDDYINT; // it doesn't harm if we don't have buddy + UDS_NOTHOUSANDS | // never useful, sometimes harmful + UDS_SETBUDDYINT; // it doesn't harm if we don't have buddy if ( m_windowStyle & wxSP_HORIZONTAL ) wstyle |= UDS_HORZ; diff --git a/src/msw/spinctrl.cpp b/src/msw/spinctrl.cpp index 1724bf68d8..3946d365a9 100644 --- a/src/msw/spinctrl.cpp +++ b/src/msw/spinctrl.cpp @@ -85,7 +85,8 @@ bool wxSpinCtrl::Create(wxWindow *parent, // 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) @@ -144,8 +145,10 @@ bool wxSpinCtrl::Create(wxWindow *parent, // 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, @@ -170,7 +173,7 @@ bool wxSpinCtrl::Create(wxWindow *parent, 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)"); } @@ -188,7 +191,7 @@ int wxSpinCtrl::GetValue() const } // ---------------------------------------------------------------------------- -// when setting font, we need to do it for both controls +// forward some methods to subcontrols // ---------------------------------------------------------------------------- bool wxSpinCtrl::SetFont(const wxFont& font) @@ -205,6 +208,30 @@ 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; +} + // ---------------------------------------------------------------------------- // event processing // ---------------------------------------------------------------------------- diff --git a/src/msw/window.cpp b/src/msw/window.cpp index eefebd74d7..e8b06acbe9 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -1841,6 +1841,11 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) break; case WM_LBUTTONDOWN: + // set focus to this window + SetFocus(); + + // fall through + case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: @@ -1950,6 +1955,8 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) case VK_RETURN: case VK_BACK: case VK_TAB: + case VK_ADD: + case VK_SUBTRACT: // but set processed to FALSE, not TRUE to still pass them to // the control's default window proc - otherwise built-in // keyboard handling won't work -- 2.45.2