You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
373 lines
9.1 KiB
C++
373 lines
9.1 KiB
C++
// XTPDatePickerList.cpp: implementation of the CXTPDatePickerList class.
|
|
//
|
|
// This file is a part of the XTREME CALENDAR MFC class library.
|
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
|
//
|
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
|
// CONSENT OF CODEJOCK SOFTWARE.
|
|
//
|
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
|
// SINGLE COMPUTER.
|
|
//
|
|
// CONTACT INFORMATION:
|
|
// support@codejock.com
|
|
// http://www.codejock.com
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "Common/XTPDrawHelpers.h"
|
|
#include "Common/XTPColorManager.h"
|
|
|
|
#include "XTPCalendarDefines.h"
|
|
#include "XTPCalendarUtils.h"
|
|
|
|
#include "XTPDatePickerPaintManager.h"
|
|
#include "XTPDatePickerControl.h"
|
|
|
|
#include "XTPDatePickerList.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPDatePickerList
|
|
|
|
CXTPDatePickerList::CXTPDatePickerList(CXTPDatePickerControl* pControl, COleDateTime dtStartMonth)
|
|
: m_pControl(pControl), m_dtStartMonth(dtStartMonth), m_dtSelMonth(dtStartMonth), m_dtMiddleMonth(dtStartMonth)
|
|
{
|
|
m_nItemsAbove = 3;
|
|
m_nItemsBelow = 3;
|
|
|
|
m_rcListControl.SetRectEmpty();
|
|
}
|
|
|
|
CXTPDatePickerList::~CXTPDatePickerList()
|
|
{
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CXTPDatePickerList, CWnd)
|
|
//{{AFX_MSG_MAP(CXTPDatePickerList)
|
|
ON_WM_ERASEBKGND()
|
|
ON_WM_PAINT()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPDatePickerList message handlers
|
|
|
|
BOOL CXTPDatePickerList::OnEraseBkgnd(CDC* /*pDC*/)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void CXTPDatePickerList::OnPaint()
|
|
{
|
|
CPaintDC dcPaint(this); // device context for painting
|
|
|
|
if (!m_pControl)
|
|
return;
|
|
|
|
CXTPClientRect rcClient(this);
|
|
CXTPBufferDC dcMem(dcPaint, rcClient);
|
|
|
|
m_dtSelMonth.SetStatus(COleDateTime::null);
|
|
int nMonth = m_dtMiddleMonth.GetMonth();
|
|
int nYear = m_dtMiddleMonth.GetYear();
|
|
|
|
//if (nYear <= 1601 && nMonth <= 4)
|
|
//{
|
|
// //no shifting
|
|
//}
|
|
//else if (nYear <= 1601 && nMonth <= 5)
|
|
// ShiftMonthDown(nYear, nMonth, m_nItemsAbove - 2);
|
|
//else if (nYear <= 1601 && nMonth <= 6)
|
|
// ShiftMonthDown(nYear, nMonth, m_nItemsAbove - 1);
|
|
//else
|
|
// ShiftMonthDown(nYear, nMonth, m_nItemsAbove);
|
|
|
|
if (nYear <= 100 && nMonth <= 2)
|
|
{
|
|
//no shifting
|
|
}
|
|
else if (nYear <= 100 && nMonth <= 3)
|
|
ShiftMonthDown(nYear, nMonth, m_nItemsAbove - 2);
|
|
else if (nYear <= 100 && nMonth <= 4)
|
|
ShiftMonthDown(nYear, nMonth, m_nItemsAbove - 1);
|
|
else
|
|
ShiftMonthDown(nYear, nMonth, m_nItemsAbove);
|
|
|
|
CXTPDatePickerPaintManager* pPaintManager = m_pControl->GetPaintManager();
|
|
// prepare DC
|
|
CFont* pOldFont = dcMem.SelectObject(pPaintManager->GetListControlTextFont());
|
|
int iPosY = 0;
|
|
|
|
// fill background
|
|
dcMem.FillSolidRect(rcClient, pPaintManager->GetListControlBackColor());
|
|
dcMem.SetTextColor(pPaintManager->GetListControlTextColor());
|
|
dcMem.SetBkMode(TRANSPARENT);
|
|
|
|
CString strDisplayText;
|
|
for (int nItem = 0; nItem < m_nItemsAbove + 1 + m_nItemsBelow; nItem++)
|
|
{
|
|
CRect rcItem;
|
|
|
|
if (!m_pControl->m_strYearMonthFormat.IsEmpty())
|
|
{
|
|
strDisplayText = CXTPCalendarUtils::GetDateFormat(COleDateTime(nYear, nMonth, 1, 0, 0, 0), m_pControl->m_strYearMonthFormat);
|
|
}
|
|
else
|
|
{
|
|
strDisplayText.Format(_T("%s %d"), (LPCTSTR)m_pControl->GetMonthName(nMonth), nYear);
|
|
}
|
|
|
|
CSize szItem = dcMem.GetTextExtent(_T(" "), 1);
|
|
szItem.cy += 3;
|
|
|
|
rcItem.SetRect(0, iPosY, m_rcListControl.Width(), iPosY + szItem.cy);
|
|
|
|
dcMem.DrawText(strDisplayText, rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
|
|
|
|
if (IsSelected(nItem, rcItem))
|
|
{
|
|
dcMem.InvertRect(rcItem);
|
|
m_dtSelMonth.SetDate(nYear, nMonth, 1);
|
|
m_dtSelMonth.SetStatus(COleDateTime::valid);
|
|
}
|
|
|
|
// next month
|
|
ShiftMonthUp(nYear, nMonth, 1);
|
|
|
|
iPosY += szItem.cy;
|
|
}
|
|
|
|
dcMem.SelectObject(pOldFont);
|
|
}
|
|
|
|
void CXTPDatePickerList::OnMouseMove(UINT /*nFlags*/, CPoint /*point*/)
|
|
{
|
|
Invalidate();
|
|
}
|
|
|
|
void CXTPDatePickerList::OnTimer(UINT_PTR /*nIDEvent*/)
|
|
{
|
|
// determine cursor position
|
|
DWORD dwPos = ::GetMessagePos();
|
|
POINTS ptsPos = MAKEPOINTS(dwPos);
|
|
CPoint ptPos;
|
|
ptPos.x = ptsPos.x;
|
|
ptPos.y = ptsPos.y;
|
|
|
|
CRect rcClient;
|
|
GetClientRect(rcClient);
|
|
ClientToScreen(rcClient);
|
|
|
|
if (ptPos.y < rcClient.top)
|
|
{
|
|
int nDiff = rcClient.top - ptPos.y;
|
|
int nScroll = nDiff / rcClient.Height() + 1;
|
|
ScrollUp(nScroll);
|
|
|
|
Invalidate();
|
|
}
|
|
else if (ptPos.y > rcClient.bottom)
|
|
{
|
|
int nDiff = ptPos.y - rcClient.bottom;
|
|
int nScroll = nDiff / rcClient.Height() + 1;
|
|
ScrollDown(nScroll);
|
|
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
BOOL CXTPDatePickerList::IsSelected(int nX, CRect rcItem) const
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
// determine cursor position
|
|
DWORD dwPos = ::GetMessagePos();
|
|
POINTS ptsPos = MAKEPOINTS(dwPos);
|
|
CPoint ptPos;
|
|
ptPos.x = ptsPos.x;
|
|
ptPos.y = ptsPos.y;
|
|
|
|
ScreenToClient(&ptPos);
|
|
|
|
CRect rcClient;
|
|
GetClientRect(rcClient);
|
|
|
|
if (ptPos.x < rcClient.left || ptPos.x > rcClient.right ||
|
|
ptPos.y < rcClient.top || ptPos.y > rcClient.bottom)
|
|
return FALSE;
|
|
|
|
if (ptPos.y < 0 && nX == 0)
|
|
bReturn = TRUE;
|
|
else if (ptPos.y > rcClient.Height() && nX == (m_nItemsBelow + m_nItemsAbove))
|
|
bReturn = TRUE;
|
|
else if (ptPos.y >= rcItem.top && ptPos.y <= rcItem.bottom-1)
|
|
bReturn = TRUE;
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
CSize CXTPDatePickerList::GetListSize() const
|
|
{
|
|
ASSERT(m_pControl);
|
|
if (!m_pControl)
|
|
return 0;
|
|
|
|
CSize szMaxItem(0, 0);
|
|
CClientDC dc(m_pControl);
|
|
|
|
CXTPDatePickerPaintManager* pPaintManager = m_pControl->GetPaintManager();
|
|
|
|
CFont* pOldFont = dc.SelectObject(pPaintManager->GetListControlTextFont());
|
|
|
|
szMaxItem.cy = dc.GetTextExtent(_T(" "), 1).cy + 3;
|
|
|
|
for (int nMonth = 1; nMonth <= 12; nMonth++)
|
|
{
|
|
CString strText;
|
|
|
|
if (m_pControl)
|
|
strText.Format(_T("%s 0000"), (LPCTSTR)m_pControl->GetMonthName(nMonth));
|
|
|
|
int iWidth = dc.GetTextExtent(strText).cx;
|
|
|
|
if (iWidth > szMaxItem.cx)
|
|
szMaxItem.cx = iWidth;
|
|
}
|
|
|
|
dc.SelectObject(pOldFont);
|
|
|
|
// calculate rectangle
|
|
CSize szCalendar(szMaxItem.cx + 20, szMaxItem.cy * (m_nItemsAbove + 1 + m_nItemsBelow) + 2);
|
|
|
|
return szCalendar;
|
|
}
|
|
|
|
void CXTPDatePickerList::ShiftMonthUp(int& nYear, int& nMonth, const int nCount)
|
|
{
|
|
for (int nItem = 0; nItem < nCount; nItem++)
|
|
{
|
|
nMonth++;
|
|
if (nMonth > 12)
|
|
{
|
|
nMonth = 1;
|
|
nYear++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXTPDatePickerList::ShiftMonthDown(int& nYear, int& nMonth, const int nCount)
|
|
{
|
|
for (int nItem = 0; nItem < nCount; nItem++)
|
|
{
|
|
nMonth--;
|
|
if (nMonth < 1)
|
|
{
|
|
nMonth = 12;
|
|
nYear--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXTPDatePickerList::ScrollUp(int nCount)
|
|
{
|
|
int nMonth = m_dtMiddleMonth.GetMonth();
|
|
int nYear = m_dtMiddleMonth.GetYear();
|
|
|
|
ShiftMonthDown(nYear, nMonth, nCount);
|
|
|
|
COleDateTime dtMinRange, dtMaxRange;
|
|
DWORD dwRes = m_pControl->GetRange(&dtMinRange, &dtMaxRange);
|
|
if (dwRes & GDTR_MIN)
|
|
{
|
|
int nTopMonth = nMonth;
|
|
int nTopYear = nYear;
|
|
ShiftMonthDown(nTopYear, nTopMonth, m_nItemsAbove);
|
|
COleDateTime dtTmp(nTopYear, nTopMonth, m_dtMiddleMonth.GetDay(), 0, 0, 0);
|
|
if (dtTmp < dtMinRange)
|
|
{
|
|
nYear = dtMinRange.GetYear();
|
|
nMonth = dtMinRange.GetMonth();
|
|
ShiftMonthUp(nYear, nMonth, m_nItemsAbove);
|
|
}
|
|
}
|
|
|
|
m_dtMiddleMonth.SetDate(nYear, nMonth, 1);
|
|
}
|
|
|
|
void CXTPDatePickerList::ScrollDown(int nCount)
|
|
{
|
|
int nMonth = m_dtMiddleMonth.GetMonth();
|
|
int nYear = m_dtMiddleMonth.GetYear();
|
|
|
|
ShiftMonthUp(nYear, nMonth, nCount);
|
|
|
|
COleDateTime dtMinRange, dtMaxRange;
|
|
DWORD dwRes = m_pControl->GetRange(&dtMinRange, &dtMaxRange);
|
|
if (dwRes & GDTR_MAX)
|
|
{
|
|
int nBottomMonth = nMonth;
|
|
int nBottomYear = nYear;
|
|
ShiftMonthUp(nBottomYear, nBottomMonth, m_nItemsBelow);
|
|
COleDateTime dtTmp(nBottomYear, nBottomMonth, m_dtMiddleMonth.GetDay(), 0, 0, 0);
|
|
if (dtTmp > dtMaxRange)
|
|
{
|
|
nYear = dtMaxRange.GetYear();
|
|
nMonth = dtMaxRange.GetMonth();
|
|
ShiftMonthDown(nYear, nMonth, m_nItemsBelow);
|
|
}
|
|
}
|
|
|
|
m_dtMiddleMonth.SetDate(nYear, nMonth, 1);
|
|
|
|
ScrollUp(0);
|
|
}
|
|
|
|
int CXTPDatePickerList::GetMonthInterval() const
|
|
{
|
|
if (m_dtSelMonth.GetStatus() == COleDateTime::valid)
|
|
{
|
|
return (m_dtSelMonth.GetYear() * 12 + m_dtSelMonth.GetMonth()) -
|
|
(m_dtStartMonth.GetYear() * 12 + m_dtStartMonth.GetMonth());
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOL CXTPDatePickerList::Create(CRect rcList)
|
|
{
|
|
// create list control
|
|
DWORD dwStyle = WS_POPUP | WS_EX_TOPMOST | WS_EX_WINDOWEDGE | WS_BORDER;
|
|
|
|
m_pControl->ClientToScreen(rcList);
|
|
|
|
if (!CreateEx(0, AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
|
|
NULL, dwStyle, rcList, m_pControl, 0, 0))
|
|
return FALSE;
|
|
|
|
CSize szCalendar = GetListSize();
|
|
|
|
m_rcListControl = rcList;
|
|
m_rcListControl.left = m_rcListControl.CenterPoint().x - szCalendar.cx / 2 - 1;
|
|
m_rcListControl.right = m_rcListControl.left + szCalendar.cx;
|
|
m_rcListControl.top = m_rcListControl.CenterPoint().y - szCalendar.cy / 2 + 1;
|
|
m_rcListControl.bottom = m_rcListControl.top + szCalendar.cy;
|
|
|
|
SetWindowPos(NULL, m_rcListControl.left, m_rcListControl.top, m_rcListControl.Width(), m_rcListControl.Height(), SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
|
|
ScrollDown(0);
|
|
RedrawWindow();
|
|
|
|
return TRUE;
|
|
}
|