Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

The Ultimate Toolbox - Updates and User Contributions

, 12 Feb 2013 CPOL
Updates and User Contributions for the Ultimate Toolbox Libraries
OutlookDemoUpdate.zip
Ultimate Grid
Demos
OutlookStyle
OutlookStyle.aps
OutlookStyle.dsp
OutlookStyle.dsw
OutlookStyle.suo
res
bitmap1.bmp
bmattach.bmp
bmp00001.bmp
bmp00002.bmp
bmp00003.bmp
Flags.bmp
OutlookStyle.ico
OutlookStyleDoc.ico
Toolbar.bmp
toolbar1.bmp
toolbar2.bmp
toolbarf.bmp
UltimateGrid72_Src_Update01.zip
CellTypes
Include
Source
UltimateGrid72_Src_Update02.zip
DataSources
ODBC
OleDB
EditControls
UltimateGrid72_Src_Update03.zip
UltimateGrid72_Src_Update04.zip
UltimateGrid73_src.zip
BuildDLL
Build DLL.dsp
Build DLL.dsw
res
BuildLib
ugmfclib.dsp
ugmfclib.dsw
Lib
Skel
UltimateTCP-IP42_Src_Update01.zip
Ultimate TCP-IP
Include
Security
Include
Source
source
UltimateTCP-IP42_Src_Update02.zip
Examples
Client
Mail
icon1.ico
icon2.ico
MailClientS.suo
test.dsp
test.dsw
UltimateTCP-IP42_Src_Update03.zip
ultimatetoolbox93_src_update01.zip
Ultimate Toolbox
include
source
UltimateToolbox93_Src_Update02.zip
lib
Build DLLs
Build Libs
UltimateToolbox93_Src_Update03.zip
UltimateToolbox93_Src_Update04.zip
UltimateToolbox93_Src_Update05.zip
// ==========================================================================
// 					Class Implementation : COXMonthCalCtrl
// ==========================================================================

// Version: 9.3

// This software along with its related components, documentation and files ("The Libraries")
// is � 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement").  Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office.  For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
                          
// //////////////////////////////////////////////////////////////////////////

// OXMonthCalCtrl.cpp : implementation file
//

#include "stdafx.h"
#include <windowsx.h>

// v93 update 03 - 64-bit - moved here from below
#include "UTB64Bit.h"

#include "OXMonthCalCtrl.h"
//#include "UTB64Bit.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// COXMonthCalCtrl


#if _MFC_VER<=0x0421
IMPLEMENT_DYNAMIC(COXMonthCalCtrl, CWnd)

#endif	//	_MFC_VER>0x0421

BOOL COXMonthCalCtrl::bComCtlInitialized=FALSE;

COXMonthCalCtrl::COXMonthCalCtrl()
{
	m_dwMonthCalStyle=0;
}

COXMonthCalCtrl::~COXMonthCalCtrl()
{
	DWORD dwMonthYear;
	LPHOLIDAYS pHolidays;
	POSITION pos=m_arrHolidays.GetStartPosition();
	while(pos!=NULL)
	{
		m_arrHolidays.GetNextAssoc(pos,dwMonthYear,pHolidays);
		ASSERT(pHolidays!=NULL);
		delete pHolidays;
	}

	if(::IsWindow(GetSafeHwnd()))
		DestroyWindow();
}


#if _MFC_VER<=0x0421
BEGIN_MESSAGE_MAP(COXMonthCalCtrl, CWnd)
#else
BEGIN_MESSAGE_MAP(COXMonthCalCtrl, CMonthCalCtrl)
#endif	//	_MFC_VER>0x0421
	//{{AFX_MSG_MAP(COXMonthCalCtrl)
	ON_WM_DESTROY()
	ON_MESSAGE(MCM_GETCURSEL,OnGetCurSel)
	//}}AFX_MSG_MAP
	ON_NOTIFY_REFLECT_EX(MCN_GETDAYSTATE,OnGetDayState)
	ON_NOTIFY_EX(TTN_NEEDTEXTA, 0, OnToolTip)
	ON_NOTIFY_EX(TTN_NEEDTEXTW, 0, OnToolTip)
END_MESSAGE_MAP()


BOOL COXMonthCalCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID,
							 DWORD dwMonthCalStyle/*=OXMCS_BOLDHOLIDAYS|OXMCS_INFOTIP*/)
{
	m_dwMonthCalStyle=dwMonthCalStyle;

	BOOL bRetVal=FALSE;

#if _MFC_VER<=0x0421
	// initialize common controls
	if(!bComCtlInitialized)
	{
		INITCOMMONCONTROLSEX icex;
		icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
		icex.dwICC = ICC_DATE_CLASSES;
		::InitCommonControlsEx(&icex);
		bComCtlInitialized = true;
	}

	CWnd* pWnd = this;
	bRetVal=pWnd->Create(MONTHCAL_CLASS, NULL, dwStyle, rect, pParentWnd, nID);
#else
	bRetVal=CMonthCalCtrl::Create(dwStyle,rect,pParentWnd,nID);
#endif	//_MFC_VER<=0x0421

	if(bRetVal && !InitMonthCalCtrl())
	{
		TRACE(_T("COXMonthCalCtrl::Create: failed to initialize the calendar control"));
		bRetVal=FALSE;
	}

	return bRetVal;
}

BOOL COXMonthCalCtrl::Create(DWORD dwStyle, const POINT& pt, CWnd* pParentWnd, UINT nID, 
							 DWORD dwMonthCalStyle/*=OXMCS_BOLDHOLIDAYS|OXMCS_INFOTIP*/, 
							 int nXDimension/*=1*/, int nYDimension/*=1*/)
{
	ASSERT(nXDimension>=1 && nYDimension>=1);

	if(nXDimension*nYDimension>ID_MAXMONTHCOUNT)
	{
		TRACE(_T("COXMonthCalCtrl::Create: The maximum total number of displayed months is %d\n"),ID_MAXMONTHCOUNT);
		return FALSE;
	}

	BOOL bWasVisible = (dwStyle & WS_VISIBLE);
	dwStyle &= ~WS_VISIBLE;

	CRect rect(pt.x, pt.y, 0, 0);

	BOOL bRetVal = FALSE;
	if(Create(dwStyle, rect, pParentWnd, nID, dwMonthCalStyle))
	{
		if(GetReqRect(rect,nXDimension,nYDimension))
		{
			rect+=pt;
			MoveWindow(rect,FALSE);

			if(bWasVisible)
				ShowWindow(SW_SHOWNA);
		
			// initialize calendar control
			if(!InitMonthCalCtrl())
				TRACE(_T("COXMonthCalCtrl::Create: failed to initialize the calendar control"));
			else
				bRetVal = TRUE;
		}
		else
			DestroyWindow();
	}

	return bRetVal;
}

