datectlg.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 958 行 · 第 1/2 页

CPP
958
字号
/////////////////////////////////////////////////////////////////////////////
// Name:        generic/datectlg.cpp
// Purpose:     generic wxDatePickerCtrlGeneric implementation
// Author:      Andreas Pflug
// Modified by:
// Created:     2005-01-19
// RCS-ID:      $Id: datectlg.cpp,v 1.36 2005/08/04 00:34:03 VZ Exp $
// Copyright:   (c) 2005 Andreas Pflug <pgadmin@pse-consulting.de>
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// ============================================================================
// declarations
// ============================================================================

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#if wxUSE_DATEPICKCTRL

#include "wx/datectrl.h"

// use this version if we're explicitly requested to do it or if it's the only
// one we have
#if !defined(wxHAS_NATIVE_DATEPICKCTRL) || \
        (defined(wxUSE_DATEPICKCTRL_GENERIC) && wxUSE_DATEPICKCTRL_GENERIC)

#ifndef WX_PRECOMP
    #include "wx/bmpbuttn.h"
    #include "wx/dialog.h"
    #include "wx/dcmemory.h"
    #include "wx/panel.h"
    #include "wx/textctrl.h"
    #include "wx/valtext.h"
#endif

#ifdef wxHAS_NATIVE_DATEPICKCTRL
    // this header is not included from wx/datectrl.h if we have a native
    // version, but we do need it here
    #include "wx/generic/datectrl.h"
#else
    // we need to define _WX_DEFINE_DATE_EVENTS_ before including wx/dateevt.h to
    // define the event types we use if we're the only date picker control version
    // being compiled -- otherwise it's defined in the native version implementation
    #define _WX_DEFINE_DATE_EVENTS_
#endif

#include "wx/dateevt.h"

#include "wx/calctrl.h"
#include "wx/renderer.h"

// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------

enum
{
    CTRLID_TXT = 101,
    CTRLID_CAL,
    CTRLID_BTN,
    CTRLID_PAN
};

#ifndef DEFAULT_ITEM_WIDTH
    #define DEFAULT_ITEM_WIDTH 100
#endif

#if defined(__WXMSW__)
    #undef wxUSE_POPUPWIN
    #define wxUSE_POPUPWIN    0  // Popup not working
    #define TXTCTRL_FLAGS     wxNO_BORDER
    #define CALBORDER         0
    #define TXTPOSY           1
#elif defined(__WXGTK__)
    #define TXTCTRL_FLAGS     0
    #define CALBORDER         4
    #define TXTPOSY           0
#else
    #define TXTCTRL_FLAGS     0
    #define CALBORDER         4
    #define TXTPOSY           0
#endif

// ----------------------------------------------------------------------------
// global variables
// ----------------------------------------------------------------------------

// this should have been a flag in wxDatePickerCtrlGeneric itself but adding it
// there now would break backwards compatibility, so put it here as a global:
// this shouldn't be a big problem as only one (GUI) thread normally can call
// wxDatePickerCtrlGeneric::SetValue() and so it can be only ever used for one
// control at a time
//
// if the value is not NULL, it points to the control which is inside SetValue()
static wxDatePickerCtrlGeneric *gs_inSetValue = NULL;

// ----------------------------------------------------------------------------
// local classes
// ----------------------------------------------------------------------------

// This flag indicates that combo box style drop button is to be created
#define wxBU_COMBO          0x0400


class wxDropdownButton : public wxBitmapButton
{
public:
    wxDropdownButton() { Init(); }
    wxDropdownButton(wxWindow *parent,
                     wxWindowID id,
                     const wxPoint& pos = wxDefaultPosition,
                     const wxSize& size = wxDefaultSize,
                     long style=0,
                     const wxValidator& validator = wxDefaultValidator);

    bool Create(wxWindow *parent,
                wxWindowID id,
                const wxPoint& pos = wxDefaultPosition,
                const wxSize& size = wxDefaultSize,
                long style = 0,
                const wxValidator& validator = wxDefaultValidator);

    virtual void DoMoveWindow(int x, int y, int w, int h);

protected:

    void OnSize(wxSizeEvent& event);
    void OnMouseEnter(wxMouseEvent& event);
    void OnMouseLeave(wxMouseEvent& event);

    void RecreateBitmaps(int w, int h);

    wxBitmap    m_bmpNormal;
    wxBitmap    m_bmpHot;

    int         m_borderX, m_borderY;

    // True if DrawDropArrow should be used instead of DrawComboBoxDropButton
    bool        m_useDropArrow;

private:

    void Init()
    {
        m_borderX = -1;
        m_borderY = -1;
    }

    DECLARE_EVENT_TABLE()
    DECLARE_DYNAMIC_CLASS_NO_COPY(wxDropdownButton)
};


// Below, macro DROPBUT_USEDROPARROW should return false when
// DrawComboBoxDropButton is to be used to render the entire button.
// COMBOST is non-zero if wxBU_COMBO was set.

#if defined(__WXMSW__)

    #define DROPBUT_USEDROPARROW(COMBOST)   (COMBOST?false:true)
    #define DROPBUT_DEFAULT_WIDTH           17

