// ========================================================================== // 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" #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