void COXMonthCalCtrl::PreSubclassWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	
	_AFX_THREAD_STATE* pThreadState=AfxGetThreadState();
	// hook not already in progress
	if(pThreadState->m_pWndInit==NULL)
	{
		if(!InitMonthCalCtrl())
			TRACE(_T("COXMonthCalCtrl::PreSubclassWindow: failed to initialize calendar control"));
	}

#if _MFC_VER<=0x0421
	CWnd::PreSubclassWindow();
#else
	CMonthCalCtrl::PreSubclassWindow();
#endif	//	_MFC_VER<=0x0421
}

void COXMonthCalCtrl::OnDestroy()
{
#if _MFC_VER >= 0x0700
	AFX_MODULE_THREAD_STATE* pThreadState = AfxGetModuleState()->m_thread.GetDataNA();
#else
	_AFX_THREAD_STATE* pThreadState=AfxGetThreadState();
#endif
	CToolTipCtrl* pToolTip=pThreadState->m_pToolTip;

	if(pToolTip && ::IsWindow(pToolTip->GetSafeHwnd()))
	{
		pToolTip->DestroyWindow();
		delete pToolTip;
		pThreadState->m_pToolTip=NULL;
		pToolTip=NULL;
	}

#if _MFC_VER<=0x0421
	CWnd::OnDestroy();
#else
	CMonthCalCtrl::OnDestroy();
#endif	//	_MFC_VER<=0x0421
}

LRESULT COXMonthCalCtrl::OnGetCurSel(WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(wParam);

	LRESULT result=Default();

	if(result!=0)
	{
		SYSTEMTIME* pSysTime=(SYSTEMTIME*)lParam;
		if(pSysTime->wHour>24)
			pSysTime->wHour=0;
		if(pSysTime->wMinute>60)
			pSysTime->wMinute=0;
		if(pSysTime->wSecond>60)
			pSysTime->wSecond=0;
	}

	return result;
}

BOOL COXMonthCalCtrl::InitMonthCalCtrl()
{
	ASSERT(::IsWindow(GetSafeHwnd()));

	// tooltips must be always enabled
	EnableToolTips(m_dwMonthCalStyle&OXMCS_INFOTIP);

	return TRUE;
}



#if _MFC_VER<=0x0421

BOOL COXMonthCalCtrl::SizeMinReq(BOOL bRepaint /* = TRUE */)
{
	CRect rect;
	BOOL bRetVal = FALSE;
	if (GetMinReqRect(rect))
	{
		DWORD dwFlags = SWP_NOZORDER | SWP_NOREPOSITION | SWP_NOMOVE | SWP_NOACTIVATE;
		if (!bRepaint)
			dwFlags |= SWP_NOREDRAW;
		SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), dwFlags);
		bRetVal = TRUE;
	}

	return bRetVal;
}

void COXMonthCalCtrl::SetToday(const COleDateTime& refTime)
{
	ASSERT_VALID(this);

	// make sure the time isn't invalid
	ASSERT(refTime.GetStatus() != COleDateTime::invalid);
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTime;
	LPSYSTEMTIME pSysTime = NULL;
	WPARAM wParam = GDT_NONE;

	// if the passed time is null or out of range,
	// we'll set the control to NULL

	if (GetAsSystemTime(refTime,sysTime))
	{
		pSysTime = &sysTime;
		wParam = GDT_VALID;
	}

	if (::IsWindow(m_hWnd))
		::SendMessage(m_hWnd, MCM_SETTODAY, wParam, (LPARAM) pSysTime);
}

void COXMonthCalCtrl::SetToday(const CTime* pDateTime)
{
	ASSERT(::IsWindow(m_hWnd));
	ASSERT_VALID(this);

	// if the passed time is NULL, we'll set the
	// control to NULL

	WPARAM wParam = GDT_NONE;
	LPSYSTEMTIME pSysTime = NULL;
	SYSTEMTIME sysTime;

	if (pDateTime != NULL && GetAsSystemTime(*pDateTime,sysTime))
	{
		wParam = GDT_VALID;
		pSysTime = &sysTime;
	}

	if (::IsWindow(m_hWnd))
 		::SendMessage(m_hWnd, MCM_SETTODAY, wParam, (LPARAM) pSysTime);
}

BOOL COXMonthCalCtrl::SetCurSel(const COleDateTime& refTime)
{
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTime;
	BOOL bRetVal = FALSE;

	// if the passed time is null or out of range,
	// we'll set the control to NULL

	if (GetAsSystemTime(refTime,sysTime) &&
		refTime.GetStatus() == COleDateTime::valid)
	{
		bRetVal = (BOOL)
			::SendMessage(m_hWnd, MCM_SETCURSEL, 0, (LPARAM) &sysTime);
	}

	return bRetVal;
}

BOOL COXMonthCalCtrl::SetCurSel(const CTime& refTime)
{
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTime;
	BOOL bRetVal = FALSE;

	if (GetAsSystemTime(refTime,sysTime))
	{
		bRetVal = (BOOL)
			::SendMessage(m_hWnd, MCM_SETCURSEL, 0, (LPARAM) &sysTime);
	}

	return bRetVal;
}

BOOL COXMonthCalCtrl::GetCurSel(COleDateTime& refTime) const
{
	ASSERT(::IsWindow(m_hWnd));

	// can't use this method on multiple selection controls
	ASSERT(!(GetStyle() & MCS_MULTISELECT));

	SYSTEMTIME sysTime;
	BOOL bResult = (BOOL)
		::SendMessage(m_hWnd, MCM_GETCURSEL, 0, (LPARAM) &sysTime);

	if (bResult)
		refTime = COleDateTime(sysTime);

	return bResult;
}

BOOL COXMonthCalCtrl::GetToday(COleDateTime& refTime) const
{
	ASSERT(::IsWindow(m_hWnd));

	// can't use this method on multiple selection controls
	ASSERT(!(GetStyle() & MCS_MULTISELECT));

	SYSTEMTIME sysTime;
	BOOL bResult = (BOOL)
		::SendMessage(m_hWnd, MCM_GETTODAY, 0, (LPARAM) &sysTime);

	if (bResult)
		refTime = COleDateTime(sysTime);

	return bResult;
}

BOOL COXMonthCalCtrl::GetCurSel(CTime& refTime) const
{
	ASSERT(::IsWindow(m_hWnd));

	// can't use this method on multiple selection controls
	ASSERT(!(GetStyle() & MCS_MULTISELECT));

	SYSTEMTIME sysTime;
	BOOL bResult = (BOOL)
		::SendMessage(m_hWnd, MCM_GETCURSEL, 0, (LPARAM) &sysTime);

	if (bResult)
		refTime = CTime(sysTime);

	return bResult;
}

BOOL COXMonthCalCtrl::GetToday(CTime& refTime) const
{
	ASSERT(::IsWindow(m_hWnd));

 	// can't use this method on multiple selection controls
	ASSERT(!(GetStyle() & MCS_MULTISELECT));

	SYSTEMTIME sysTime;
	BOOL bResult = (BOOL)
		::SendMessage(m_hWnd, MCM_GETTODAY, 0, (LPARAM) &sysTime);

	if (bResult)
		refTime = CTime(sysTime);

	return bResult;
}

int COXMonthCalCtrl::GetFirstDayOfWeek(BOOL* pbLocal /* = NULL */) const
{
	ASSERT(::IsWindow(m_hWnd));
	DWORD dwResult;
	dwResult = (DWORD) ::SendMessage(m_hWnd, MCM_GETFIRSTDAYOFWEEK, 0, 0);

	// set *pbLocal to reflect if the first day of week
	// matches current locale setting

	if (pbLocal)
		*pbLocal = HIWORD(dwResult);
	return LOWORD(dwResult);
}

BOOL COXMonthCalCtrl::SetFirstDayOfWeek(int iDay, int* lpnOld /* = NULL */)
{
	ASSERT(::IsWindow(m_hWnd));
	DWORD dwResult;
	dwResult = (DWORD) ::SendMessage(m_hWnd, MCM_SETFIRSTDAYOFWEEK, 0, (WPARAM) iDay);

	if (lpnOld != NULL)
		*lpnOld = LOWORD(dwResult);

	return (BOOL) HIWORD(dwResult);
}

BOOL COXMonthCalCtrl::SetDayState(int nMonths, LPMONTHDAYSTATE pStates)
{
	ASSERT(::IsWindow(m_hWnd));
	ASSERT(AfxIsValidAddress(pStates, nMonths * sizeof(MONTHDAYSTATE), FALSE));
	return (BOOL) ::SendMessage(m_hWnd, MCM_SETDAYSTATE, (WPARAM) nMonths, (LPARAM) pStates);
}

BOOL COXMonthCalCtrl::SetRange(const COleDateTime* pMinRange,
	const COleDateTime* pMaxRange)
{
	ASSERT(::IsWindow(m_hWnd));
	ASSERT(pMinRange == NULL || pMinRange->GetStatus() != COleDateTime::invalid);
	ASSERT(pMaxRange == NULL || pMaxRange->GetStatus() != COleDateTime::invalid);

	SYSTEMTIME sysTimes[2];
	WPARAM wFlags = 0;

	if (pMinRange != NULL && pMinRange->GetStatus() != COleDateTime::null)
	{
		if (GetAsSystemTime(*pMinRange,sysTimes[0]))
			wFlags |= GDTR_MIN;
	}

	if (pMaxRange != NULL && pMaxRange->GetStatus() != COleDateTime::null)
	{
		if (GetAsSystemTime(*pMaxRange,sysTimes[1]))
			wFlags |= GDTR_MAX;
	}

	return (BOOL)
		::SendMessage(m_hWnd, MCM_SETRANGE, wFlags, (LPARAM) &sysTimes);
}

BOOL COXMonthCalCtrl::SetRange(const LPSYSTEMTIME pMinRange,
							   const LPSYSTEMTIME pMaxRange)
{
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTimes[2];
	WPARAM wFlags = 0;

	if (pMinRange != NULL)
	{
		memcpy(&sysTimes[0], pMinRange, sizeof(SYSTEMTIME));
		wFlags |= GDTR_MIN;
	}

	if (pMaxRange != NULL)
	{
		memcpy(&sysTimes[1], pMaxRange, sizeof(SYSTEMTIME));
		wFlags |= GDTR_MAX;
	}

	return (BOOL)
		::SendMessage(m_hWnd, MCM_SETRANGE, wFlags, (LPARAM) &sysTimes);
}

DWORD COXMonthCalCtrl::GetRange(COleDateTime* pMinRange,
								COleDateTime* pMaxRange) const
{
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTimes[2];
	memset(sysTimes, 0, sizeof(sysTimes));

	DWORD dwRanges = (DWORD)
		::SendMessage(m_hWnd, MCM_GETRANGE, 0, (LPARAM) &sysTimes);

	if (dwRanges & GDTR_MIN && pMinRange)
		*pMinRange = COleDateTime(sysTimes[0]);

	if (dwRanges & GDTR_MAX && pMaxRange)
		*pMaxRange = COleDateTime(sysTimes[1]);

	return dwRanges;
}

DWORD COXMonthCalCtrl::GetRange(LPSYSTEMTIME pMinRange,
								LPSYSTEMTIME pMaxRange) const
{
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTimes[2];
	memset(sysTimes, 0, sizeof(sysTimes));

	DWORD dwRanges = (DWORD)
		::SendMessage(m_hWnd, MCM_GETRANGE, 0, (LPARAM) &sysTimes);

	if (dwRanges & GDTR_MIN && pMinRange)
		memcpy(pMinRange, &sysTimes[0], sizeof(SYSTEMTIME));

	if (dwRanges & GDTR_MAX && pMaxRange)
		memcpy(pMaxRange, &sysTimes[1], sizeof(SYSTEMTIME));

	return dwRanges;
}

BOOL COXMonthCalCtrl::SetRange(const CTime* pMinRange, const CTime* pMaxRange)
{
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTimes[2];
	WPARAM wFlags = 0;
	if (pMinRange != NULL && GetAsSystemTime(*pMinRange,sysTimes[0]))
		wFlags |= GDTR_MIN;

	if (pMaxRange != NULL && GetAsSystemTime(*pMaxRange,sysTimes[1]))
		wFlags |= GDTR_MAX;

	return (BOOL)
		::SendMessage(m_hWnd, MCM_SETRANGE, wFlags, (LPARAM) &sysTimes);
}

