1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/datectlg.cpp 
   3 // Purpose:     generic wxDatePickerCtrlGeneric implementation 
   4 // Author:      Andreas Pflug 
   8 // Copyright:   (c) 2005 Andreas Pflug <pgadmin@pse-consulting.de> 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #include "wx/wxprec.h" 
  26 #if wxUSE_DATEPICKCTRL 
  28 #include "wx/datectrl.h" 
  30 // use this version if we're explicitly requested to do it or if it's the only 
  32 #if !defined(wxHAS_NATIVE_DATEPICKCTRL) || \ 
  33         (defined(wxUSE_DATEPICKCTRL_GENERIC) && wxUSE_DATEPICKCTRL_GENERIC) 
  36     #include "wx/bmpbuttn.h" 
  37     #include "wx/dialog.h" 
  38     #include "wx/dcmemory.h" 
  40     #include "wx/textctrl.h" 
  41     #include "wx/valtext.h" 
  44 #ifdef wxHAS_NATIVE_DATEPICKCTRL 
  45     // this header is not included from wx/datectrl.h if we have a native 
  46     // version, but we do need it here 
  47     #include "wx/generic/datectrl.h" 
  49     // we need to define _WX_DEFINE_DATE_EVENTS_ before including wx/dateevt.h to 
  50     // define the event types we use if we're the only date picker control version 
  51     // being compiled -- otherwise it's defined in the native version implementation 
  52     #define _WX_DEFINE_DATE_EVENTS_ 
  55 #include "wx/dateevt.h" 
  57 #include "wx/calctrl.h" 
  58 #include "wx/renderer.h" 
  60 // ---------------------------------------------------------------------------- 
  62 // ---------------------------------------------------------------------------- 
  72 #ifndef DEFAULT_ITEM_WIDTH 
  73     #define DEFAULT_ITEM_WIDTH 100 
  76 #if defined(__WXMSW__) 
  78     #define wxUSE_POPUPWIN    0  // Popup not working 
  79     #define TXTCTRL_FLAGS     wxNO_BORDER 
  82 #elif defined(__WXGTK__) 
  83     #define TXTCTRL_FLAGS     0 
  87     #define TXTCTRL_FLAGS     0 
  92 // ---------------------------------------------------------------------------- 
  94 // ---------------------------------------------------------------------------- 
  96 // this should have been a flag in wxDatePickerCtrlGeneric itself but adding it 
  97 // there now would break backwards compatibility, so put it here as a global: 
  98 // this shouldn't be a big problem as only one (GUI) thread normally can call 
  99 // wxDatePickerCtrlGeneric::SetValue() and so it can be only ever used for one 
 102 // if the value is not NULL, it points to the control which is inside SetValue() 
 103 static wxDatePickerCtrlGeneric 
*gs_inSetValue 
= NULL
; 
 105 // ---------------------------------------------------------------------------- 
 107 // ---------------------------------------------------------------------------- 
 109 // This flag indicates that combo box style drop button is to be created 
 110 #define wxBU_COMBO          0x0400 
 113 class wxDropdownButton 
: public wxBitmapButton
 
 116     wxDropdownButton() { Init(); } 
 117     wxDropdownButton(wxWindow 
*parent
, 
 119                      const wxPoint
& pos 
= wxDefaultPosition
, 
 120                      const wxSize
& size 
= wxDefaultSize
, 
 122                      const wxValidator
& validator 
= wxDefaultValidator
); 
 124     bool Create(wxWindow 
*parent
, 
 126                 const wxPoint
& pos 
= wxDefaultPosition
, 
 127                 const wxSize
& size 
= wxDefaultSize
, 
 129                 const wxValidator
& validator 
= wxDefaultValidator
); 
 131     virtual void DoMoveWindow(int x
, int y
, int w
, int h
); 
 135     void OnSize(wxSizeEvent
& event
); 
 136     void OnMouseEnter(wxMouseEvent
& event
); 
 137     void OnMouseLeave(wxMouseEvent
& event
); 
 139     void RecreateBitmaps(int w
, int h
); 
 141     wxBitmap    m_bmpNormal
; 
 144     int         m_borderX