#elif defined(__WXGTK__)

    #define DROPBUT_USEDROPARROW(COMBOST)   true
    #define DROPBUT_DEFAULT_WIDTH           19

#else

    #define DROPBUT_USEDROPARROW(COMBOST)   true
    #define DROPBUT_DEFAULT_WIDTH           17

#endif


IMPLEMENT_DYNAMIC_CLASS(wxDropdownButton, wxBitmapButton)


BEGIN_EVENT_TABLE(wxDropdownButton,wxBitmapButton)
    EVT_ENTER_WINDOW(wxDropdownButton::OnMouseEnter)
    EVT_LEAVE_WINDOW(wxDropdownButton::OnMouseLeave)
    EVT_SIZE(wxDropdownButton::OnSize)
END_EVENT_TABLE()


wxDropdownButton::wxDropdownButton(wxWindow *parent,
                                   wxWindowID id,
                                   const wxPoint& pos,
                                   const wxSize& size,
                                   long style,
                                   const wxValidator& validator)
{
    Init();
    Create(parent, id, pos, size, style, validator);
}


bool wxDropdownButton::Create(wxWindow *parent,
                              wxWindowID id,
                              const wxPoint& pos,
                              const wxSize& size,
                              long style,
                              const wxValidator& validator)
{
    m_marginX = 0;
    m_marginY = 0;

    m_useDropArrow = DROPBUT_USEDROPARROW(style & wxBU_COMBO);

    wxBitmap chkBmp(15,15);  // arbitrary
    if ( !wxBitmapButton::Create(parent, id, chkBmp,
                                 pos, wxDefaultSize,
                                 style | (m_useDropArrow ? wxBU_AUTODRAW : wxNO_BORDER),
                                 validator) )
        return false;

    const wxSize sz = GetSize();
    int w = chkBmp.GetWidth(),
        h = chkBmp.GetHeight();
    m_borderX = sz.x - m_marginX - w;
    m_borderY = sz.y - m_marginY - h;

    DoMoveWindow(pos.x, pos.y, size.x, size.y);

    return true;
}


void wxDropdownButton::RecreateBitmaps(int w, int h)
{
    wxMemoryDC dc;

    int borderX = m_marginX + m_borderX;
    int borderY = m_marginY + m_borderY;
    int bw = w - borderX;
    int bh = h - borderY;

    wxBitmap bmp(bw, bh);
    wxBitmap bmpSel(bw, bh);
    wxRect r(0,0,w,h);

    wxRendererNative& renderer = wxRendererNative::Get();

    dc.SelectObject(bmp);

    if ( m_useDropArrow )
    {
        // Use DrawDropArrow on transparent background.

        wxColour magic(255,0,255);
        wxBrush magicBrush(magic);
        r.x = -(borderX/2);
        r.y = -(borderY/2);

        dc.SetBrush( magicBrush );
        dc.SetPen( *wxTRANSPARENT_PEN );
        dc.DrawRectangle(0,0,bw,bh);
        renderer.DrawDropArrow(this, dc, r);
        dc.SelectObject( wxNullBitmap );
        wxMask *mask = new wxMask( bmp, magic );
        bmp.SetMask( mask );

        dc.SelectObject(bmpSel);

        dc.SetBrush( magicBrush );
        dc.SetPen( *wxTRANSPARENT_PEN );
        dc.DrawRectangle(0,0,bw,bh);
        renderer.DrawDropArrow(this, dc, r, wxCONTROL_PRESSED);
        dc.SelectObject( wxNullBitmap );
        mask = new wxMask( bmpSel, magic );
        bmpSel.SetMask( mask );
    }
    else
    {
        // Use DrawComboBoxDropButton for the entire button
        // (also render extra "hot" button state).

        renderer.DrawComboBoxDropButton(this, dc, r);

        dc.SelectObject(bmpSel);

        renderer.DrawComboBoxDropButton(this, dc, r, wxCONTROL_PRESSED);

        wxBitmap bmpHot(bw,bh);
        dc.SelectObject(bmpHot);
        renderer.DrawComboBoxDropButton(this, dc, r, wxCONTROL_CURRENT);

        m_bmpNormal = bmp;
        m_bmpHot = bmpHot;
    }

    SetBitmapLabel(bmp);
    SetBitmapSelected(bmpSel);
}


void wxDropdownButton::DoMoveWindow(int x, int y, int w, int h)
{
    if (w < 0)
        w = DROPBUT_DEFAULT_WIDTH;

    wxBitmapButton::DoMoveWindow(x, y, w, h);
}


void wxDropdownButton::OnSize(wxSizeEvent& event)
{
    if ( m_borderX >= 0 && m_borderY >= 0 )
    {
        int w, h;
        GetClientSize(&w,&h);

        if ( w > 1 && h > 1 )
            RecreateBitmaps(w,h);
    }
    event.Skip();
}


void wxDropdownButton::OnMouseEnter(wxMouseEvent& event)
{
    if ( !m_useDropArrow )
        SetBitmapLabel(m_bmpHot);

    event.Skip();
}