DWORD COXMonthCalCtrl::GetRange(CTime* pMinRange, CTime* pMaxRange) const
{
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTimes[2];
	memset(sysTimes, 0, sizeof(sysTimes));

	DWORD dwRanges = (DWORD)
		::SendMessage(m_hWnd, MCM_GETRANGE, 0, (LPARAM) &sysTimes);

	if (dwRanges & GDTR_MIN && pMinRange)
		*pMinRange = CTime(sysTimes[0]);

	if (dwRanges & GDTR_MAX && pMaxRange)
		*pMaxRange = CTime(sysTimes[1]);

	return dwRanges;
}

int COXMonthCalCtrl::GetMonthRange(COleDateTime& refMinRange,
								   COleDateTime& refMaxRange, 
								   DWORD dwFlags) const
{
	ASSERT(::IsWindow(m_hWnd));
	ASSERT(dwFlags == GMR_DAYSTATE || dwFlags == GMR_VISIBLE);

	SYSTEMTIME sysTimes[2];
	memset(sysTimes, 0, sizeof(sysTimes));
	int nCount = (int) ::SendMessage(m_hWnd, MCM_GETMONTHRANGE,
		(WPARAM) dwFlags, (LPARAM) &sysTimes);

	refMinRange = COleDateTime(sysTimes[0]);
	refMaxRange = COleDateTime(sysTimes[1]);

	return nCount;
}

int COXMonthCalCtrl::GetMonthRange(LPSYSTEMTIME pMinRange,
								   LPSYSTEMTIME pMaxRange, 
								   DWORD dwFlags) const
{
	ASSERT(::IsWindow(m_hWnd));
	ASSERT_POINTER(pMinRange, SYSTEMTIME);
	ASSERT_POINTER(pMaxRange, SYSTEMTIME);

	SYSTEMTIME sysTimes[2];
	
	int nCount = (int) ::SendMessage(m_hWnd, MCM_GETMONTHRANGE,
		(WPARAM) dwFlags, (LPARAM) &sysTimes);

	memcpy(pMinRange, &sysTimes[0], sizeof(SYSTEMTIME));
	memcpy(pMaxRange, &sysTimes[1], sizeof(SYSTEMTIME));

	return nCount;
}

int COXMonthCalCtrl::GetMonthRange(CTime& refMinRange, 
								   CTime& refMaxRange,
								   DWORD dwFlags) const
{
	ASSERT(::IsWindow(m_hWnd));
	ASSERT(dwFlags == GMR_DAYSTATE || dwFlags == GMR_VISIBLE);

	SYSTEMTIME sysTimes[2];
	memset(sysTimes, 0, sizeof(sysTimes));
	int nCount = (int) ::SendMessage(m_hWnd, MCM_GETMONTHRANGE,
		(WPARAM) dwFlags,	(LPARAM) &sysTimes);

	refMinRange = CTime(sysTimes[0]);
	refMaxRange = CTime(sysTimes[1]);

	return nCount;
}

BOOL COXMonthCalCtrl::GetSelRange(LPSYSTEMTIME pMinRange,
								  LPSYSTEMTIME pMaxRange) const
{
	ASSERT(m_hWnd != NULL);
	ASSERT((GetStyle() & MCS_MULTISELECT));

	ASSERT_POINTER(pMinRange, SYSTEMTIME);
	ASSERT_POINTER(pMaxRange, SYSTEMTIME);

	SYSTEMTIME sysTimes[2];
	BOOL bReturn = (BOOL) ::SendMessage(m_hWnd, MCM_GETSELRANGE,
										0, (LPARAM) &sysTimes);

	if (bReturn)
	{
		memcpy(pMinRange, &sysTimes[0], sizeof(SYSTEMTIME));
		memcpy(pMaxRange, &sysTimes[1], sizeof(SYSTEMTIME));
	}

	return bReturn;
}

BOOL COXMonthCalCtrl::SetSelRange(const LPSYSTEMTIME pMinRange,
								  const LPSYSTEMTIME pMaxRange)
{
	ASSERT(m_hWnd != NULL);
	ASSERT((GetStyle() & MCS_MULTISELECT));

	ASSERT_POINTER(pMinRange, SYSTEMTIME);
	ASSERT_POINTER(pMaxRange, SYSTEMTIME);

	SYSTEMTIME sysTimes[2];
	memcpy(&sysTimes[0], pMinRange, sizeof(SYSTEMTIME));
	memcpy(&sysTimes[1], pMaxRange, sizeof(SYSTEMTIME));

	return (BOOL) ::SendMessage(m_hWnd, MCM_SETSELRANGE,
		0, (LPARAM) &sysTimes);
}

BOOL COXMonthCalCtrl::SetSelRange(const COleDateTime& refMinRange,
								  const COleDateTime& refMaxRange)
{
	// control must have multiple select
	ASSERT((GetStyle() & MCS_MULTISELECT));
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTimes[2];
	BOOL bResult = FALSE;

	if (refMinRange.GetStatus() == COleDateTime::valid &&
		refMinRange.GetStatus() == COleDateTime::valid)
	{
		if (GetAsSystemTime(refMinRange,sysTimes[0]) &&
			GetAsSystemTime(refMaxRange,sysTimes[1]))
		{
			bResult = (BOOL)
				::SendMessage(m_hWnd, MCM_SETSELRANGE, 0, (LPARAM)sysTimes);
		}
	}

	return bResult;
}

BOOL COXMonthCalCtrl::GetSelRange(COleDateTime& refMinRange,
								  COleDateTime& refMaxRange) const
{
	// control must have multiple select
	ASSERT((GetStyle() & MCS_MULTISELECT));
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTimes[2];
	memset(sysTimes, 0, sizeof(sysTimes));
	BOOL bResult = (BOOL)
		::SendMessage(m_hWnd, MCM_GETSELRANGE, 0, (LPARAM) &sysTimes);

	if (bResult)
	{
		refMinRange = COleDateTime(sysTimes[0]);
		refMaxRange = COleDateTime(sysTimes[1]);
	}
	return bResult;
}

BOOL COXMonthCalCtrl::SetSelRange(const CTime& refMinRange,
								  const CTime& refMaxRange)
{
	// control must have multiple select
	ASSERT((GetStyle() & MCS_MULTISELECT));
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTimes[2];
	BOOL bResult = FALSE;

	if (GetAsSystemTime(refMinRange,sysTimes[0]) &&
		GetAsSystemTime(refMaxRange,sysTimes[1]))
	{
		bResult = (BOOL)
			::SendMessage(m_hWnd, MCM_SETSELRANGE, 0, (LPARAM)sysTimes);
	}

	return bResult;
}