, m_borderY
; 
 146     // True if DrawDropArrow should be used instead of DrawComboBoxDropButton 
 157     DECLARE_EVENT_TABLE() 
 158     DECLARE_DYNAMIC_CLASS_NO_COPY(wxDropdownButton
) 
 162 // Below, macro DROPBUT_USEDROPARROW should return false when 
 163 // DrawComboBoxDropButton is to be used to render the entire button. 
 164 // COMBOST is non-zero if wxBU_COMBO was set. 
 166 #if defined(__WXMSW__) 
 168     #define DROPBUT_USEDROPARROW(COMBOST)   (COMBOST?false:true) 
 169     #define DROPBUT_DEFAULT_WIDTH           17 
 171 #elif defined(__WXGTK__) 
 173     #define DROPBUT_USEDROPARROW(COMBOST)   true 
 174     #define DROPBUT_DEFAULT_WIDTH           19 
 178     #define DROPBUT_USEDROPARROW(COMBOST)   true 
 179     #define DROPBUT_DEFAULT_WIDTH           17 
 184 IMPLEMENT_DYNAMIC_CLASS(wxDropdownButton
, wxBitmapButton
) 
 187 BEGIN_EVENT_TABLE(wxDropdownButton
,wxBitmapButton
) 
 188     EVT_ENTER_WINDOW(wxDropdownButton::OnMouseEnter
) 
 189     EVT_LEAVE_WINDOW(wxDropdownButton::OnMouseLeave
) 
 190     EVT_SIZE(wxDropdownButton::OnSize
) 
 194 wxDropdownButton::wxDropdownButton(wxWindow 
*parent
, 
 199                                    const wxValidator
& validator
) 
 202     Create(parent
, id
, pos
, size
, style
, validator
); 
 206 bool wxDropdownButton::Create(wxWindow 
*parent
, 
 211                               const wxValidator
& validator
) 
 216     m_useDropArrow 
= DROPBUT_USEDROPARROW(style 
& wxBU_COMBO
); 
 218     wxBitmap 