void wxDropdownButton::OnMouseLeave(wxMouseEvent& event)
{
    if ( !m_useDropArrow )
        SetBitmapLabel(m_bmpNormal);

    event.Skip();
}


#if wxUSE_POPUPWIN

#include "wx/popupwin.h"

class wxDatePopupInternal : public wxPopupTransientWindow
{
public:
    wxDatePopupInternal(wxWindow *parent) : wxPopupTransientWindow(parent) { }

    void ShowAt(int x, int y)
    {
        Position(wxPoint(x, y), wxSize(0, 0));
        Popup();
    }

    void Hide()
    {
        Dismiss();
    }
};

#else // !wxUSE_POPUPWIN

class wxDatePopupInternal : public wxDialog
{
public:
    wxDatePopupInternal(wxWindow *parent)
        : wxDialog(parent,
                   wxID_ANY,
                   wxEmptyString,
                   wxDefaultPosition,
                   wxDefaultSize,
                   wxSIMPLE_BORDER)
    {
    }

    void ShowAt(int x, int y)
    {
        Show();
        Move(x, y);
    }

    void Hide()
    {
        wxDialog::Hide();
    }
};

#endif // wxUSE_POPUPWIN/!wxUSE_POPUPWIN

// ============================================================================
// wxDatePickerCtrlGeneric implementation
// ============================================================================

BEGIN_EVENT_TABLE(wxDatePickerCtrlGeneric, wxDatePickerCtrlBase)
    EVT_BUTTON(CTRLID_BTN, wxDatePickerCtrlGeneric::OnClick)
    EVT_TEXT(CTRLID_TXT, wxDatePickerCtrlGeneric::OnText)
    EVT_CHILD_FOCUS(wxDatePickerCtrlGeneric::OnChildSetFocus)
    EVT_SIZE(wxDatePickerCtrlGeneric::OnSize)
END_EVENT_TABLE()

#ifndef wxHAS_NATIVE_DATEPICKCTRL
    IMPLEMENT_DYNAMIC_CLASS(wxDatePickerCtrl, wxControl)
#endif

// ----------------------------------------------------------------------------
// creation
// ----------------------------------------------------------------------------

bool wxDatePickerCtrlGeneric::Create(wxWindow *parent,
                                     wxWindowID id,
                                     const wxDateTime& date,
                                     const wxPoint& pos,
                                     const wxSize& size,
                                     long style,
                                     const wxValidator& validator,
                                     const wxString& name)
{
    wxASSERT_MSG( !(style & wxDP_SPIN),
                  _T("wxDP_SPIN style not supported, use wxDP_DEFAULT") );

    if ( !wxControl::Create(parent, id, pos, size,
                            style | wxCLIP_CHILDREN | wxWANTS_CHARS,
                            validator, name) )

    {
        return false;
    }

    InheritAttributes();

    m_txt = new wxTextCtrl(this, CTRLID_TXT, wxEmptyString, wxDefaultPosition, wxDefaultSize, TXTCTRL_FLAGS);

    m_txt->Connect(wxEVT_KEY_DOWN,
                   wxKeyEventHandler(wxDatePickerCtrlGeneric::OnEditKey),
                   NULL, this);
    m_txt->Connect(wxEVT_KILL_FOCUS,
                   wxFocusEventHandler(wxDatePickerCtrlGeneric::OnKillFocus),
                   NULL, this);

    m_btn = new wxDropdownButton(this, CTRLID_BTN, wxDefaultPosition, wxDefaultSize, wxBU_COMBO);

    m_popup = new wxDatePopupInternal(this);
    m_popup->SetFont(GetFont());

    wxPanel *panel=new wxPanel(m_popup, CTRLID_PAN,
                               wxPoint(0, 0), wxDefaultSize,
                               wxSUNKEN_BORDER);
    m_cal = new wxCalendarCtrl(panel, CTRLID_CAL, wxDefaultDateTime,
                               wxPoint(0, 0), wxDefaultSize,
                               wxCAL_SHOW_HOLIDAYS | wxSUNKEN_BORDER);
    m_cal->Connect(wxEVT_CALENDAR_SEL_CHANGED,
                   wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange),
                   NULL, this);
    m_cal->Connect(wxEVT_KEY_DOWN,
                   wxKeyEventHandler(wxDatePickerCtrlGeneric::OnCalKey),
                   NULL, this);
    m_cal->Connect(wxEVT_CALENDAR_DOUBLECLICKED,
                   wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange),
                   NULL, this);
    m_cal->Connect(wxEVT_CALENDAR_DAY_CHANGED,
                   wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange),
                   NULL, this);
    m_cal->Connect(wxEVT_CALENDAR_MONTH_CHANGED,
                   wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange),
                   NULL, this);
    m_cal->Connect(wxEVT_CALENDAR_YEAR_CHANGED,
                   wxCalendarEventHandler(wxDatePickerCtrlGeneric::OnSelChange),
                   NULL, this);

    wxWindow *yearControl = m_cal->GetYearControl();

    Connect(wxEVT_SET_FOCUS,
            wxFocusEventHandler(wxDatePickerCtrlGeneric::OnSetFocus));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?