BOOL COXMonthCalCtrl::GetSelRange(CTime& refMinRange, CTime& refMaxRange) const
{
	// control must have multiple select
	ASSERT((GetStyle() & MCS_MULTISELECT));
	ASSERT(::IsWindow(m_hWnd));

	SYSTEMTIME sysTimes[2];
	memset(sysTimes, 0, sizeof(sysTimes));
	BOOL bResult = (BOOL)
		::SendMessage(m_hWnd, MCM_GETSELRANGE, 0, (LPARAM) &sysTimes);

	if (bResult)
	{
		refMinRange = CTime(sysTimes[0]);
		refMaxRange = CTime(sysTimes[1]);
	}
	return bResult;
}

/////////////////////////////////////////////////////////////////////////////
// DDX_ routines

void AFXAPI DDX_MonthCalCtrl(CDataExchange* pDX, int nIDC,
							 COleDateTime& value)
{
	HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
	COXMonthCalCtrl* pWnd = (COXMonthCalCtrl*) CWnd::FromHandle(hWndCtrl);

	if (pDX->m_bSaveAndValidate)
		pWnd->GetCurSel(value);
	else
		pWnd->SetCurSel(value);
}

void AFXAPI DDX_MonthCalCtrl(CDataExchange* pDX, int nIDC, CTime& value)
{
	HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
	COXMonthCalCtrl* pWnd = (COXMonthCalCtrl*) CWnd::FromHandle(hWndCtrl);

	if (pDX->m_bSaveAndValidate)
		pWnd->GetCurSel(value);
	else
		pWnd->SetCurSel(value);
}

void AFXAPI DDV_MinMaxMonth(CDataExchange* pDX,	CTime& refValue,
							const CTime* pMinRange, const CTime* pMaxRange)
{
	ASSERT(pMinRange == NULL || pMaxRange == NULL || *pMinRange <= *pMaxRange);
	COXMonthCalCtrl* pWnd =
		(COXMonthCalCtrl*) CWnd::FromHandle(pDX->m_hWndLastControl);

	if (!pDX->m_bSaveAndValidate)
	{
		if ( (pMinRange != NULL && *pMinRange > refValue) ||
			  (pMaxRange != NULL && *pMaxRange < refValue))
		{
#ifdef _DEBUG
			int nIDC = GetWindowLongPtr(pDX->m_hWndLastControl, GWL_ID);
			TRACE1("Warning: initial dialog data is out of range in control ID %d.\n", nIDC);
#endif
			return;     // don't stop now
		}
	}

	pWnd->SetRange(pMinRange, pMaxRange);
}

void AFXAPI DDV_MinMaxMonth(CDataExchange* pDX,	COleDateTime& refValue,
							const COleDateTime* pMinRange, 
							const COleDateTime* pMaxRange)
{
	ASSERT(pMinRange == NULL || pMaxRange == NULL || *pMinRange <= *pMaxRange);
	COXMonthCalCtrl* pWnd =
		(COXMonthCalCtrl*) CWnd::FromHandle(pDX->m_hWndLastControl);

	if (!pDX->m_bSaveAndValidate)
	{
		if ( (pMinRange != NULL && *pMinRange > refValue) ||
			  (pMaxRange != NULL && *pMaxRange < refValue))
		{
#ifdef _DEBUG
			int nIDC = GetWindowLongPtr(pDX->m_hWndLastControl, GWL_ID);
			TRACE1("Warning: initial dialog data is out of range in control ID %d.\n", nIDC);
#endif
			return;     // don't stop now
		}
	}

	pWnd->SetRange(pMinRange, pMaxRange);
}

#endif	//	_MFC_VER>0x0421


BOOL COXMonthCalCtrl::SetHolidays(LPHOLIDAYS pHolidays)
{
	ASSERT(::IsWindow(m_hWnd));
	ASSERT(pHolidays!=NULL);
	ASSERT(pHolidays->nMonth==-1 || (pHolidays->nMonth>=1 && pHolidays->nMonth<=12));
	ASSERT(pHolidays->nYear==-1 || (pHolidays->nYear>=100 && pHolidays->nYear<=9999));

	LPHOLIDAYS pNewHolidays=NULL; 

	DWORD dwMonthYear=pHolidays->nMonth+pHolidays->nYear*100;


	if (m_arrHolidays.Lookup (dwMonthYear,pNewHolidays)) 
      { 
      if (pNewHolidays) 
         delete pNewHolidays; 
      } 

	pNewHolidays=new HOLIDAYS; 
	*pNewHolidays=*pHolidays; 

	m_arrHolidays.SetAt(dwMonthYear,pNewHolidays);

	return TRUE;
}

BOOL COXMonthCalCtrl::GetHolidays(LPHOLIDAYS pDestHolidays)
{
	ASSERT(pDestHolidays->nMonth>=1 && pDestHolidays->nMonth<=12);
	ASSERT(pDestHolidays->nYear>=100 && pDestHolidays->nYear<=9999);
	ASSERT(pDestHolidays!=NULL);

	pDestHolidays->arrWeekDays.RemoveAll();
	pDestHolidays->arrMonthDays.RemoveAll();

	DWORD dwMonthYear;
	LPHOLIDAYS pHolidays;
	POSITION pos=m_arrHolidays.GetStartPosition();
	while(pos!=NULL)
	{
		m_arrHolidays.GetNextAssoc(pos,dwMonthYear,pHolidays);

		ASSERT(pHolidays!=NULL);
		ASSERT(pHolidays->nMonth==-1 || (pHolidays->nMonth>=1 && pHolidays->nMonth<=12));
		ASSERT(pHolidays->nYear==-1 || (pHolidays->nYear>=100 && pHolidays->nYear<=9999));

		POSITION posList;
		if((pHolidays->nMonth==-1 && pHolidays->nYear==-1) || 
			(pHolidays->nMonth==-1 && pHolidays->nYear==pDestHolidays->nYear) || 
			(pHolidays->nMonth==pDestHolidays->nMonth && pHolidays->nYear==-1) ||
			(pHolidays->nMonth==pDestHolidays->nMonth && 
			pHolidays->nYear==pDestHolidays->nYear)) 
		{
			posList=pHolidays->arrWeekDays.GetHeadPosition();
			while(posList!=NULL)
			{
				WEEKDAYS weekDay=pHolidays->arrWeekDays.GetNext(posList);
				if(!pDestHolidays->arrWeekDays.Find(weekDay))
					pDestHolidays->arrWeekDays.AddTail(weekDay);
			}

			posList=pHolidays->arrMonthDays.GetHeadPosition();
			while(posList!=NULL)
			{
				MONTHDAYS monthDay=pHolidays->arrMonthDays.GetNext(posList);
				if(!pDestHolidays->arrMonthDays.Find(monthDay))
					pDestHolidays->arrMonthDays.AddTail(monthDay);
			}
		}
	}

	return TRUE;
}

