📄 bcgpdatetimectrl.cpp
字号:
// BCGCalendarButton.cpp : implementation file
// This is a part of the BCGControlBar Library
// Copyright (C) 1998-2000 BCGSoft Ltd.
// All rights reserved.
//
// This source code can be used, distributed or modified
// only under terms and conditions
// of the accompanying license agreement.
//
#include "stdafx.h"
#ifndef BCG_NO_CALENDAR
#include "BCGCBPro.h"
#include "BCGPDateTimeCtrl.h"
#include "BCGPCalendarBar.h"
#include "CalendarPopup.h"
#include "BCGPWinXPVisualManager.h"
#include "BCGPToolbarComboBoxButton.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static const int iSpinWidth = 15;
static const int iDropButtonWidth = 17;
static const int iSpinID = 1;
static const COLORREF clrTransparent = RGB (255, 0, 255);
static const int iFirstAllowedYear = 100; // COleDateTime limitation
static const int iLastAllowedYear = 9999; // COleDateTime limitation
static const UINT BCGDATETIME_HOLDTIMER = ::RegisterWindowMessage (_T("BCGDATETIME_HOLDTIMER"));
const UINT CBCGPDateTimeCtrl::DTM_SPIN = 0x1;
const UINT CBCGPDateTimeCtrl::DTM_DATE = 0x2;
const UINT CBCGPDateTimeCtrl::DTM_TIME = 0x4;
const UINT CBCGPDateTimeCtrl::DTM_CHECKBOX = 0x8;
const UINT CBCGPDateTimeCtrl::DTM_DROPCALENDAR = 0x10;
const UINT CBCGPDateTimeCtrl::DTM_TIME24H = 0x20;
const UINT CBCGPDateTimeCtrl::DTM_CHECKED = 0x40;
const UINT CBCGPDateTimeCtrl::DTM_TIME24HBYLOCALE = 0x80;
static int GetDaysInMonth (int iMonth, int iYear)
{
static int nMonthLen [] =
{
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int nRes = nMonthLen [iMonth - 1];
if (iMonth == 2 && iYear % 4 == 0 &&
(iYear % 100 != 0 || iYear % 400 == 0))
{
nRes = 29;
}
return nRes;
}
/////////////////////////////////////////////////////////////////////////////
// CBCGPDateTimeCtrl
IMPLEMENT_DYNAMIC(CBCGPDateTimeCtrl, CButton)
CBCGPDateTimeCtrl::CBCGPDateTimeCtrl()
{
m_checkButton = TRUE;
m_dropCalendar = TRUE;
m_showDate = TRUE;
m_showTime = TRUE;
m_spinButton = TRUE;
m_type2DigitsInYear = TRUE;
m_maxYear2Digits = 2090;
m_bCheckBoxIsAvailable = FALSE;
m_iPartNum = 0;
m_bIsChecked = TRUE;
m_Date = COleDateTime::GetCurrentTime ();
m_iPrevDigit = -1;
m_bShowSelection = FALSE;
m_bDropButtonIsPressed = FALSE;
m_pPopup = NULL;
m_bDropButtonIsPressed = FALSE;
m_bMouseOnDropButton = FALSE;
for (int i = 0; i < MAX_PARTS; i ++)
{
m_arPartRects [i].SetRectEmpty ();
}
m_rectText.SetRectEmpty ();
m_bAutoResize = TRUE;
m_iControlWidth = 0;
m_iControlHeight = 0;
m_iYearPos = 0;
m_monthFormat = 0;
m_MinDate = COleDateTime (iFirstAllowedYear, 1, 1, 0, 0, 0);
m_MaxDate = COleDateTime (iLastAllowedYear, 12, 31, 23, 59, 59);
m_weekStart = 1;
m_b24HoursByLocale = TRUE;
m_hFont = NULL;
m_bIsInitialized = FALSE;
m_bDrawDateTimeOnly = FALSE;
m_colorText = (COLORREF)-1;
}
CBCGPDateTimeCtrl::~CBCGPDateTimeCtrl()
{
}
BEGIN_MESSAGE_MAP(CBCGPDateTimeCtrl, CButton)
//{{AFX_MSG_MAP(CBCGPDateTimeCtrl)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_CREATE()
ON_WM_GETDLGCODE()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_KEYDOWN()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_ERASEBKGND()
ON_WM_NCCALCSIZE()
ON_WM_NCPAINT()
ON_WM_SETCURSOR()
ON_WM_SIZE()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_SETFONT, OnSetFont)
ON_MESSAGE(WM_GETFONT, OnGetFont)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBCGPDateTimeCtrl message handlers
void CBCGPDateTimeCtrl::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
ASSERT (lpDIS != NULL);
ASSERT (lpDIS->CtlType == ODT_BUTTON);
CDC* pDC = CDC::FromHandle (lpDIS->hDC);
ASSERT_VALID (pDC);
CBCGPDefaultLocale dl;
CRect rectClient = lpDIS->rcItem;
pDC->FillSolidRect (&rectClient,
IsWindowEnabled () ? globalData.clrWindow : globalData.clrBtnFace);
pDC->SetBkMode (TRANSPARENT);
CFont* pPrevFont = m_hFont == NULL ?
(CFont*) pDC->SelectStockObject (DEFAULT_GUI_FONT) :
pDC->SelectObject (CFont::FromHandle (m_hFont));
ASSERT (pPrevFont != NULL);
if (!m_bDrawDateTimeOnly)
{
// Draw check box:
DrawCheckBox (pDC, lpDIS->itemState);
// Draw "Drop Date combo" button:
DrawDateDropButton (pDC, lpDIS->itemState);
}
// Draw date/time parts:
int iStart = m_bCheckBoxIsAvailable ? 1 : 0;
for (int i = iStart; i < m_iPartsNumber; i ++)
{
CString str = m_Date.Format (GetPartFormat (i));
CRect rect = m_arPartRects [i];
if (m_bIsChecked && m_bShowSelection && i == m_iPartNum) // Selected part
{
CRect rectFill = rect;
pDC->DrawText (str, rectFill,
DT_SINGLELINE | DT_VCENTER | DT_CENTER | DT_CALCRECT);
int iOffset = (m_rectText.Height () - rectFill.Height ()) / 2;
rectFill.OffsetRect ((rect.Width () - rectFill.Width ()) / 2, iOffset);
pDC->FillSolidRect (rectFill, globalData.clrHilite);
pDC->SetTextColor (globalData.clrTextHilite);
}
else
{
pDC->SetTextColor (m_bIsChecked && IsWindowEnabled () ?
(m_colorText == (COLORREF)-1 ? globalData.clrWindowText : m_colorText) :
globalData.clrGrayedText);
}
pDC->DrawText (str, rect, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
//-----------------
// Draw separator:
//-----------------
if (i < m_iPartsNumber - 1)
{
CString strSeparator = _T(" ");
if (IsDatePart (i) && IsDatePart (i + 1))
{
strSeparator = m_strDateSeparator;
}
if (IsTimePart (i) && IsTimePart (i + 1))
{
strSeparator = m_strTimeSeparator;
}
rect.left = m_arPartRects [i].right;
rect.right = m_arPartRects [i + 1].left;
pDC->SetTextColor (m_bIsChecked && IsWindowEnabled () ?
(m_colorText == (COLORREF)-1 ? globalData.clrWindowText : m_colorText) :
globalData.clrGrayedText);
pDC->DrawText (strSeparator, rect, DT_SINGLELINE | DT_VCENTER);
}
}
pDC->SelectObject (pPrevFont);
}
//*****************************************************************************************
void CBCGPDateTimeCtrl::OnShowCalendarPopup ()
{
if (!m_dropCalendar)
return;
if (m_pPopup != NULL)
{
m_pPopup->SendMessage (WM_CLOSE);
m_pPopup = NULL;
return;
}
m_pPopup = new CCalendarPopup (this, m_Date);
m_pPopup->m_bEnabledInCustomizeMode = m_bEnabledInCustomizeMode;
m_bDropButtonIsPressed = TRUE;
RedrawWindow (m_rectDropButton);
CRect rectWindow;
GetWindowRect (rectWindow);
if (!m_pPopup->Create (this, rectWindow.left, rectWindow.bottom, NULL, TRUE))
{
ASSERT (FALSE);
m_pPopup = NULL;
TRACE(_T ("Calendar menu can't be used in the customization mode. You need to set CBCGPDateTimeCtrl::m_bEnabledInCustomizeMode\n"));
}
else
{
SetFirstDayOfWeek(m_weekStart - 1);
if (m_bEnabledInCustomizeMode)
{
CBCGPCalendarBar* pCalendarBar = DYNAMIC_DOWNCAST (
CBCGPCalendarBar, m_pPopup->GetMenuBar());
if (pCalendarBar != NULL)
{
ASSERT_VALID (pCalendarBar);
pCalendarBar->m_bInternal = TRUE;
}
}
if (m_bAutoSetFocus)
{
m_pPopup->GetMenuBar()->SetFocus ();
}
}
}
//************************************************************************************
void CBCGPDateTimeCtrl::OnLButtonDown(UINT /*nFlags*/, CPoint point)
{
m_iPrevDigit = -1;
int iPrevPart = m_iPartNum;
SetFocus ();
if (m_rectDropButton.PtInRect (point))
{
if (m_dropCalendar && m_bIsChecked && m_showDate)
{
m_bDropButtonIsPressed = TRUE;
SetCapture ();
RedrawWindow (m_rectDropButton);
OnShowCalendarPopup ();
}
return;
}
int iPartNum = GetPartFromPoint (point);
if (iPartNum == -1)
{
m_CurrPartType = NO;
if (m_rectText.PtInRect (point))
{
do
{
point.x++;
if (point.x > m_rectText.right)
{
return;
}
iPartNum = GetPartFromPoint (point);
}
while (iPartNum == -1);
}
else
{
return;
}
}
if (!m_bIsChecked &&
m_arPartsOrder [iPartNum] != CHECK_BOX)
{
return;
}
m_iPartNum = iPartNum;
m_CurrPartType = m_arPartsOrder [m_iPartNum];
if (m_CurrPartType == CHECK_BOX)
{
ToggleCheck ();
}
if (iPrevPart != m_iPartNum)
{
CRect rectPrevPart = m_arPartRects [iPrevPart];
rectPrevPart.InflateRect (1, 1);
RedrawWindow (rectPrevPart);
CRect rectPart = m_arPartRects [m_iPartNum];
rectPart.InflateRect (1, 1);
RedrawWindow (rectPart);
}
}
//****************************************************************************************
void CBCGPDateTimeCtrl::OnLButtonUp(UINT /*nFlags*/, CPoint /*point*/)
{
if (m_bDropButtonIsPressed)
{
m_bDropButtonIsPressed = FALSE;
RedrawWindow (m_rectDropButton);
if (GetCapture () == this)
{
ReleaseCapture ();
}
ASSERT (m_pPopup != NULL);
m_pPopup->SetFocus ();
}
}
//****************************************************************************************
void CBCGPDateTimeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
CButton::OnMouseMove(nFlags, point);
}
//****************************************************************************************
int CBCGPDateTimeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
BOOL bRC;
if (CButton::OnCreate(lpCreateStruct) == -1)
return -1;
CRect rectSpin (0, 0, 1, 1);
bRC = m_wndSpin.Create (WS_CHILD | WS_VISIBLE | UDS_ALIGNRIGHT | UDS_AUTOBUDDY,
rectSpin, this, iSpinID);
if (!bRC)
{
TRACE (_T ("IETDateTimeCtrl: Can't create spin button!\n"));
return -1;
}
CRect rectClient;
GetClientRect (rectClient);
AdjustControl (rectClient);
return 0;
}
//****************************************************************************************
UINT CBCGPDateTimeCtrl::OnGetDlgCode()
{
return DLGC_WANTARROWS | DLGC_WANTCHARS;
}
//****************************************************************************************
void CBCGPDateTimeCtrl::OnRButtonDown(UINT /*nFlags*/, CPoint /*point*/)
{
}
//****************************************************************************************
void CBCGPDateTimeCtrl::OnRButtonUp(UINT /*nFlags*/, CPoint /*point*/)
{
}
//****************************************************************************************
void CBCGPDateTimeCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (!IsWindowEnabled ())
{
return;
}
if (isdigit (nChar))
{
PushDigit (nChar - '0');
return;
}
if (nChar >= VK_NUMPAD0 && nChar <= VK_NUMPAD9)
{
PushDigit (nChar - VK_NUMPAD0);
return;
}
if (isalpha (nChar))
{
switch (m_CurrPartType)
{
case MONTH:
if (m_monthFormat != 2)
{
ChangeMonth (nChar);
}
break;
case AMPM:
ChangeAmPm (nChar);
break;
}
return;
}
m_iPrevDigit = -1;
switch (nChar)
{
case VK_DOWN:
ScrollCurrPart (-1);
break;
case VK_UP:
ScrollCurrPart (1);
break;
case VK_RIGHT:
SelectNext ();
break;
case VK_LEFT:
SelectPrev ();
break;
case VK_HOME:
ScrollCurrPartToLimit (TRUE);
break;
case VK_END:
ScrollCurrPartToLimit (FALSE);
break;
case VK_SPACE:
if (m_CurrPartType == CHECK_BOX)
{
ToggleCheck ();
}
else if (m_CurrPartType == AMPM)
{
ScrollCurrPart (1);
}
break;
}
CButton::OnKeyDown(nChar, nRepCnt, nFlags);
}
//****************************************************************************************
DATE CBCGPDateTimeCtrl::GetDate()
{
if (m_bIsChecked)
{
COleDateTime today = COleDateTime::GetCurrentTime ();
COleDateTime date ( m_showDate ? m_Date.GetYear () : today.GetYear (),
m_showDate ? m_Date.GetMonth () : today.GetMonth (),
m_showDate ? m_Date.GetDay () : today.GetDay (),
m_showTime ? m_Date.GetHour () : 0,
m_showTime ? m_Date.GetMinute () : 0,
0); // Always clear seconds
return (DATE) date;
}
else
{
COleDateTime dateEmpty;
return (DATE) dateEmpty;
}
}
//****************************************************************************************
void CBCGPDateTimeCtrl::SetDate(DATE newValue)
{
m_Date = COleDateTime (newValue);
if (m_bCheckBoxIsAvailable)
{
COleDateTime dateEmpty;
m_bIsChecked = (m_Date != dateEmpty);
if (m_spinButton)
{
m_wndSpin.EnableWindow (m_bIsChecked);
}
}
RedrawWindow ();
}
//****************************************************************************************
void CBCGPDateTimeCtrl::SetMinDate(DATE newValue)
{
COleDateTime dateMin = newValue;
COleDateTime dateEmpty;
if (m_MaxDate > dateMin || m_MaxDate == dateEmpty)
{
m_MinDate = dateMin;
if (m_Date < m_MinDate)
{
m_Date = m_MinDate;
OnDateChanged ();
}
RedrawWindow ();
}
}
//****************************************************************************************
DATE CBCGPDateTimeCtrl::GetMaxDate()
{
return (DATE) m_MaxDate;
}
//****************************************************************************************
void CBCGPDateTimeCtrl::SetMaxDate(DATE newValue)
{
COleDateTime dateMax = newValue;
COleDateTime dateEmpty;
if (m_MinDate < dateMax)
{
m_MaxDate = dateMax;
if (m_MaxDate.GetHour () == 0 && m_MaxDate.GetMinute () == 0)
{
m_MaxDate -= COleDateTimeSpan (0, 0, 1, 0); // 1 minute before
}
if (m_Date > m_MaxDate && m_MaxDate != dateEmpty)
{
m_Date = m_MaxDate;
OnDateChanged ();
}
RedrawWindow ();
}
}
//************************************************************************************************
void CBCGPDateTimeCtrl::AdjustControl (CRect rectClient)
{
if (GetSafeHwnd () == NULL) // Control doesn't created yet (e.g., AppStudio)
{
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -