484 lines
24 KiB
C++
484 lines
24 KiB
C++
// ==========================================================================
|
||
// Class Implementation : COXDateTimeCtrl
|
||
// ==========================================================================
|
||
|
||
// 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.
|
||
|
||
// Version: 9.3
|
||
|
||
// //////////////////////////////////////////////////////////////////////////
|
||
|
||
// OXDateTimeCtrl.cpp : implementation file
|
||
//
|
||
|
||
#include "stdafx.h"
|
||
|
||
// v93 update 03 - 64-bit
|
||
#include "UTB64Bit.h"
|
||
|
||
#include "OXDateTimeCtrl.h"
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#undef THIS_FILE
|
||
static char THIS_FILE[] = __FILE__;
|
||
#endif
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// COXDateTimeCtrl
|
||
|
||
//#if _MFC_VER<=0x0421
|
||
IMPLEMENT_DYNCREATE(COXDateTimeCtrl, CWnd)
|
||
//#endif // _MFC_VER>0x0421
|
||
|
||
BOOL COXDateTimeCtrl::bComCtlInitialized=FALSE;
|
||
|
||
COXDateTimeCtrl::COXDateTimeCtrl()
|
||
{
|
||
}
|
||
|
||
COXDateTimeCtrl::~COXDateTimeCtrl()
|
||
{
|
||
if(::IsWindow(GetSafeHwnd()))
|
||
DestroyWindow();
|
||
}
|
||
|
||
void COXDateTimeCtrl::InitializeDTPCtrl()
|
||
{
|
||
INITCOMMONCONTROLSEX icex;
|
||
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
||
icex.dwICC = ICC_DATE_CLASSES;
|
||
::InitCommonControlsEx(&icex);
|
||
}
|
||
|
||
|
||
#if _MFC_VER<=0x0421
|
||
BEGIN_MESSAGE_MAP(COXDateTimeCtrl, CWnd)
|
||
#else
|
||
BEGIN_MESSAGE_MAP(COXDateTimeCtrl, CDateTimeCtrl)
|
||
#endif // _MFC_VER>0x0421
|
||
//{{AFX_MSG_MAP(COXDateTimeCtrl)
|
||
ON_NOTIFY_REFLECT_EX(DTN_DROPDOWN, OnDropDown)
|
||
//}}AFX_MSG_MAP
|
||
END_MESSAGE_MAP()
|
||
|
||
|
||
BOOL COXDateTimeCtrl::Create(DWORD dwStyle, const RECT& rect,
|
||
CWnd* pParentWnd, UINT nID)
|
||
{
|
||
BOOL bRetVal=FALSE;
|
||
|
||
#if _MFC_VER<=0x0421
|
||
// initialize common controls
|
||
if(!bComCtlInitialized)
|
||
{
|
||
InitializeDTPCtrl();
|
||
bComCtlInitialized = true;
|
||
}
|
||
|
||
CWnd* pWnd = this;
|
||
bRetVal=pWnd->Create(DATETIMEPICK_CLASS, NULL, dwStyle, rect, pParentWnd, nID);
|
||
#else
|
||
bRetVal=CDateTimeCtrl::Create(dwStyle,rect,pParentWnd,nID);
|
||
#endif //_MFC_VER<=0x0421
|
||
|
||
if(bRetVal && !InitDateTimeCtrl())
|
||
{
|
||
TRACE(_T("COXDateTimeCtrl::Create: failed to initialize the date time control"));
|
||
bRetVal=FALSE;
|
||
}
|
||
|
||
return bRetVal;
|
||
}
|
||
|
||
void COXDateTimeCtrl::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)
|
||
{
|
||
DWORD dwStyle=GetStyle();
|
||
// check if subclassed window has WS_CHILD style
|
||
VERIFY((dwStyle&WS_CHILD)!=0);
|
||
|
||
BOOL bRecreate=FALSE;
|
||
TCHAR buffer[254];
|
||
if(::GetClassName(GetSafeHwnd(),buffer,254)>0)
|
||
{
|
||
CString sClassName=buffer;
|
||
bRecreate=(sClassName!=_T("SysDateTimePick32"));
|
||
}
|
||
|
||
if(bRecreate)
|
||
{
|
||
int nCtrlID=GetDlgCtrlID();
|
||
CWnd* pWndParent=GetParent();
|
||
ASSERT(pWndParent!=NULL);
|
||
CRect rcWnd;
|
||
GetWindowRect(rcWnd);
|
||
HWND hSubclassedWnd=Detach();
|
||
::DestroyWindow(hSubclassedWnd);
|
||
pWndParent->ScreenToClient(rcWnd);
|
||
VERIFY(Create(WS_TABSTOP|WS_CHILD|
|
||
((dwStyle&WS_VISIBLE)!=0 ? WS_VISIBLE : 0),
|
||
rcWnd,pWndParent,nCtrlID));
|
||
}
|
||
|
||
if(!InitDateTimeCtrl())
|
||
TRACE(_T("COXDateTimeCtrl::PreSubclassWindow: failed to initialize date time control"));
|
||
}
|
||
|
||
#if _MFC_VER<=0x0421
|
||
CWnd::PreSubclassWindow();
|
||
#else
|
||
CDateTimeCtrl::PreSubclassWindow();
|
||
#endif // _MFC_VER<=0x0421
|
||
}
|
||
|
||
BOOL COXDateTimeCtrl::InitDateTimeCtrl()
|
||
{
|
||
ASSERT(::IsWindow(GetSafeHwnd()));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
DWORD COXDateTimeCtrl::GetRange(LPSYSTEMTIME pMinRange,
|
||
LPSYSTEMTIME pMaxRange) const
|
||
{
|
||
ASSERT(::IsWindow(m_hWnd));
|
||
|
||
SYSTEMTIME sysTimes[2];
|
||
memset(sysTimes, 0, sizeof(sysTimes));
|
||
|
||
DWORD dwResult = (DWORD)
|
||
::SendMessage(m_hWnd, DTM_GETRANGE, 0, (LPARAM) &sysTimes);
|
||
|
||
if (dwResult & GDTR_MIN && pMinRange)
|
||
memcpy(pMinRange, &sysTimes[0], sizeof(SYSTEMTIME));
|
||
|
||
if (dwResult & GDTR_MAX && pMaxRange)
|
||
memcpy(pMaxRange, &sysTimes[1], sizeof(SYSTEMTIME));
|
||
|
||
return dwResult;
|
||
}
|
||
|
||
BOOL COXDateTimeCtrl::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, DTM_SETRANGE, wFlags, (LPARAM) &sysTimes);
|
||
}
|
||
|
||
|
||
|
||
#if _MFC_VER<=0x0421
|
||
|
||
BOOL COXDateTimeCtrl::SetTime(LPSYSTEMTIME pTimeNew /* = NULL */)
|
||
{
|
||
ASSERT(::IsWindow(m_hWnd));
|
||
WPARAM wParam = (pTimeNew == NULL) ? GDT_NONE : GDT_VALID;
|
||
return (BOOL) ::SendMessage(m_hWnd, DTM_SETSYSTEMTIME,
|
||
wParam, (LPARAM) pTimeNew);
|
||
}
|
||
|
||
BOOL COXDateTimeCtrl::SetTime(const COleDateTime& timeNew)
|
||
{
|
||
BOOL bRetVal = FALSE;
|
||
|
||
// make sure the time isn't invalid
|
||
ASSERT(timeNew.GetStatus() != COleDateTime::invalid);
|
||
ASSERT(::IsWindow(m_hWnd));
|
||
|
||
SYSTEMTIME sysTime;
|
||
WPARAM wParam = GDT_NONE;
|
||
if (timeNew.GetStatus() == COleDateTime::valid &&
|
||
COXMonthCalCtrl::GetAsSystemTime(timeNew,sysTime))
|
||
{
|
||
wParam = GDT_VALID;
|
||
}
|
||
|
||
bRetVal = (BOOL) ::SendMessage(m_hWnd,
|
||
DTM_SETSYSTEMTIME, wParam, (LPARAM) &sysTime);
|
||
|
||
return bRetVal;
|
||
}
|
||
|
||
BOOL COXDateTimeCtrl::SetTime(const CTime* pTimeNew)
|
||
{
|
||
BOOL bRetVal = FALSE;
|
||
|
||
// make sure the time isn't invalid
|
||
ASSERT(::IsWindow(m_hWnd));
|
||
|
||
SYSTEMTIME sysTime;
|
||
WPARAM wParam = GDT_NONE;
|
||
if (pTimeNew != NULL && COXMonthCalCtrl::GetAsSystemTime(*pTimeNew,sysTime))
|
||
{
|
||
wParam = GDT_VALID;
|
||
}
|
||
|
||
bRetVal = (BOOL) ::SendMessage(m_hWnd,
|
||
DTM_SETSYSTEMTIME, wParam, (LPARAM) &sysTime);
|
||
|
||
return bRetVal;
|
||
}
|
||
|
||
BOOL COXDateTimeCtrl::GetTime(COleDateTime& timeDest) const
|
||
{
|
||
SYSTEMTIME sysTime;
|
||
BOOL bRetVal = TRUE;
|
||
|
||
LRESULT result = ::SendMessage(m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM) &sysTime);
|
||
if (result == GDT_VALID)
|
||
{
|
||
timeDest = COleDateTime(sysTime);
|
||
bRetVal = TRUE;
|
||
ASSERT(timeDest.GetStatus() == COleDateTime::valid);
|
||
}
|
||
else if (result == GDT_NONE)
|
||
{
|
||
timeDest.SetStatus(COleDateTime::null);
|
||
bRetVal = TRUE;
|
||
}
|
||
else
|
||
timeDest.SetStatus(COleDateTime::invalid);
|
||
return bRetVal;
|
||
}
|
||
|
||
DWORD COXDateTimeCtrl::GetTime(CTime& timeDest) const
|
||
{
|
||
SYSTEMTIME sysTime;
|
||
DWORD dwResult = (DWORD)
|
||
::SendMessage(m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM) &sysTime);
|
||
|
||
if (dwResult == GDT_VALID)
|
||
timeDest = CTime(sysTime);
|
||
|
||
return dwResult;
|
||
}
|
||
|
||
#endif // _MFC_VER>0x0421
|
||
|
||
|
||
DWORD COXDateTimeCtrl::GetRange(CTime* pMinTime, CTime* pMaxTime) const
|
||
{
|
||
#if _MFC_VER<=0x0421
|
||
ASSERT(::IsWindow(m_hWnd));
|
||
SYSTEMTIME sysTimes[2];
|
||
memset(sysTimes, 0, sizeof(sysTimes));
|
||
|
||
DWORD dwResult = ::SendMessage(m_hWnd, DTM_GETRANGE, 0, (LPARAM) &sysTimes);
|
||
|
||
if (pMinTime != NULL)
|
||
{
|
||
if (dwResult & GDTR_MIN)
|
||
*pMinTime = CTime(sysTimes[0]);
|
||
}
|
||
|
||
if (pMaxTime != NULL)
|
||
{
|
||
if (dwResult & GDTR_MAX)
|
||
*pMaxTime = CTime(sysTimes[1]);
|
||
}
|
||
|
||
return dwResult;
|
||
#else
|
||
return CDateTimeCtrl::GetRange(pMinTime,pMaxTime);
|
||
#endif // _MFC_VER>0x0421
|
||
}
|
||
|
||
DWORD COXDateTimeCtrl::GetRange(COleDateTime* pMinTime,
|
||
COleDateTime* pMaxTime) const
|
||
{
|
||
#if _MFC_VER<=0x0421
|
||
ASSERT(::IsWindow(m_hWnd));
|
||
|
||
SYSTEMTIME sysTimes[2];
|
||
memset(sysTimes, 0, sizeof(sysTimes));
|
||
|
||
DWORD dwResult = ::SendMessage(m_hWnd, DTM_GETRANGE, 0, (LPARAM) &sysTimes);
|
||
if (pMinTime != NULL)
|
||
{
|
||
if (dwResult & GDTR_MIN)
|
||
*pMinTime = COleDateTime(sysTimes[0]);
|
||
else
|
||
pMinTime->SetStatus(COleDateTime::null);
|
||
}
|
||
|
||
if (pMaxTime != NULL)
|
||
{
|
||
if (dwResult & GDTR_MAX)
|
||
*pMaxTime = COleDateTime(sysTimes[1]);
|
||
else
|
||
pMaxTime->SetStatus(COleDateTime::null);
|
||
}
|
||
|
||
return dwResult;
|
||
#else
|
||
return CDateTimeCtrl::GetRange(pMinTime,pMaxTime);
|
||
#endif // _MFC_VER>0x0421
|
||
}
|
||
|
||
BOOL COXDateTimeCtrl::SetRange(const CTime* pMinTime, const CTime* pMaxTime)
|
||
{
|
||
#if _MFC_VER<=0x0421
|
||
ASSERT(::IsWindow(m_hWnd));
|
||
|
||
SYSTEMTIME sysTimes[2];
|
||
|
||
WPARAM wFlags = 0;
|
||
if (pMinTime != NULL && COXMonthCalCtrl::GetAsSystemTime(*pMinTime,sysTimes[0]))
|
||
wFlags |= GDTR_MIN;
|
||
|
||
if (pMaxTime != NULL && COXMonthCalCtrl::GetAsSystemTime(*pMaxTime,sysTimes[1]))
|
||
wFlags |= GDTR_MAX;
|
||
|
||
return (BOOL)::SendMessage(m_hWnd, DTM_SETRANGE, wFlags, (LPARAM) &sysTimes);
|
||
#else
|
||
return CDateTimeCtrl::SetRange(pMinTime,pMaxTime);
|
||
#endif // _MFC_VER>0x0421
|
||
}
|
||
|
||
BOOL COXDateTimeCtrl::SetRange(const COleDateTime* pMinTime,
|
||
const COleDateTime* pMaxTime)
|
||
{
|
||
#if _MFC_VER<=0x0421
|
||
ASSERT(::IsWindow(m_hWnd));
|
||
ASSERT(pMinTime == NULL || pMinTime->GetStatus() != COleDateTime::invalid);
|
||
ASSERT(pMaxTime == NULL || pMaxTime->GetStatus() != COleDateTime::invalid);
|
||
|
||
SYSTEMTIME sysTime[2];
|
||
|
||
WPARAM wFlags = 0;
|
||
if (pMinTime != NULL && pMinTime->GetStatus() != COleDateTime::null)
|
||
{
|
||
if (COXMonthCalCtrl::GetAsSystemTime(*pMinTime,sysTime[0]))
|
||
wFlags |= GDTR_MIN;
|
||
}
|
||
|
||
if (pMaxTime != NULL && pMaxTime->GetStatus() != COleDateTime::null)
|
||
{
|
||
if (COXMonthCalCtrl::GetAsSystemTime(*pMaxTime,sysTime[1]))
|
||
wFlags |= GDTR_MAX;
|
||
}
|
||
|
||
return (BOOL) ::SendMessage(m_hWnd, DTM_SETRANGE, wFlags, (LPARAM) &sysTime);
|
||
#else
|
||
return CDateTimeCtrl::SetRange(pMinTime,pMaxTime);
|
||
#endif // _MFC_VER>0x0421
|
||
}
|
||
|
||
BOOL COXDateTimeCtrl::OnDropDown(NMHDR *pHdr, LRESULT *pRes)
|
||
{
|
||
UNREFERENCED_PARAMETER(pHdr);
|
||
|
||
HWND hwndMonthCal=(HWND)::SendMessage(m_hWnd,DTM_GETMONTHCAL,0,0);
|
||
if(hwndMonthCal!=NULL)
|
||
{
|
||
if(::IsWindow(m_ctlMonthCal.GetSafeHwnd()))
|
||
m_ctlMonthCal.DestroyWindow();
|
||
|
||
m_ctlMonthCal.SubclassWindow(hwndMonthCal);
|
||
}
|
||
|
||
*pRes=0;
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// DDX_ routines
|
||
|
||
#if _MFC_VER<=0x0421
|
||
|
||
void AFXAPI DDX_DateTimeCtrl(CDataExchange* pDX, int nIDC, COleDateTime& value)
|
||
{
|
||
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
|
||
COXDateTimeCtrl* pWnd = (COXDateTimeCtrl*) CWnd::FromHandle(hWndCtrl);
|
||
|
||
if (pDX->m_bSaveAndValidate)
|
||
pWnd->GetTime(value);
|
||
else
|
||
pWnd->SetTime(value);
|
||
}
|
||
|
||
void AFXAPI DDX_DateTimeCtrl(CDataExchange* pDX, int nIDC, CTime& value)
|
||
{
|
||
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
|
||
COXDateTimeCtrl* pWnd = (COXDateTimeCtrl*) CWnd::FromHandle(hWndCtrl);
|
||
|
||
if (pDX->m_bSaveAndValidate)
|
||
pWnd->GetTime(value);
|
||
else
|
||
pWnd->SetTime(&value);
|
||
}
|
||
|
||
void AFXAPI DDV_MinMaxDateTime(CDataExchange* pDX, CTime& refValue,
|
||
const CTime* pMinRange, const CTime* pMaxRange)
|
||
{
|
||
ASSERT(pMinRange == NULL || pMaxRange == NULL || *pMinRange <= *pMaxRange);
|
||
|
||
COXDateTimeCtrl* pWnd =
|
||
(COXDateTimeCtrl*) 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_MinMaxDateTime(CDataExchange* pDX, COleDateTime& refValue,
|
||
const COleDateTime* pMinRange, const COleDateTime* pMaxRange)
|
||
{
|
||
ASSERT(pMinRange == NULL || pMaxRange == NULL || *pMinRange <= *pMaxRange);
|
||
COXDateTimeCtrl* pWnd =
|
||
(COXDateTimeCtrl*) CWnd::FromHandle(pDX->m_hWndLastControl);
|
||
|
||
if (!pDX->m_bSaveAndValidate)
|
||
{
|
||
if ( (pMinRange != NULL && *pMinRange > refValue) ||
|
||
(pMaxRange != NULL && *pMaxRange < refValue))
|
||
{
|
||
int nIDC = GetWindowLongPtr(pDX->m_hWndLastControl, GWL_ID);
|
||
TRACE1("Warning: initial dialog data is out of range in control ID %d.\n", nIDC);
|
||
return; // don't stop now
|
||
}
|
||
}
|
||
|
||
pWnd->SetRange(pMinRange, pMaxRange);
|
||
}
|
||
|
||
#endif
|