BOOL COXMonthCalCtrl::SetCtrlDimension(int nXDimension, int nYDimension,
									   const CSize& szMargins/*=CSize(0,0)*/)
{
	ASSERT(::IsWindow(m_hWnd));

	if(nXDimension*nYDimension>ID_MAXMONTHCOUNT)
	{
		TRACE(_T("COXMonthCalCtrl::SetCtrlDimension: The maximum total number of displayed months is %d\n"),ID_MAXMONTHCOUNT);
		return FALSE;
	}

	CRect rect;
	GetWindowRect(rect);
	CPoint ptTopLeft=rect.TopLeft();

	CWnd* pWnd=GetParent();
	if(pWnd!=NULL)
	{
		ASSERT(::IsWindow(pWnd->GetSafeHwnd()));
		pWnd->ScreenToClient(&ptTopLeft);
	}

	BOOL bResult=FALSE;
	if(GetReqRect(rect,nXDimension,nYDimension))
	{
		rect.right+=szMargins.cx*2;
		rect.bottom+=szMargins.cy*2;
		CalcWindowRect(rect);
		if(SetWindowPos(NULL,ptTopLeft.x,ptTopLeft.y,rect.Width(),rect.Height(),
			SWP_NOZORDER|SWP_NOACTIVATE))
			bResult=TRUE;
	}

	return bResult;
}

BOOL COXMonthCalCtrl::GetMonthFitCount(CSize& szMonthFit) const
{
	ASSERT(::IsWindow(m_hWnd));

	CRect rectMin;
	if(!GetMinReqRect(rectMin))
		return FALSE;

	CRect rect;
	GetClientRect(rect);

	int nWidth=rect.Width();
	int nWidthMin=rectMin.Width();
	int nHorzFit=nWidth/nWidthMin;
	if(nHorzFit!=0)
	{
		nWidth-=ID_MCHORZGAP*(nHorzFit-1);
		nHorzFit=nWidth/nWidthMin;
	}
	nHorzFit=(nHorzFit>1 ? nHorzFit : 1);


	int nHeight=rect.Height();
	int nHeightMin=rectMin.Height();
	int nVertFit=nHeight/nHeightMin;
	if(nVertFit!=0)
	{
		CFont* pFont=GetFont();
		ASSERT(pFont!=NULL);
		LOGFONT lf;
		VERIFY(pFont->GetLogFont(&lf));
		nHeight+=abs(lf.lfHeight)*(nVertFit);

		nVertFit=nHeight/nHeightMin;
	}
	nVertFit=(nVertFit>1 ? nVertFit : 1);

	if(nHorzFit>ID_MAXMONTHCOUNT)
	{
		nHorzFit=ID_MAXMONTHCOUNT;
		nVertFit=1;
	}
	else if(nHorzFit*nVertFit>ID_MAXMONTHCOUNT)
		nVertFit=ID_MAXMONTHCOUNT/nHorzFit;

	
	szMonthFit.cx=nHorzFit;
	szMonthFit.cy=nVertFit;

	return TRUE;
}

BOOL COXMonthCalCtrl::GetReqRect(RECT* pRect, int nXDimension, int nYDimension) const
{
	COXMonthCalCtrl ctlDummy;
	if(ctlDummy.Create((GetStyle()&~(MCS_NOTODAY|WS_POPUP)),
		CRect(0,0,0,0),(CWnd*)this,100) && ctlDummy.GetMinReqRect(pRect))
	{
		pRect->right*=nXDimension;
		pRect->right+=ID_MCHORZGAP*(nXDimension-1);
		pRect->bottom*=nYDimension;

		CFont* pFont=GetFont();
		ASSERT(pFont!=NULL);
		LOGFONT lf;
		VERIFY(pFont->GetLogFont(&lf));
		pRect->bottom-=abs(lf.lfHeight)*(nYDimension-1);

		CWnd* pWnd=(CWnd*)this;
		pWnd->CalcWindowRect(pRect);
		pRect->right-=pRect->left;
		pRect->bottom-=pRect->top;
		pRect->left=0;
		pRect->top=0;

		return TRUE;
	}
	else
		return FALSE;
}