chkBmp(15,15);  // arbitrary 
 219     if ( !wxBitmapButton::Create(parent
, id
, chkBmp
, 
 221                                  style 
| (m_useDropArrow 
? wxBU_AUTODRAW 
: wxNO_BORDER
), 
 225     const wxSize sz 
= GetSize(); 
 226     int w 
= chkBmp
.GetWidth(), 
 227         h 
= chkBmp
.GetHeight(); 
 228     m_borderX 
= sz
.x 
- m_marginX 
- w
; 
 229     m_borderY 
= sz
.y 
- m_marginY 
- h
; 
 231     DoMoveWindow(pos
.x
, pos
.y
, size
.x
, size
.y
); 
 237 void wxDropdownButton::RecreateBitmaps(int w
, int h
) 
 241     int borderX 
= m_marginX 
+ m_borderX
; 
 242     int borderY 
= m_marginY 
+ m_borderY
; 
 243     int bw 
= w 
- borderX
; 
 244     int bh 
= h 
- borderY
; 
 246     wxBitmap 
bmp(bw
, bh
); 
 247     wxBitmap 
bmpSel(bw
, bh
); 
 250     wxRendererNative
& renderer 
= wxRendererNative::Get(); 
 252     dc
.SelectObject(bmp
); 
 254     if ( m_useDropArrow 
) 
 256         // Use DrawDropArrow on transparent background. 
 258         wxColour 
magic(255,0,255); 
 259         wxBrush 
magicBrush(magic
); 
 263         dc
.SetBrush( magicBrush 
); 
 264         dc
.SetPen( *wxTRANSPARENT_PEN 
); 
 265         dc
.DrawRectangle(0,0,bw
,bh
); 
 266         renderer
.DrawDropArrow(this, dc
, r
); 
 267         dc
.SelectObject( wxNullBitmap 
); 
 268         wxMask 
*mask 
= new wxMask( bmp
, magic 
); 
 271         dc
.SelectObject(bmpSel
); 
 273         dc
.SetBrush( magicBrush 
); 
 274         dc
.SetPen( *wxTRANSPARENT_PEN 
); 
 275         dc
.DrawRectangle(0,0,bw
,bh
); 
 276         renderer
.DrawDropArrow(this, dc
, r
, wxCONTROL_PRESSED
); 
 277         dc
.SelectObject( wxNullBitmap 
); 
 278         mask 
= new wxMask( bmpSel
, magic 
); 
 279         bmpSel
.SetMask( mask 
); 
 283         // Use DrawComboBoxDropButton for the entire button 
 284         // (also render extra "hot" button state). 
 286         renderer
.DrawComboBoxDropButton(this, dc
, r
); 
 288         dc
.SelectObject(bmpSel
); 
 290         renderer
.DrawComboBoxDropButton(this, dc
, r
, wxCONTROL_PRESSED
); 
 292         wxBitmap 
bmpHot(bw
,bh
); 
 293         dc
.SelectObject(bmpHot
); 
 294         renderer
.DrawComboBoxDropButton(this, dc
, r
, wxCONTROL_CURRENT
); 
 301     SetBitmapSelected(bmpSel
); 
 305 void wxDropdownButton::DoMoveWindow(int x
, int y
, int w
, int h
) 
 308         w 
= DROPBUT_DEFAULT_WIDTH
; 
 310     wxBitmapButton::DoMoveWindow(x
, y
, w
, h
); 
 314 void wxDropdownButton::OnSize(wxSizeEvent
& event
) 
 316     if ( m_borderX 
>= 0 && m_borderY 
>= 0 ) 
 319         GetClientSize(&w
,&h
); 
 321         if ( w 
> 1 && h 
> 1 ) 
 322             RecreateBitmaps(w
,h
); 
 328 void wxDropdownButton::OnMouseEnter(wxMouseEvent
& event
) 
 330     if ( !m_useDropArrow 
) 
 331         SetBitmapLabel(m_bmpHot
); 
 337 void wxDropdownButton::OnMouseLeave(wxMouseEvent
& event
) 
 339     if ( !m_useDropArrow 
) 
 340         SetBitmapLabel(m_bmpNormal
); 
 348 #include "wx/popupwin.h" 
 350 class wxDatePopupInternal 
: public wxPopupTransientWindow
 
 353     wxDatePopupInternal(wxWindow 
*parent
) : wxPopupTransientWindow(parent
) { } 
 355     void ShowAt(int x
, int y
) 
 357         Position(wxPoint(x
, y
), wxSize(0, 0)); 
 367 #else // !wxUSE_POPUPWIN 
 369 class wxDatePopupInternal 
: public wxDialog
 
 372     wxDatePopupInternal(wxWindow 
*parent
) 
 382     void ShowAt(int x
, int y
) 
 394 #endif // wxUSE_POPUPWIN/!wxUSE_POPUPWIN 
 396 // ============================================================================ 
 397 // wxDatePickerCtrlGeneric implementation 
 398 // ============================================================================ 
 400 BEGIN_EVENT_TABLE(wxDatePickerCtrlGeneric
, wxDatePickerCtrlBase
) 
 401     EVT_BUTTON(CTRLID_BTN
, wxDatePickerCtrlGeneric::OnClick
) 
 402     EVT_TEXT(CTRLID_TXT
, wxDatePickerCtrlGeneric::OnText
) 
 403     EVT_CHILD_FOCUS(wxDatePickerCtrlGeneric::OnChildSetFocus
) 
 404     EVT_SIZE(wxDatePickerCtrlGeneric::OnSize
) 
 407 #ifndef wxHAS_NATIVE_DATEPICKCTRL 
 408     IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl
, wxControl
) 
 411 // ---------------------------------------------------------------------------- 
 413 // ---------------------------------------------------------------------------- 
 415 bool wxDatePickerCtrlGeneric::Create(wxWindow 
*parent
, 
 417                                      const wxDateTime
& date
, 
 421                                      const wxValidator
& validator
, 
 422                                      const wxString
& name
) 
 424     wxASSERT_MSG( !(style 
& wxDP_SPIN
), 
 425                   _T("wxDP_SPIN style not supported, use wxDP_DEFAULT") ); 
 427     if ( !wxControl::Create(parent
, id
, pos
, size
, 
 428                             style 
| wxCLIP_CHILDREN 
| wxWANTS_CHARS
, 
 437     m_txt 
= new wxTextCtrl(this, CTRLID_TXT
, wxEmptyString
, wxDefaultPosition
, wxDefaultSize
, TXTCTRL_FLAGS
); 
 439     m_txt
->Connect(wxEVT_KEY_DOWN
, 
 440                    wxKeyEventHandler(wxDatePickerCtrlGeneric::OnEditKey
), 
 442     m_txt
->Connect(wxEVT_KILL_FOCUS
, 
 443                    wxFocusEventHandler(wxDatePickerCtrlGeneric::OnKillFocus
), 
 446     m_btn 
= new wxDropdownButton(this, CTRLID_BTN
, wxDefaultPosition
, wxDefaultSize
, wxBU_COMBO
); 
 448     m_popup 
= new wxDatePopupInternal(this); 
 449     m_popup
->SetFont(GetFont()); 
 451     wxPanel 
*panel
=new wxPanel(m_popup
, CTRLID_PAN
, 
 452                                wxPoint(0, 0), wxDefaultSize
, 
 454     m_cal 
= new wxCalendarCtrl(panel
, CTRLID_CAL
, wxDefaultDateTime
, 
 455                                wxPoint(0, 0), wxDefaultSize
, 
 456                                wxCAL_SHOW_HOLIDAYS 
| wxSUNKEN_BORDER
); 
 457     m_cal
->Connect(wxEVT_CALENDAR_SEL_CHANGED
, 
 458                    wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange
), 
 460     m_cal
->Connect(wxEVT_KEY_DOWN
, 
 461                    wxKeyEventHandler(wxDatePickerCtrlGeneric::OnCalKey
), 
 463     m_cal
->Connect(wxEVT_CALENDAR_DOUBLECLICKED
, 
 464                    wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange
), 
 466     m_cal
->Connect(wxEVT_CALENDAR_DAY_CHANGED
, 
 467                    wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange
), 
 469     m_cal
->Connect(wxEVT_CALENDAR_MONTH_CHANGED
, 
 470                    wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange
), 
 472     m_cal
->Connect(wxEVT_CALENDAR_YEAR_CHANGED
, 
 473                    wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange
), 
 476     wxWindow 
*yearControl 
= m_cal
->GetYearControl(); 
 478     Connect(wxEVT_SET_FOCUS
, 
 479             wxFocusEventHandler(wxDatePickerCtrlGeneric::OnSetFocus
)); 
 481     wxClientDC 
dc(yearControl
); 
 482     dc
.SetFont(yearControl
->GetFont()); 
 483     wxCoord width
, dummy
; 
 484     dc
.GetTextExtent(wxT("2000"), &width
, &dummy
); 
 485     width 
+= ConvertDialogToPixels(wxSize(20, 0)).x
; 
 487     wxSize calSize 
= m_cal
->GetBestSize(); 
 488     wxSize yearSize 
= yearControl
->GetSize(); 
 491     wxPoint yearPosition 
= yearControl
->GetPosition(); 
 493     SetFormat(wxT("%x")); 
 495     width 
= yearPosition
.x 
+ yearSize
.x
+2+CALBORDER
/2; 
 496     if (width 
< calSize
.x
-4) 
 499     int calPos 
= (width
-calSize
.x
)/2; 
 505     m_cal
->SetSize(calPos
, 0, calSize
.x
, calSize
.y
); 
 506     yearControl
->SetSize(width
-yearSize
.x
-CALBORDER
/2, yearPosition
.y
, 
 507                          yearSize
.x
, yearSize
.y
); 
 508     m_cal
->GetMonthControl()->Move(0, 0); 
 512     panel
->SetClientSize(width
+CALBORDER
/2, calSize
.y
-2+CALBORDER
); 
 513     m_popup
->SetClientSize(panel
->GetSize()); 
 516     SetValue(date
.IsValid() ? date 
: wxDateTime::Today()); 
 518     SetBestFittingSize(size
); 
 520     SetBackgroundColour(m_txt
->GetBackgroundColour()); 
 526 void wxDatePickerCtrlGeneric::Init() 
 534     m_ignoreDrop 
= false; 
 537 wxDatePickerCtrlGeneric::~wxDatePickerCtrlGeneric() 
 545 bool wxDatePickerCtrlGeneric::Destroy() 
 561     return wxControl::Destroy(); 
 564 // ---------------------------------------------------------------------------- 
 565 // overridden base class methods 
 566 // ---------------------------------------------------------------------------- 
 568 void wxDatePickerCtrlGeneric::DoMoveWindow(int x
, int y
, int w
, int h
) 
 570     wxControl::DoMoveWindow(x
, y
, w
, h
); 
 576 wxSize 
wxDatePickerCtrlGeneric::DoGetBestSize() const 
 578     int bh
=m_btn
->GetBestSize().y
; 
 579     int eh
=m_txt
->GetBestSize().y
; 
 580     return wxSize(DEFAULT_ITEM_WIDTH
, bh 
> eh 
? bh 
: eh
); 
 584 bool wxDatePickerCtrlGeneric::Show(bool show
) 
 586     if ( !wxControl::Show(show
) ) 
 604 bool wxDatePickerCtrlGeneric::Enable(bool enable
) 
 606     if ( !wxControl::Enable(enable
) ) 
 618         m_btn
->Enable(enable
); 
 623 // ---------------------------------------------------------------------------- 
 624 // wxDatePickerCtrlGeneric API 
 625 // ---------------------------------------------------------------------------- 
 628 wxDatePickerCtrlGeneric::SetDateRange(const wxDateTime
& lowerdate
, 
 629                                       const wxDateTime
& upperdate
) 
 631     return m_cal
->SetDateRange(lowerdate
, upperdate
); 
 634 bool wxDatePickerCtrlGeneric::SetFormat(const wxChar 
*fmt
) 
 637     dt
.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d")); 
 638     wxString str
=dt
.Format(fmt
); 
 639     wxChar 
*p
=(wxChar
*)str
.c_str(); 
 641     m_format
=wxEmptyString
; 
 646         if (n 
== dt
.GetDay()) 
 648             m_format
.Append(wxT("%d")); 
 651         else if (n 
== (int)dt
.GetMonth()+1) 
 653             m_format
.Append(wxT("%m")); 
 656         else if (n 
== dt
.GetYear()) 
 658             m_format
.Append(wxT("%Y")); 
 661         else if (n 
== (dt
.GetYear() % 100)) 
 663             if (GetWindowStyle() & wxDP_SHOWCENTURY
) 
 664                 m_format
.Append(wxT("%Y")); 
 666                 m_format
.Append(wxT("%y")); 
 670             m_format
.Append(*p
++); 
 675         wxArrayString allowedChars
; 
 676         for ( wxChar c 
= _T('0'); c 
<= _T('9'); c
++ ) 
 677             allowedChars
.Add(wxString(c
, 1)); 
 679         const wxChar 
*p 
= m_format
.c_str(); 
 685                 allowedChars
.Add(wxString(*p
++, 1)); 
 689         wxTextValidator 
tv(wxFILTER_INCLUDE_CHAR_LIST
); 
 690         tv
.SetIncludes(allowedChars
); 
 691         m_txt
->SetValidator(tv
); 
 694         if (m_currentDate
.IsValid()) 
 695             m_txt
->SetValue(m_currentDate
.Format(m_format
)); 
 702 wxDateTime 
wxDatePickerCtrlGeneric::GetValue() const 
 704     return m_currentDate
; 
 708 void wxDatePickerCtrlGeneric::SetValue(const wxDateTime
& date
) 
 713     // we need to suppress the event sent from wxTextCtrl as calling our 
 714     // SetValue() should not result in an event being sent (wxTextCtrl is 
 715     // an exception to this rule) 
 716     gs_inSetValue 
= this; 
 718     if ( date
.IsValid() ) 
 720         m_txt
->SetValue(date
.Format(m_format
)); 
 724         wxASSERT_MSG( HasFlag(wxDP_ALLOWNONE
), 
 725                         _T("this control must have a valid date") ); 
 727         m_txt
->SetValue(wxEmptyString
); 
 730     gs_inSetValue 
= NULL
; 
 732     m_currentDate 
= date
; 
 736 bool wxDatePickerCtrlGeneric::GetRange(wxDateTime 
*dt1
, wxDateTime 
*dt2
) const 
 739         *dt1 
= m_cal
->GetLowerDateLimit(); 
 741         *dt2 
= m_cal
->GetUpperDateLimit(); 
 747 wxDatePickerCtrlGeneric::SetRange(const wxDateTime 
&dt1
, const wxDateTime 
&dt2
) 
 749     m_cal
->SetDateRange(dt1
, dt2
); 
 752 // ---------------------------------------------------------------------------- 
 754 // ---------------------------------------------------------------------------- 
 756 void wxDatePickerCtrlGeneric::DropDown(bool down
) 
 763             if (!m_txt
->GetValue().empty()) 
 764                 dt
.ParseFormat(m_txt
->GetValue(), m_format
); 
 769                 m_cal
->SetDate(wxDateTime::Today()); 
 771             wxPoint pos
=GetParent()->ClientToScreen(GetPosition()); 
 772             m_popup
->ShowAt(pos
.x
, pos
.y 
+ GetSize().y
); 
 786 void wxDatePickerCtrlGeneric::OnSize(wxSizeEvent
& event
) 
 790         wxSize sz 
= GetClientSize(); 
 792         wxSize bs
=m_btn
->GetSize(); 
 793         int eh
=m_txt
->GetBestSize().y
; 
 795         m_txt
->SetSize(0, TXTPOSY
, sz
.x
-bs
.x
, sz
.y 
> eh 
? eh
-TXTPOSY 
: sz
.y
-TXTPOSY
); 
 796         m_btn
->SetSize(sz
.x 
- bs
.x
, 0, bs
.x
, sz
.y
); 
 803 void wxDatePickerCtrlGeneric::OnChildSetFocus(wxChildFocusEvent 
&ev
) 
 806     m_ignoreDrop 
= false; 
 808     wxWindow  
*w
=(wxWindow
*)ev
.GetEventObject(); 
 819         if (::wxFindWindowAtPoint(::wxGetMousePosition()) == m_btn
) 
 825 void wxDatePickerCtrlGeneric::OnClick(wxCommandEvent
& WXUNUSED(event
)) 
 829         m_ignoreDrop 
= false; 
 840 void wxDatePickerCtrlGeneric::OnSetFocus(wxFocusEvent
& WXUNUSED(ev
)) 
 845         m_txt
->SetSelection(-1, -1); // select everything 
 850 void wxDatePickerCtrlGeneric::OnKillFocus(wxFocusEvent 
&ev
) 
 858     dt
.ParseFormat(m_txt
->GetValue(), m_format
); 
 861         if ( !HasFlag(wxDP_ALLOWNONE
) ) 
 866         m_txt
->SetValue(dt
.Format(m_format
)); 
 868         m_txt
->SetValue(wxEmptyString
); 
 870     // notify that we had to change the date after validation 
 871     if ( (dt
.IsValid() && (!m_currentDate
.IsValid() || m_currentDate 
!= dt
)) || 
 872             (!dt
.IsValid() && m_currentDate
.IsValid()) ) 
 875         wxDateEvent 
event(this, dt
, wxEVT_DATE_CHANGED
); 
 876         GetEventHandler()->ProcessEvent(event
); 
 881 void wxDatePickerCtrlGeneric::OnSelChange(wxCalendarEvent 
&ev
) 
 885         m_currentDate 
= m_cal
->GetDate(); 
 886         m_txt
->SetValue(m_currentDate
.Format(m_format
)); 
 887         if (ev
.GetEventType() == wxEVT_CALENDAR_DOUBLECLICKED
) 
 893     ev
.SetEventObject(this); 
 895     GetParent()->ProcessEvent(ev
); 
 897     wxDateEvent 
dev(this, ev
.GetDate(), wxEVT_DATE_CHANGED
); 
 898     GetParent()->ProcessEvent(dev
); 
 902 void wxDatePickerCtrlGeneric::OnText(wxCommandEvent 
&ev
) 
 906         // artificial event resulting from our own SetValue() call, ignore it 
 910     ev
.SetEventObject(this); 
 912     GetParent()->ProcessEvent(ev
); 
 914     // We'll create an additional event if the date is valid. 
 915     // If the date isn't valid, the user's probably in the middle of typing 
 916     wxString txt 
= m_txt
->GetValue(); 
 920         dt
.ParseFormat(txt
, m_format
); 
 925     wxCalendarEvent 
cev(m_cal
, wxEVT_CALENDAR_SEL_CHANGED
); 
 926     cev
.SetEventObject(this); 
 930     GetParent()->ProcessEvent(cev
); 
 932     wxDateEvent 
dev(this, dt
, wxEVT_DATE_CHANGED
); 
 933     GetParent()->ProcessEvent(dev
); 
 937 void wxDatePickerCtrlGeneric::OnEditKey(wxKeyEvent 
& ev
) 
 939     if (ev
.GetKeyCode() == WXK_DOWN 
&& !ev
.HasModifiers()) 
 946 void wxDatePickerCtrlGeneric::OnCalKey(wxKeyEvent 
& ev
) 
 948     if (ev
.GetKeyCode() == WXK_ESCAPE 
&& !ev
.HasModifiers()) 
 954 #endif // wxUSE_DATEPICKCTRL_GENERIC 
 956 #endif // wxUSE_DATEPICKCTRL