BOOL COXMonthCalCtrl::OnGetDayState(NMHDR *pHdr, LRESULT *pRes)
{
	NMDAYSTATE *pds=(NMDAYSTATE*)pHdr;

	COleDateTime dtMin,dtMax;
	GetMonthRange(dtMin,dtMax,GMR_DAYSTATE);
	int nMonth=dtMin.GetMonth();
	int nYear=dtMin.GetYear();
	for(int nIndex=0; nIndex<pds->cDayState; nIndex++)
	{
		HOLIDAYS holidays;
		holidays.nMonth=nMonth;
		holidays.nYear=nYear;
		VERIFY(GetHolidays(&holidays));

		OXNMDAYSTATE nmds;
		nmds.nmhdr.code=OXMCN_GETDAYSTATE;
		nmds.nMonth=holidays.nMonth;
		nmds.nYear=holidays.nYear;
		nmds.parrDayState=new ARRMONTHDAYS;

		if((GetMonthCalStyle()&OXMCS_BOLDHOLIDAYS)!=0)
		{
			POSITION posList=holidays.arrWeekDays.GetHeadPosition();
			while(posList!=NULL)
			{
				WEEKDAYS weekDay=holidays.arrWeekDays.GetNext(posList);
				COleDateTime dtDummy;
				for(int nDay=1; nDay<=31; nDay++)
				{
					dtDummy.SetDate(nmds.nYear,nmds.nMonth,nDay);
					if(dtDummy.GetDayOfWeek()==GetAsCOleDateTimeDayOfWeek(weekDay) &&
						!nmds.parrDayState->Find((MONTHDAYS)nDay))
						nmds.parrDayState->AddTail((MONTHDAYS)nDay);
				}
			}

			posList=holidays.arrMonthDays.GetHeadPosition();
			while(posList!=NULL)
			{
				MONTHDAYS monthDay=holidays.arrMonthDays.GetNext(posList);
				if(!nmds.parrDayState->Find(monthDay))
					nmds.parrDayState->AddTail(monthDay);
			}
		}

		// notify parent
		CWnd* pParentWnd=GetParent();
		if(pParentWnd)
		{
			// fill notification structure
			nmds.nmhdr.hwndFrom=GetSafeHwnd();
			nmds.nmhdr.idFrom=GetDlgCtrlID();

			pParentWnd->SendMessage(WM_NOTIFY,(WPARAM)GetDlgCtrlID(),(LPARAM)&nmds);
		}

		pds->prgDayState[nIndex]=0;
		POSITION posList=nmds.parrDayState->GetHeadPosition();
		while(posList!=NULL)
		{
			MONTHDAYS monthDay=nmds.parrDayState->GetNext(posList);
			BOLDDAY(pds->prgDayState[nIndex],monthDay);
		}

		nMonth++;
		if(nMonth>ID_MAXMONTHCOUNT)
		{
			nMonth=1;
			nYear++;
		}

	}

	*pRes=0;

	return FALSE;
}
// v9.3 - update 03 - 64-bit - using OXINTRET instead of int here - see UTB64Bit.h
OXINTRET COXMonthCalCtrl::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
	ASSERT_VALID(this);
	ASSERT(::IsWindow(GetSafeHwnd()));

	// the control should be designated to provide tooltips
	if((GetMonthCalStyle()&OXMCS_INFOTIP)==0)
		return -1;

	pTI->hwnd=GetSafeHwnd();

	GetClientRect(&pTI->rect);

	MCHITTESTINFO mcHitTest;
	::ZeroMemory((void*)&mcHitTest,sizeof(mcHitTest));
	mcHitTest.cbSize=sizeof(mcHitTest);
	mcHitTest.pt=point;
///	HitTest(&mcHitTest);
	::SendMessage(GetSafeHwnd(),MCM_HITTEST,0,(LPARAM)&mcHitTest);

	pTI->uId=mcHitTest.uHit;

	pTI->uFlags&=~(TTF_IDISHWND);

	// set text to LPSTR_TEXTCALLBACK in order to get TTN_NEEDTEXT message when 
	// it's time to display tool tip
	pTI->lpszText=LPSTR_TEXTCALLBACK;

	return PtrToInt(pTI->uId);
}

BOOL COXMonthCalCtrl::OnToolTip(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
{   
	UNREFERENCED_PARAMETER(id);

	ASSERT(pNMHDR->code==TTN_NEEDTEXTA || pNMHDR->code==TTN_NEEDTEXTW);

	DWORD dwMessagePos=::GetMessagePos();
	CPoint point(GET_X_LPARAM(dwMessagePos),GET_Y_LPARAM(dwMessagePos));
	ScreenToClient(&point);
	// now hit test against COXMonthCalCtrl elements
	MCHITTESTINFO mcHitTest;
	::ZeroMemory((void*)&mcHitTest,sizeof(mcHitTest));
	mcHitTest.cbSize=sizeof(mcHitTest);
	mcHitTest.pt=point;
	HitTest(&mcHitTest);

	ASSERT(pNMHDR->idFrom==mcHitTest.uHit);

	// need to handle both ANSI and UNICODE versions of the message
	TOOLTIPTEXTA* pTTTA=(TOOLTIPTEXTA*)pNMHDR;
	TOOLTIPTEXTW* pTTTW=(TOOLTIPTEXTW*)pNMHDR;
    
	// idFrom must be the handle to the group
	if (pNMHDR->code==TTN_NEEDTEXTA)
		ASSERT((pTTTA->uFlags&TTF_IDISHWND)==0);
	else
		ASSERT((pTTTW->uFlags&TTF_IDISHWND)==0);

	OXNMMCINFOTIP infoTip;
	// fill structure for notification
	infoTip.nmhdr.code=OXMCN_GETINFOTIP;
	infoTip.pMCHitTest=&mcHitTest;

	// notify parent
	CWnd* pParentWnd=GetParent();
	if(pParentWnd)
	{
		// fill notification structure
		infoTip.nmhdr.hwndFrom=GetSafeHwnd();
		infoTip.nmhdr.idFrom=GetDlgCtrlID();

		pParentWnd->SendMessage(WM_NOTIFY,(WPARAM)GetDlgCtrlID(),(LPARAM)&infoTip);
	}

#ifndef _UNICODE
	if(pNMHDR->code==TTN_NEEDTEXTA)
		lstrcpyn(pTTTA->szText,infoTip.szText,countof(pTTTA->szText));
	else
		_mbstowcsz(pTTTW->szText,infoTip.szText,countof(pTTTW->szText));
#else
	if (pNMHDR->code==TTN_NEEDTEXTA)
		_wcstombsz(pTTTA->szText,infoTip.szText,countof(pTTTA->szText));
	else
		lstrcpyn(pTTTW->szText,infoTip.szText,countof(pTTTW->szText));
#endif

	if(pNMHDR->code==TTN_NEEDTEXTA)
	{
		if(infoTip.lpszText==NULL)
			pTTTA->lpszText=pTTTA->szText;
		else
			pTTTA->lpszText=(LPSTR)infoTip.lpszText;
		pTTTA->hinst=infoTip.hinst;
	}
	else
	{
		if(infoTip.lpszText==NULL)
			pTTTW->lpszText=pTTTW->szText;
		else
			pTTTW->lpszText=(LPWSTR)infoTip.lpszText;
		pTTTW->hinst=infoTip.hinst;
	}

	*pResult=0;

	return TRUE;    // message was handled
}

/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////

#if _MFC_VER<=0x0421

BOOL COXMonthCalCtrl::GetAsSystemTime(const COleDateTime& rDateTime, SYSTEMTIME& sysTime)
{
	BOOL bRetVal = FALSE;
	if(rDateTime.GetStatus() == COleDateTime::valid)
	{
		struct tm tmTemp;
		if (TimeFromOleDate(rDateTime.m_dt, tmTemp))
		{
			sysTime.wYear = (WORD) tmTemp.tm_year;
			sysTime.wMonth = (WORD) tmTemp.tm_mon;
			sysTime.wDayOfWeek = (WORD) tmTemp.tm_wday;
			sysTime.wDay = (WORD) tmTemp.tm_mday;
			sysTime.wHour = (WORD) tmTemp.tm_hour;
			sysTime.wMinute = (WORD) tmTemp.tm_min;
			sysTime.wSecond = (WORD) tmTemp.tm_sec;
			sysTime.wMilliseconds = 0;

			bRetVal = TRUE;
		}
	}

	return bRetVal;
}

BOOL COXMonthCalCtrl::GetAsSystemTime(const CTime& rTime, SYSTEMTIME& timeDest)
{
	struct tm* ptm = rTime.GetLocalTm(NULL);
	if (ptm == NULL)
		return FALSE;

	timeDest.wYear = (WORD) (1900 + ptm->tm_year);
	timeDest.wMonth = (WORD) (1 + ptm->tm_mon);
	timeDest.wDay = (WORD) ptm->tm_mday;
	timeDest.wHour = (WORD) ptm->tm_hour;
	timeDest.wMinute = (WORD) ptm->tm_min;
	timeDest.wSecond = (WORD) ptm->tm_sec;
	timeDest.wMilliseconds = 0;

	return TRUE;
}


BOOL COXMonthCalCtrl::TimeFromOleDate(DATE dtSrc, struct tm& tmDest)
{
	// The legal range does not actually span year 0 to 9999.
	if (dtSrc > MAX_DATE || dtSrc < MIN_DATE) // about year 100 to about 9999
		return FALSE;

	long nDays;             // Number of days since Dec. 30, 1899
	long nDaysAbsolute;     // Number of days since 1/1/0
	long nSecsInDay;        // Time in seconds since midnight
	long nMinutesInDay;     // Minutes in day

	long n400Years;         // Number of 400 year increments since 1/1/0
	long n400Century;       // Century within 400 year block (0,1,2 or 3)
	long n4Years;           // Number of 4 year increments since 1/1/0
	long n4Day;             // Day within 4 year block
							//  (0 is 1/1/yr1, 1460 is 12/31/yr4)
	long n4Yr;              // Year within 4 year block (0,1,2 or 3)
	BOOL bLeap4 = TRUE;     // TRUE if 4 year block includes leap year

	double dblDate = dtSrc; // tempory serial date

	// If a valid date, then this conversion should not overflow
	nDays = (long)dblDate;

	// Round to the second
	dblDate += ((dtSrc > 0.0) ? HALF_SECOND : -HALF_SECOND);

	nDaysAbsolute = (long)dblDate + 693959L; // Add days from 1/1/0 to 12/30/1899

	dblDate = fabs(dblDate);
	nSecsInDay = (long)((dblDate - floor(dblDate)) * 86400.);

	// Calculate the day of week (sun=1, mon=2...)
	//   -1 because 1/1/0 is Sat.  +1 because we want 1-based
	tmDest.tm_wday = (int)((nDaysAbsolute - 1) % 7L) + 1;

	// Leap years every 4 yrs except centuries not multiples of 400.
	n400Years = (long)(nDaysAbsolute / 146097L);

	// Set nDaysAbsolute to day within 400-year block
	nDaysAbsolute %= 146097L;

	// -1 because first century has extra day
	n400Century = (long)((nDaysAbsolute - 1) / 36524L);

	// Non-leap century
	if (n400Century != 0)
	{
		// Set nDaysAbsolute to day within century
		nDaysAbsolute = (nDaysAbsolute - 1) % 36524L;

		// +1 because 1st 4 year increment has 1460 days
		n4Years = (long)((nDaysAbsolute + 1) / 1461L);

		if (n4Years != 0)
			n4Day = (long)((nDaysAbsolute + 1) % 1461L);
		else
		{
			bLeap4 = FALSE;
			n4Day = (long)nDaysAbsolute;
		}
	}
	else
	{
		// Leap century - not special case!
		n4Years = (long)(nDaysAbsolute / 1461L);
		n4Day = (long)(nDaysAbsolute % 1461L);
	}

	if (bLeap4)
	{
		// -1 because first year has 366 days
		n4Yr = (n4Day - 1) / 365;

		if (n4Yr != 0)
			n4Day = (n4Day - 1) % 365;
	}
	else
	{
		n4Yr = n4Day / 365;
		n4Day %= 365;
	}

	// n4Day is now 0-based day of year. Save 1-based day of year, year number
	tmDest.tm_yday = (int)n4Day + 1;
	tmDest.tm_year = n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr;

	// Handle leap year: before, on, and after Feb. 29.
	if (n4Yr == 0 && bLeap4)
	{
		// Leap Year
		if (n4Day == 59)
		{
			/* Feb. 29 */
			tmDest.tm_mon = 2;
			tmDest.tm_mday = 29;
			goto DoTime;
		}

		// Pretend it's not a leap year for month/day comp.
		if (n4Day >= 60)
			--n4Day;
	}

	// Make n4DaY a 1-based day of non-leap year and compute
	//  month/day for everything but Feb. 29.
	++n4Day;

	// Month number always >= n/32, so save some loop time */
	for (tmDest.tm_mon = (n4Day >> 5) + 1;
		n4Day > arrMonthStartDay[tmDest.tm_mon]; tmDest.tm_mon++);

	tmDest.tm_mday = (int)(n4Day - arrMonthStartDay[tmDest.tm_mon-1]);

DoTime:
	if (nSecsInDay == 0)
		tmDest.tm_hour = tmDest.tm_min = tmDest.tm_sec = 0;
	else
	{
		tmDest.tm_sec = (int)nSecsInDay % 60L;
		nMinutesInDay = nSecsInDay / 60L;
		tmDest.tm_min = (int)nMinutesInDay % 60;
		tmDest.tm_hour = (int)nMinutesInDay / 60;
	}

	return TRUE;
}

#endif	//	_MFC_VER<=0x0421


int COXMonthCalCtrl::GetAsCOleDateTimeDayOfWeek(const WEEKDAYS weekDay)
{
	switch(weekDay)
	{
	case MONDAY:
		return 2;
	case TUESDAY:
		return 3;
	case WENDSDAY:
		return 4;
	case THURSDAY:
		return 5;
	case FRIDAY:
		return 6;
	case SATURDAY:
		return 7;
	case SUNDAY:
		return 1;
	default:
		return -1;
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

The Ultimate Toolbox
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.
 
Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
Group type: Organisation

394 members


| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 13 Feb 2013
Article Copyright 2008 by The Ultimate Toolbox
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid