// XTPCalendarView.cpp : implementation file // // 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/XTPPropExchange.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPSmartPtrInternalT.h" #include "Common/XTPNotifyConnection.h" #include "Common/XTPColorManager.h" #include "XTPCalendarDefines.h" #include "XTPCalendarUtils.h" #include "XTPCalendarPtrCollectionT.h" #include "XTPCalendarNotifications.h" #include "XTPCalendarOptions.h" #include "XTPCalendarTimeZoneHelper.h" #include "XTPCalendarResource.h" #include "XTPCalendarEvent.h" #include "XTPCalendarEvents.h" #include "XTPCalendarView.h" #include "XTPCalendarViewEvent.h" #include "XTPCalendarViewDay.h" #include "XTPCalendarTimeLineView.h" #include "XTPCalendarViewPart.h" #include "XTPCalendarControl.h" #include "XTPCalendarData.h" #include "XTPCalendarPaintManager.h" #include "XTPCalendarTheme.h" #include "XTPCalendarThemeOffice2007.h" #include #pragma warning(disable: 4571) // warning C4571: catch(...) blocks compiled with /EHs do not catch or re-throw Structured Exceptions #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define XTP_CLIPBOARD_EVENTS_DATA_VER 2 class CXTPCalendarView::CUndoBuffer { public: //----------------------------------------------------------------------- // Summary: // Default class constructor. //----------------------------------------------------------------------- CUndoBuffer() {}; //----------------------------------------------------------------------- // Summary: // Default class destructor. //----------------------------------------------------------------------- virtual ~CUndoBuffer() { RemoveAll(); }; //----------------------------------------------------------------------- // Summary: // This member function is used to add an Undo action to the buffer. // Parameters: // pPrev - A CXTPCalendarEvent object that contains the instance // before the edit action. // pNew - A CXTPCalendarEvent that contains the instance after // the edit action. //----------------------------------------------------------------------- void AddUndoAction(CXTPCalendarEvent* pPrev, CXTPCalendarEvent* pNew) { CXTPCalendarEventPtr ptrPrevCopy = pPrev ? pPrev->CloneEvent() : NULL; CXTPCalendarEventPtr ptrNewCopy = pNew ? pNew->CloneEvent() : NULL; m_arUndoActions.Add(SUndoAction(ptrPrevCopy, ptrNewCopy)); } //----------------------------------------------------------------------- // Summary: // Call this member function to clear the Undo buffer. //----------------------------------------------------------------------- void RemoveAll() { m_arUndoActions.RemoveAll(); } //----------------------------------------------------------------------- // Summary: // This member function is used to search for an undo action for a // specified event in the buffer. // Parameters: // pEvent - A CXTPCalendarEvent object to search for in the buffer. // Returns: // A BOOL. TRUE if undo action for a specified event exists in the // buffer. FALSE otherwise. //----------------------------------------------------------------------- BOOL IsInUndoBuffer(CXTPCalendarEvent* pEvent) { int nCount = (int)m_arUndoActions.GetSize(); for (int i = nCount-1; i >= 0; i--) { SUndoAction& rAction = m_arUndoActions.ElementAt(i); if (rAction.ptrPrev && rAction.ptrPrev->IsEqualIDs(pEvent) || rAction.ptrNew && rAction.ptrNew->IsEqualIDs(pEvent)) { return TRUE; } } return FALSE; } //----------------------------------------------------------------------- // Summary: // Call this member function to obtain the number of undo actions. // Returns: // An int that contains the number of Undo actions. //----------------------------------------------------------------------- int GetCount() const { return (int)m_arUndoActions.GetSize(); } //----------------------------------------------------------------------- // Summary: // Call this member function to obtain the first undo event. // Returns: // A CXTPCalendarEvent object that contains the first undo event // or NULL if there are no undo events. //----------------------------------------------------------------------- CXTPCalendarEventPtr GetFirstUndoEvent() { int nCount = (int)m_arUndoActions.GetSize(); if (nCount > 0) { SUndoAction& rAction = m_arUndoActions.ElementAt(0); if (rAction.ptrPrev) { return rAction.ptrPrev; } else if (rAction.ptrNew) { return rAction.ptrNew; } } return NULL; } //----------------------------------------------------------------------- // Summary: // This member function is used to search for the first action for // a specified event in the buffer. // Parameters: // pEvent - A CXTPCalendarEvent object that contains the event to // search for in the buffer. // Returns: // A CXTPCalendarEvent that contains the oldest event object from // all of the editing actions or NULL if there are no events. //----------------------------------------------------------------------- CXTPCalendarEventPtr UndoAllForEvent(CXTPCalendarEvent* pEvent) { int nCount = (int)m_arUndoActions.GetSize(); for (int i = 0; i < nCount; i++) { SUndoAction& rAction = m_arUndoActions.ElementAt(i); if (rAction.ptrPrev && rAction.ptrPrev->IsEqualIDs(pEvent) || rAction.ptrNew && rAction.ptrNew->IsEqualIDs(pEvent)) { return rAction.ptrPrev; } } return NULL; } //----------------------------------------------------------------------- // Summary: // This member function is used to search for last action for a // specified event in the buffer. // Parameters: // pEvent - A CXTPCalendarEvent object that contains the event // to search for in the buffer. // Returns: // A CXTPCalendarEvent that contains the latest event object from // all of the editing actions or NULL if there are no events. //----------------------------------------------------------------------- CXTPCalendarEventPtr RedoAllForEvent(CXTPCalendarEvent* pEvent) { CXTPCalendarEventPtr ptrResult; int nCount = (int)m_arUndoActions.GetSize(); for (int i = nCount-1; i >= 0; i--) { SUndoAction& rAction = m_arUndoActions.ElementAt(i); if (rAction.ptrPrev && rAction.ptrPrev->IsEqualIDs(pEvent) || rAction.ptrNew && rAction.ptrNew->IsEqualIDs(pEvent)) { return rAction.ptrNew; } } return NULL; } //----------------------------------------------------------------------- // Summary: // This member function is used to clear the current buffer of all // undo actions and then add new undo actions to the buffer from // the source object. // Parameters: // rSrc - A CUndoBuffer object that contains the new undo actions // to add to the undo buffer object. //----------------------------------------------------------------------- void Set(CUndoBuffer& rSrc) { m_arUndoActions.RemoveAll(); m_arUndoActions.Append(rSrc.m_arUndoActions); } protected: //----------------------------------------------------------------------- // Remarks: // Helper structure to store editing/undo actions. //----------------------------------------------------------------------- struct SUndoAction { CXTPCalendarEventPtr ptrPrev; // Event instance before edit action. CXTPCalendarEventPtr ptrNew; // Event instance after edit action. //----------------------------------------------------------------------- // Summary: // Default class constructor. // Parameters: // pPrev - A CXTPCalendarEvent object that contains the instance // before the edit action. // pNew - A CXTPCalendarEvent object that contains the instance // after the edit action. //----------------------------------------------------------------------- SUndoAction(CXTPCalendarEvent* pPrev = NULL, CXTPCalendarEvent* pNew = NULL) : ptrPrev(pPrev, TRUE), ptrNew(pNew, TRUE) {}; //----------------------------------------------------------------------- // Parameters: // src - A SUndoAction object that contains the source object. // Summary: // Copy class constructor. //----------------------------------------------------------------------- SUndoAction(const SUndoAction& src) { *this = src; } //----------------------------------------------------------------------- // Summary: // Default class destructor. //----------------------------------------------------------------------- virtual ~SUndoAction() {} //----------------------------------------------------------------------- // Summary: // This is the overloaded assignment operator. // Parameters: // src - Source object. // Returns: // A reference to the current object. // Remarks: // Copy class operator. //----------------------------------------------------------------------- const SUndoAction& operator=(const SUndoAction& src) { ptrPrev = src.ptrPrev; ptrNew = src.ptrNew; return *this; } }; CArray m_arUndoActions; // Array of editing/undo actions. }; //=========================================================================== IMPLEMENT_DYNAMIC(CXTPCalendarWMHandler, CCmdTarget) IMPLEMENT_DYNAMIC(CXTPCalendarView, CXTPCalendarWMHandler) ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // CXTPCalendarView CXTPCalendarView::CXTPCalendarView(CXTPCalendarControl* pCalendarControl) : m_pControl(pCalendarControl) { //m_strDayHeaderFormatLong = _T("d MMMM"); //m_strDayHeaderFormatMiddle = _T("d MMM"); //m_strDayHeaderFormatShort = _T("d"); //m_strDayHeaderFormatShortest = _T("d"); m_rcView.SetRectEmpty(); m_rcTooltip.SetRectEmpty(); m_Layout.m_nRowHeight = 18; m_eDraggingMode = xtpCalendaDragModeUnknown; m_ptStartDragging.x = m_ptStartDragging.y = LONG_MAX; m_bStartedClickInside = FALSE; m_nTimerID_StartEditSubject = 0; m_nTimerID_ShowToolTip = 0; m_eUndoMode = xtpCalendarUndoModeUnknown; m_bResetUndoBuffer = FALSE; m_nKeyStateTimerID = 0; m_pSelectedEvents = new CXTPCalendarViewEvents(); m_pResources = NULL; m_pUndoBuffer = new CUndoBuffer(); m_pPrevUndoBuffer = new CUndoBuffer(); _CalculateEventTimeFormat(); m_bScrollV_Disabled = FALSE; m_bScrollH_Disabled = FALSE; ClearDiscreteSelection(); m_ptLBtnDownMousePos = CPoint(0,0); m_ptLBtnUpMousePos = CPoint(0,0); } CXTPCalendarView::~CXTPCalendarView() { CMDTARGET_RELEASE(m_pSelectedEvents); CMDTARGET_RELEASE(m_pResources); ASSERT(m_nTimerID_StartEditSubject == 0); ASSERT(m_nTimerID_ShowToolTip == 0); ClearDiscreteSelection(); SAFE_DELETE(m_pUndoBuffer); SAFE_DELETE(m_pPrevUndoBuffer); } void CXTPCalendarView::OnBeforeDestroy() { // --- Kill Subject editor if (IsEditingSubject()) EndEditSubject(xtpCalendarEditSubjectCommit, FALSE); if (m_ptrDraggingEventNew) CommitDraggingEvent(); // --- Kill tooltip (and timer inside) ShowToolTip(FALSE); // --- Clear selected events collection if (m_pSelectedEvents) m_pSelectedEvents->RemoveAll(); // === Call base cleanup code TBase::OnBeforeDestroy(); } void CXTPCalendarView::OnActivateView(BOOL bActivate, CXTPCalendarView* pActivateView, CXTPCalendarView* pInactiveView) { UNREFERENCED_PARAMETER(pActivateView); UNREFERENCED_PARAMETER(pInactiveView); if (!bActivate && IsEditingSubject()) EndEditSubject(xtpCalendarEditSubjectCommit, FALSE); } void CXTPCalendarView::RedrawControl() { ASSERT(m_pControl); if (m_pControl) { m_pControl->RedrawControl(); } } void CXTPCalendarView::Populate() { if (IsEditingSubject()) { EndEditSubject(xtpCalendarEditSubjectCommit); } int nCount = GetViewDayCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarViewDay* pViewDay = GetViewDay_(i); COleDateTime dtDay = GetViewDayDate(i); //ASSERT(pViewDay); if (pViewDay) pViewDay->Populate(dtDay); } _ReSelectSelectEvents(); } BOOL CXTPCalendarView::OnLButtonDown(UINT nFlags, CPoint point) { m_ptLBtnDownMousePos = point; CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed); CSelectionChangedContext selChanged(this); if (!m_pControl->IsReadonlyMode()) m_bStartedClickInside = TRUE; //--------------------------------------------------------------------------- TBase::OnLButtonDown(nFlags, point); //= kill timeout request to edit subject===================================== if (m_nTimerID_StartEditSubject) { KillTimer(m_nTimerID_StartEditSubject); m_nTimerID_StartEditSubject = 0; m_ptrEditingViewEvent = NULL; } //--------------------------------------------------------------------------- XTP_CALENDAR_HITTESTINFO hitInfo; if (HitTest(point, &hitInfo)) { if (hitInfo.uHitCode & xtpCalendarHitTestDay_Mask) { CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw); ProcessDaySelection(&hitInfo, nFlags); } else if (hitInfo.uHitCode & xtpCalendarHitTestEvent_Mask && !m_pControl->IsReadonlyMode()) { CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw); ProcessEventSelection(&hitInfo, nFlags); // set request to start dragging when OnMouseMove() m_ptStartDragging = point; } } //--------------------------------------------------------------------------- BOOL bResetUndoLocal = TRUE; if (IsEditingSubject() && !m_pControl->IsReadonlyMode()) { if (!GetSubjectEditorRect().PtInRect(point)) { bResetUndoLocal = m_eDraggingMode != xtpCalendaDragModeEditSubject; EndEditSubject(xtpCalendarEditSubjectCommit); } } m_bResetUndoBuffer = bResetUndoLocal; //--------------------------------------------------------------------------- CXTPCalendarThemeOffice2007* pThemeX = DYNAMIC_DOWNCAST(CXTPCalendarThemeOffice2007, GetTheme()); if (pThemeX) { XTP_SAFE_CALL1(pThemeX->GetPrevNextEventButtonsPartX(), OnLButtonDown(this, nFlags, point)); } return TRUE; } BOOL CXTPCalendarView::OnLButtonUp(UINT nFlags, CPoint point) { m_ptLBtnUpMousePos = m_ptLBtnDownMousePos; m_ptLBtnDownMousePos = CPoint(0, 0); // way to support discrete selection - pick all days while ALT key hold XTP_CALENDAR_HITTESTINFO hitAltInfo; BOOL bAltHitTest = HitTest(point, &hitAltInfo); BOOL bVKAlt = (GetKeyState(VK_MENU) < 0); if (bAltHitTest && bVKAlt && nFlags == 0 && m_bStartedClickInside) { if (hitAltInfo.dt != NULL) { UINT uDay = (UINT) hitAltInfo.dt; AddToDiscreteSelection(uDay); return TRUE; } } else { ClearDiscreteSelection(); } CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed); CSelectionChangedContext selChanged(this); const BOOL bHandled = TBase::OnLButtonUp(nFlags, point); //--------------------------------------------------------------------------- m_ptStartDragging.x = m_ptStartDragging.y = LONG_MAX; XTP_CALENDAR_HITTESTINFO hitInfo; BOOL bHitTest = HitTest(point, &hitInfo); if (GetViewType() == xtpCalendarTimeLineView) { CXTPCalendarTimeLineView* pView = (CXTPCalendarTimeLineView* ) GetCalendarControl()->GetActiveView(); if (pView) pView->ShowCalendarPopup(hitInfo.dt, point); } int nDragMode = m_eDraggingMode; if (!OnEndDragging(point, &hitInfo) && !m_pControl->IsReadonlyMode()) { if (!bHandled && bHitTest) { UINT uESmask = xtpCalendarHitTestEventTextArea | xtpCalendarHitTestEventResizeArea_Mask; if ((hitInfo.uHitCode & uESmask) && !IsEditingSubject() && hitInfo.pViewEvent && hitInfo.pViewEvent->IsSelected()) { BOOL bEnabled = XTP_SAFE_GET1(GetCalendarOptions(), bEnableInPlaceEditEventSubject_ByMouseClick, FALSE); bEnabled = bEnabled && IsSingleEventSelected(); if (bEnabled) bEnabled = !OnBeforeEditOperationNotify(xtpCalendarEO_EditSubject_ByMouseClick, hitInfo.pViewEvent); if (bEnabled) { ASSERT(!m_ptrEditingViewEvent); m_ptrEditingViewEvent = hitInfo.pViewEvent; m_ptrEditingViewEvent->InternalAddRef(); if (m_nTimerID_StartEditSubject == 0) { UINT uTimeOut_ms = GetStartEditSubjectTimeOut(); m_nTimerID_StartEditSubject = SetTimer(uTimeOut_ms); } } } } } //--------------------------------------------------------------------------- if (_IsDragModeCopyMove(nDragMode) && bHitTest && hitInfo.pViewDay) { UnselectAllEvents(); SelectDay(hitInfo.pViewDay, hitInfo.nGroup); } if (GetCalendarControl()) GetCalendarControl()->m_mouseMode = xtpCalendarMouseNothing; m_bStartedClickInside = FALSE; OnMouseMove(nFlags, point); return TRUE; } void CXTPCalendarView::OnMouseMove(UINT nFlags, CPoint point) { CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed); CSelectionChangedContext selChanged(this); CXTPCalendarThemeOffice2007* pThemeX = DYNAMIC_DOWNCAST(CXTPCalendarThemeOffice2007, GetTheme()); if (pThemeX) XTP_SAFE_CALL1(pThemeX->GetPrevNextEventButtonsPartX(), OnMouseMove(this, nFlags, point)); TBase::OnMouseMove(nFlags, point); XTP_CALENDAR_HITTESTINFO hitInfo; BOOL bHitTest = HitTest(point, &hitInfo); if (bHitTest && hitInfo != m_LastHitInfo) { m_LastHitInfo = hitInfo; BOOL bVKAlt = (GetKeyState(VK_MENU) < 0); if (bVKAlt && (nFlags & MK_LBUTTON && m_bStartedClickInside)) { //Preventing continues selection if ALT key hold if (m_LastHitInfo.dt != NULL) { UINT uDay = (UINT) m_LastHitInfo.dt; AddToDiscreteSelection(uDay); } } else if (nFlags & MK_LBUTTON && m_bStartedClickInside) { const int cEpsilon = 2; if (m_ptStartDragging.x == LONG_MAX || m_ptStartDragging.y == LONG_MAX || abs(point.x - m_ptStartDragging.x) >= cEpsilon || abs(point.y - m_ptStartDragging.y) >= cEpsilon) { if (!m_ptrDraggingEventNew && !m_ptrDraggingEventOrig && m_eDraggingMode == xtpCalendaDragModeUnknown) { XTP_CALENDAR_HITTESTINFO hitInfoSD; if (HitTest(m_ptStartDragging, &hitInfoSD)) { if (hitInfoSD.uHitCode & xtpCalendarHitTestEvent_Mask) { int eDragMode = _GetDraggingMode(&hitInfoSD); if (!IsEditOperationDisabledNotify(_DragMod2Operation(eDragMode), hitInfoSD.pViewEvent)) OnStartDragging(m_ptStartDragging, &hitInfoSD); } } } m_ptStartDragging.x = m_ptStartDragging.y = LONG_MAX; BOOL bDragging = m_ptrDraggingEventNew && m_eDraggingMode != xtpCalendaDragModeEditSubject; if (bDragging) { CXTPCalendarEventPtr ptrDragEventPrev = m_ptrDraggingEventNew->CloneEvent(); BOOL bDragged = OnDragging(point, &hitInfo); if (bDragged) { XTP_EVENT_DRAG_OPERATION_PARAMS opParamsDrag; ::ZeroMemory(&opParamsDrag, sizeof(opParamsDrag)); opParamsDrag.eOperation = _DragMod2Operation(m_eDraggingMode); opParamsDrag.pDraggingEventOriginal = m_ptrDraggingEventOrig; opParamsDrag.pDraggingEvent = ptrDragEventPrev; opParamsDrag.pDraggingEventNew = m_ptrDraggingEventNew; BOOL bHandled = FALSE; if (m_pControl) m_pControl->SendNotification(XTP_NC_CALENDAR_BEFORE_EVENT_EDIT_OPERATION, (WPARAM)&opParamsDrag, (LPARAM)&bHandled); if (bHandled) //rollback m_ptrDraggingEventNew = ptrDragEventPrev; XTP_SAFE_CALL1(GetCalendarControl(), Populate()); CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateLayout | xtpCalendarUpdateRedraw); if (m_ptrDraggingEventNew && m_ptrDraggingEventOrig && (!m_ptrDraggingEventNew->IsEqualStartEnd(m_ptrDraggingEventOrig) || m_ptrDraggingEventNew->GetScheduleID() != m_ptrDraggingEventOrig->GetScheduleID())) SelectEvent(m_ptrDraggingEventNew); } } } if (m_eDraggingMode == xtpCalendaDragModeUnknown && hitInfo.uHitCode & (xtpCalendarHitTestDay_Mask | xtpCalendarHitTestEvent_Mask)) { if ((hitInfo.uHitCode & xtpCalendarHitTestEvent_Mask) && hitInfo.pViewEvent && hitInfo.pViewEvent->IsSelected()) {} else { CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw); ProcessDaySelection(&hitInfo, nFlags | MK_SHIFT); } } } // process tooltip events (only when no buttons pressed) if (0 == nFlags) { CRect rcTooltip(GetTooltipRect(point, hitInfo)); if (m_rcTooltip != rcTooltip) { // -- kill waiting and hide a tooltip because we switched to another cell ShowToolTip(FALSE); // -- start waiting for mouse under regular empty cell // (to show later "click to add appointment" button) UINT uTimeOut_ms = GetShowToolTipTimeOut(); m_nTimerID_ShowToolTip = SetTimer(uTimeOut_ms); m_rcTooltip = rcTooltip; ASSERT(m_nTimerID_ShowToolTip); } } } else if (!bHitTest) { XTP_CALENDAR_HITTESTINFO hitInfoEmpty; m_LastHitInfo = hitInfoEmpty; } //=========================================================================== if (GetCalendarControl()) { if (_IsDragModeCopyMove(m_eDraggingMode) && GetCalendarControl()->m_mouseMode != xtpCalendarMouseEventDraggingOut) { GetCalendarControl()->m_mouseMode = m_eDraggingMode == xtpCalendaDragModeCopy ? xtpCalendarMouseEventDragCopy : xtpCalendarMouseEventDragMove; GetCalendarControl()->UpdateMouseCursor(); } } } void CXTPCalendarView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed); CSelectionChangedContext selChanged(this); TBase::OnChar(nChar, nRepCnt, nFlags); BOOL bEnable = XTP_SAFE_GET1(GetCalendarOptions(), bEnableInPlaceCreateEvent, FALSE); if (nChar >= _T(' ') && bEnable && !m_pControl->IsReadonlyMode()) { CString strInitialSubj((TCHAR)nChar); if (!OnInPlaceCreateEvent(strInitialSubj)) StartEditNewEventInplace(strInitialSubj); } } void CXTPCalendarView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed); CSelectionChangedContext selChanged(this); TBase::OnKeyDown(nChar, nRepCnt, nFlags); if (nChar == VK_RETURN || nChar == VK_ESCAPE) { if (IsEditingSubject()) { CXTPCalendarEventPtr ptrEditingEvent(m_ptrDraggingEventOrig, TRUE); EndEditSubject((nChar == VK_RETURN) ? xtpCalendarEditSubjectCommit : xtpCalendarEditSubjectCancel); if (nChar == VK_ESCAPE && ptrEditingEvent) { _Undo(ptrEditingEvent); m_pUndoBuffer->Set(*m_pPrevUndoBuffer); } } if (nChar == VK_ESCAPE && m_ptrDraggingEventNew) { CXTPCalendarEventPtr ptrEditingEvent(m_ptrDraggingEventOrig, TRUE); CancelDraggingEvent(); BOOL bControlUpdated = FALSE; if (ptrEditingEvent && !m_bResetUndoBuffer) { bControlUpdated = _Undo(ptrEditingEvent); m_pUndoBuffer->Set(*m_pPrevUndoBuffer); } if (!bControlUpdated && GetCalendarControl()) { CXTPCalendarControl::CUpdateContext updateContext1(GetCalendarControl(), xtpCalendarUpdateLayout | xtpCalendarUpdateRedraw); GetCalendarControl()->Populate(); } } } else if (nChar == VK_F2) { if (IsEditingSubject()) { return; } CXTPCalendarViewEvent* pViewEvent = GetLastSelectedViewEvent(); if (GetViewType() == xtpCalendarDayView || GetViewType() == xtpCalendarWorkWeekView || GetViewType() == xtpCalendarFullWeekView) { CPoint point = m_ptLBtnUpMousePos; XTP_CALENDAR_HITTESTINFO hitInfo; if (HitTest(point, &hitInfo)) { if (pViewEvent) { CXTPCalendarEvent* pEvent = pViewEvent->GetEvent(); if (pEvent) pViewEvent = FindViewEventByGroup(pEvent, pEvent->GetStartTime(), hitInfo.nGroup); } } } BOOL bEnabled = XTP_SAFE_GET1(GetCalendarOptions(), bEnableInPlaceEditEventSubject_ByF2, FALSE); bEnabled = bEnabled && m_eDraggingMode == xtpCalendaDragModeUnknown && pViewEvent; if (bEnabled) bEnabled = !OnBeforeEditOperationNotify(xtpCalendarEO_EditSubject_ByF2, pViewEvent); if (bEnabled) { ASSERT(!m_ptrDraggingEventOrig && !m_ptrDraggingEventNew && !m_ptrEditingViewEvent); if (pViewEvent) { CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw); EmptyUndoBuffer(); StartEditSubject(pViewEvent); } } } else if (nChar == VK_DELETE) { if (m_eDraggingMode == xtpCalendaDragModeUnknown && !m_ptrEditingViewEvent) { ASSERT(!m_ptrDraggingEventOrig && !m_ptrDraggingEventNew && !m_ptrEditingViewEvent); CXTPCalendarViewEvent* pViewEvent = GetLastSelectedViewEvent(); if (m_selectedBlock.dtEnd.GetStatus() == COleDateTime::valid && GetCalendarControl() && pViewEvent && pViewEvent->IsSelected()) { CXTPCalendarControl::CUpdateContext updateContext1(GetCalendarControl(), xtpCalendarUpdateRedraw | xtpCalendarUpdateLayout); VERIFY(GetCalendarControl()->DoDeleteSelectedEvents(pViewEvent)); GetCalendarControl()->Populate(); } } } else if (nChar == VK_TAB) { if (m_eDraggingMode == xtpCalendaDragModeUnknown || m_eDraggingMode == xtpCalendaDragModeEditSubject) { BOOL bShift = (GetKeyState(VK_SHIFT) < 0); CXTPCalendarControl::CUpdateContext updateContext1(m_pControl, xtpCalendarUpdateRedraw); if (IsEditingSubject()) { EndEditSubject(xtpCalendarEditSubjectCommit); } COleDateTime dtMinStart = GetNextTimeEditByTAB(); CXTPCalendarViewEvent* pViewEvent = GetLastSelectedViewEvent(); CXTPCalendarEvent* pLastEvent = pViewEvent ? pViewEvent->GetEvent() : NULL; const int cLoopMax = 5000; int i; for (i = 0; i < cLoopMax; i++) // to prevent infinite looping { pViewEvent = FindEventToEditByTAB(dtMinStart, bShift, pLastEvent); pLastEvent = pViewEvent ? pViewEvent->GetEvent() : NULL; if (!pViewEvent || pViewEvent && pViewEvent->IsVisible()) { break; } } ASSERT(i < cLoopMax); // probably infinite looping ??? UnselectAllEvents(); if (pViewEvent && pViewEvent->IsVisible() && pViewEvent->GetEvent()) { dtMinStart = pViewEvent->GetEvent()->GetStartTime(); UpdateNextTimeEditByTAB(dtMinStart, bShift); EmptyUndoBuffer(); BOOL bEnabled = XTP_SAFE_GET1(GetCalendarOptions(), bEnableInPlaceEditEventSubject_ByTab, FALSE); if (bEnabled) { bEnabled = !OnBeforeEditOperationNotify(xtpCalendarEO_EditSubject_ByTab, pViewEvent); } if (bEnabled) { StartEditSubject(pViewEvent); } else { SelectEvent(pViewEvent->GetEvent()); } SelectDay(XTP_SAFE_GET2(pViewEvent, GetViewGroup_(), GetViewDay_(), NULL), XTP_SAFE_GET2(pViewEvent, GetViewGroup_(), GetGroupIndex(), -1)); } else { dtMinStart = GetViewDayDate(bShift ? GetViewDayCount()-1 : 0); UpdateNextTimeEditByTAB(dtMinStart, bShift, TRUE); } } } } BOOL CXTPCalendarView::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedrawIfNeed); CSelectionChangedContext selChanged(this); BOOL bHandled = TBase::OnSysKeyDown(nChar, nRepCnt, nFlags); UINT uAltBit = (((UINT)1) << 13); if (nChar == VK_BACK && (nFlags & uAltBit)) { bHandled = TRUE; if (CanUndo()) Undo(); else if (CanRedo()) Redo(); } return bHandled; } BOOL CXTPCalendarView::SetDraggingEvent(CXTPCalendarEvent* pEventOrig) { if (m_ptrDraggingEventOrig || m_ptrDraggingEventNew || !pEventOrig) return FALSE; // Dragging Event already set or CommitDraggingEvent() was not called or invalid parameter pEventOrig->InternalAddRef(); m_ptrDraggingEventOrig = pEventOrig; m_ptrDraggingEventNew = pEventOrig->CloneEvent(); if (m_ptrDraggingEventNew && m_ptrDraggingEventNew->GetRecurrenceState() == xtpCalendarRecurrenceOccurrence) { VERIFY(m_ptrDraggingEventNew->MakeAsRException()); } return TRUE; } CXTPCalendarEvent* CXTPCalendarView::GetDraggingEventOrig() const { return m_ptrDraggingEventOrig; } CXTPCalendarEvent* CXTPCalendarView::GetDraggingEventNew() const { return m_ptrDraggingEventNew; } BOOL CXTPCalendarView::CommitDraggingEvent() { ASSERT(m_ptrDraggingEventNew); if (!GetCalendarControl()) { return FALSE; } CXTPAutoResetValue autoSet_UpdateCtrlNf(GetCalendarControl()->m_bUpdateWhenEventChangedNotify); autoSet_UpdateCtrlNf = FALSE; if (m_ptrDraggingEventNew && m_ptrDraggingEventOrig) { BOOL bDPdiff = m_ptrDraggingEventNew->GetDataProvider() != m_ptrDraggingEventOrig->GetDataProvider(); BOOL bChanged = !m_ptrDraggingEventNew->IsEqualStartEnd(m_ptrDraggingEventOrig); bChanged = bChanged || m_ptrDraggingEventNew->GetSubject() != m_ptrDraggingEventOrig->GetSubject(); bChanged = bChanged || m_ptrDraggingEventNew->IsAllDayEvent() != m_ptrDraggingEventOrig->IsAllDayEvent(); bChanged = bChanged || m_ptrDraggingEventNew->GetScheduleID() != m_ptrDraggingEventOrig->GetScheduleID(); bChanged = bChanged || bDPdiff; if (bChanged || m_eDraggingMode == xtpCalendaDragModeCopy) { if (!m_pUndoBuffer->IsInUndoBuffer(m_ptrDraggingEventOrig) || m_bResetUndoBuffer) { m_pPrevUndoBuffer->Set(*m_pUndoBuffer); EmptyUndoBuffer(); } CXTPCalendarData* pDataNew = m_ptrDraggingEventNew->GetDataProvider(); // _GetDataProviderForDraggingEvent(m_ptrDraggingEventNew); CXTPCalendarData* pDataOrig = m_ptrDraggingEventOrig->GetDataProvider(); if (m_eDraggingMode == xtpCalendaDragModeCopy) { if (m_ptrDraggingEventNew->GetRecurrenceState() != xtpCalendarRecurrenceNotRecurring) { VERIFY(m_ptrDraggingEventNew->RemoveRecurrence() ); } if (pDataNew) { DBG_DATA_VERIFY(pDataNew->AddEvent(m_ptrDraggingEventNew) ); } } else { m_pUndoBuffer->AddUndoAction(m_ptrDraggingEventOrig, m_ptrDraggingEventNew); m_eUndoMode = xtpCalendarUndoModeUndo; m_bResetUndoBuffer = FALSE; if (pDataNew) { if (!bDPdiff) { // restore event ID for case when m_ptrDraggingEventNew was recreated // during dragging between providers m_ptrDraggingEventNew->SetEventID(m_ptrDraggingEventOrig->GetEventID()); DBG_DATA_VERIFY(pDataNew->ChangeEvent(m_ptrDraggingEventNew) ); } else { if (m_ptrDraggingEventNew->GetRecurrenceState() != xtpCalendarRecurrenceNotRecurring) { VERIFY(m_ptrDraggingEventNew->RemoveRecurrence() ); } if (pDataOrig) { DBG_DATA_VERIFY(pDataOrig->DeleteEvent(m_ptrDraggingEventOrig) ); } DBG_DATA_VERIFY(pDataNew->AddEvent(m_ptrDraggingEventNew)); } } } } m_ptrDraggingEventOrig = NULL; m_ptrDraggingEventNew = NULL; return bChanged; } else if (m_ptrDraggingEventNew) { if (!m_pUndoBuffer->IsInUndoBuffer(m_ptrDraggingEventNew) || m_bResetUndoBuffer) { m_pPrevUndoBuffer->Set(*m_pUndoBuffer); EmptyUndoBuffer(); } CXTPCalendarData* pData = m_ptrDraggingEventNew->GetDataProvider(); //_GetDataProviderForDraggingEvent(m_ptrDraggingEventNew); ASSERT(m_ptrDraggingEventNew->GetRecurrenceState() == xtpCalendarRecurrenceNotRecurring); if (pData) { DBG_DATA_VERIFY( pData->AddEvent(m_ptrDraggingEventNew) ); } m_pUndoBuffer->AddUndoAction(NULL, m_ptrDraggingEventNew); m_eUndoMode = xtpCalendarUndoModeUndo; m_bResetUndoBuffer = FALSE; m_ptrDraggingEventOrig = NULL; m_ptrDraggingEventNew = NULL; return TRUE; } return FALSE; } void CXTPCalendarView::CancelDraggingEvent() { ASSERT(m_ptrDraggingEventNew); m_eDraggingMode = xtpCalendaDragModeUnknown; if (GetCalendarControl()) { GetCalendarControl()->m_mouseMode = xtpCalendarMouseNothing; GetCalendarControl()->UpdateMouseCursor(); } m_ptrDraggingEventOrig = NULL; m_ptrDraggingEventNew = NULL; m_ptStartDragging.x = m_ptStartDragging.y = LONG_MAX; m_bStartedClickInside = FALSE; } CXTPCalendarEventsPtr CXTPCalendarView::RetrieveDayEvents(CXTPCalendarResource* pRC, COleDateTime dtDay) { ASSERT(pRC); dtDay = CXTPCalendarUtils::ResetTime(dtDay); CXTPCalendarEventsPtr ptrEvents = pRC ? pRC->RetrieveDayEvents(dtDay) : new CXTPCalendarEvents(); if (!m_ptrDraggingEventNew || !ptrEvents || !pRC) { return ptrEvents; } BOOL bIsDragCopy = m_eDraggingMode == xtpCalendaDragModeCopy; COleDateTime dtDay1 = GetDateTimeDay(m_ptrDraggingEventNew->GetStartTime(), m_ptrDraggingEventNew->IsAllDayEvent()); COleDateTime dtDay2 = GetDateTimeDay(m_ptrDraggingEventNew->GetEndTime(), m_ptrDraggingEventNew->IsAllDayEvent()); UINT uSchID = m_ptrDraggingEventNew->GetScheduleID(); BOOL bNewEventScheduleVisible = m_ptrDraggingEventNew->GetDataProvider() == pRC->GetDataProvider() && pRC->ExistsScheduleID(uSchID); if (!bIsDragCopy) { int nCount = ptrEvents->GetCount(); for (int i = nCount-1; i >= 0; i--) { CXTPCalendarEvent* pEvent = ptrEvents->GetAt(i, FALSE); if (!pEvent) { continue; } if (m_ptrDraggingEventOrig && m_ptrDraggingEventOrig->GetDataProvider() == pEvent->GetDataProvider() && m_ptrDraggingEventOrig->IsEqualIDs(pEvent) && m_ptrDraggingEventOrig->GetScheduleID() == pEvent->GetScheduleID()) { ptrEvents->RemoveAt(i); //break; } } } if (dtDay >= dtDay1 && dtDay <= dtDay2 && bNewEventScheduleVisible) { ptrEvents->Add(m_ptrDraggingEventNew); } return ptrEvents; } XTPCalendarDraggingMode CXTPCalendarView::_GetDraggingMode(XTP_CALENDAR_HITTESTINFO* pHitTest) const { if (!pHitTest) { ASSERT(FALSE); return xtpCalendaDragModeUnknown; } if (pHitTest->uHitCode & xtpCalendarHitTestEventResizeArea_Mask) { if (pHitTest->uHitCode & xtpCalendarHitTestEventResizeBegin) { return xtpCalendaDragModeResizeBegin; } else if (pHitTest->uHitCode & xtpCalendarHitTestEventResizeEnd) { return xtpCalendaDragModeResizeEnd; } } else { BOOL bIsCtrl = (GetKeyState(VK_CONTROL) < 0); return bIsCtrl ? xtpCalendaDragModeCopy : xtpCalendaDragModeMove; } return xtpCalendaDragModeUnknown; } void CXTPCalendarView::OnStartDragging(CPoint /*point*/, XTP_CALENDAR_HITTESTINFO* pHitTest) { if (!pHitTest) return; if ((pHitTest->uHitCode & xtpCalendarHitTestEvent_Mask) == 0) return; if (IsEditingSubject()) EndEditSubject(xtpCalendarEditSubjectCommit, FALSE); m_spDraggingStartOffset.SetStatus(COleDateTimeSpan::null); m_eDraggingMode = xtpCalendaDragModeUnknown; if (!pHitTest->pViewEvent || !pHitTest->pViewEvent->GetEvent()) return; m_eDraggingMode = _GetDraggingMode(pHitTest); ASSERT(m_eDraggingMode != xtpCalendaDragModeUnknown); if (_IsDragModeCopyMove(m_eDraggingMode)) { if (pHitTest->bTimePartValid) { m_spDraggingStartOffset = pHitTest->dt - pHitTest->pViewEvent->GetEvent()->GetStartTime(); } else { m_spDraggingStartOffset = CXTPCalendarUtils::ResetTime(pHitTest->dt) - CXTPCalendarUtils::ResetTime(pHitTest->pViewEvent->GetEvent()->GetStartTime()); } if (!m_nKeyStateTimerID) m_nKeyStateTimerID = SetTimer(50); } //--------------------------------------------------------------------------- VERIFY(SetDraggingEvent(pHitTest->pViewEvent->GetEvent())); } BOOL CXTPCalendarView::OnEndDragging(CPoint point, XTP_CALENDAR_HITTESTINFO* /*phitInfo*/) { if (!m_ptrDraggingEventNew || !m_ptrDraggingEventOrig || m_eDraggingMode == xtpCalendaDragModeEditSubject) { return FALSE; } CXTPCalendarEventPtr ptrEventToSelect = m_ptrDraggingEventNew; BOOL bChanged = CommitDraggingEvent(); int nDragMode = m_eDraggingMode; m_eDraggingMode = xtpCalendaDragModeUnknown; if (bChanged && GetCalendarControl()) GetCalendarControl()->Populate(); UnselectAllEvents(); if (_IsDragModeCopyMove(nDragMode)) EmptyUndoBuffer(); if (ptrEventToSelect && (nDragMode == xtpCalendaDragModeResizeBegin || nDragMode == xtpCalendaDragModeResizeEnd)) { CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw); COleDateTime dtFVDate = GetDateTimeDay(ptrEventToSelect->GetStartTime(), ptrEventToSelect->IsAllDayEvent()); if (nDragMode == xtpCalendaDragModeResizeEnd) dtFVDate = CXTPCalendarUtils::RetriveEventEndDate(ptrEventToSelect); CXTPCalendarViewEvent* pViewEvent = FindViewEvent(ptrEventToSelect, dtFVDate); if (pViewEvent && pViewEvent->GetEvent()) { SelectDay(XTP_SAFE_GET2(pViewEvent, GetViewGroup_(), GetViewDay_(), NULL), XTP_SAFE_GET2(pViewEvent, GetViewGroup_(), GetGroupIndex(), -1)); BOOL bEnabled = XTP_SAFE_GET1(GetCalendarOptions(), bEnableInPlaceEditEventSubject_AfterEventResize, FALSE); if (bEnabled) bEnabled = !OnBeforeEditOperationNotify(xtpCalendarEO_EditSubject_AfterEventResize, pViewEvent); BOOL bNo = pViewEvent->GetEvent()->GetDurationMinutes() < 1440; if (bEnabled && bNo) StartEditSubject(pViewEvent); else SelectEvent(pViewEvent->GetEvent()); } } SelectEvent(ptrEventToSelect); return TRUE; } CXTPCalendarViewEvent* CXTPCalendarView::FindViewEvent(CXTPCalendarEvent* pEvent, COleDateTime dtDay) const { if (!pEvent) { ASSERT(FALSE); return NULL; } dtDay = CXTPCalendarUtils::ResetTime(dtDay); CXTPCalendarViewEvent* pFEView = NULL; BOOL bFDayProceessed = FALSE; int nCount = GetViewDayCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarViewDay* pViewDay = GetViewDay_(i); if (!pViewDay) { ASSERT(FALSE); continue; } COleDateTime dtDayDate = pViewDay->GetDayDate(); int nGroupsCount = pViewDay->GetViewGroupsCount(); for (int g = 0; g < nGroupsCount; g++) { CXTPCalendarViewGroup* pViewGroup = pViewDay->GetViewGroup_(g); ASSERT(pViewGroup); if (!pViewGroup) { continue; } int nECount = pViewGroup->GetViewEventsCount(); for (int j = 0; j < nECount; j++) { CXTPCalendarViewEvent* pViewEvent = pViewGroup->GetViewEvent_(j); CXTPCalendarEvent* pEv = pViewEvent ? pViewEvent->GetEvent() : NULL; if (!pEv) { ASSERT(FALSE); continue; } if (pEvent->IsEqualIDs(pEv) && pEvent->IsEqualStartEnd(pEv)) { if (pViewEvent->IsVisible()) { pFEView = pViewEvent; } if (CXTPCalendarUtils::IsEqual(dtDay, dtDayDate)) { bFDayProceessed = TRUE; } if (pFEView && bFDayProceessed) { return pFEView; } } } } } return NULL; } CXTPCalendarViewEvent* CXTPCalendarView::FindViewEventByGroup(CXTPCalendarEvent* pEvent, COleDateTime dtDay, int nScheduleID) const { if (!pEvent) { ASSERT(FALSE); return NULL; } dtDay = CXTPCalendarUtils::ResetTime(dtDay); CXTPCalendarViewEvent* pFEView = NULL; BOOL bFDayProceessed = FALSE; int nCount = GetViewDayCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarViewDay* pViewDay = GetViewDay_(i); if (!pViewDay) { ASSERT(FALSE); continue; } COleDateTime dtDayDate = pViewDay->GetDayDate(); int nGroupsCount = pViewDay->GetViewGroupsCount(); if (nScheduleID < nGroupsCount) { CXTPCalendarViewGroup* pViewGroup = pViewDay->GetViewGroup_(nScheduleID); ASSERT(pViewGroup); if (!pViewGroup) { continue; } int nECount = pViewGroup->GetViewEventsCount(); for (int j = 0; j < nECount; j++) { CXTPCalendarViewEvent* pViewEvent = pViewGroup->GetViewEvent_(j); CXTPCalendarEvent* pEv = pViewEvent ? pViewEvent->GetEvent() : NULL; if (!pEv) { ASSERT(FALSE); continue; } if (pEvent->IsEqualIDs(pEv) && pEvent->IsEqualStartEnd(pEv)) { if (pViewEvent->IsVisible()) { pFEView = pViewEvent; } if (CXTPCalendarUtils::IsEqual(dtDay, dtDayDate)) { bFDayProceessed = TRUE; } if (pFEView && bFDayProceessed) { return pFEView; } } } } } return NULL; } BOOL CXTPCalendarView::HasSelectedViewEvent() const { if (!m_pSelectedEvents) { return FALSE; } return m_pSelectedEvents->GetCount() > 0; } CXTPCalendarViewEvents* CXTPCalendarView::GetSelectedViewEvents() const { return m_pSelectedEvents; } BOOL CXTPCalendarView::IsSingleEventSelected() const { int nCount = m_pSelectedEvents ? m_pSelectedEvents->GetCount() : 0; if (nCount == 0) return FALSE; if (nCount == 1) return TRUE; CXTPCalendarEvent* pEvent = m_pSelectedEvents->GetAt(0)->GetEvent(); for (int i = 0; i < nCount; i++) { CXTPCalendarViewEvent* pViewEvent = m_pSelectedEvents->GetAt(i); ASSERT(pViewEvent); if (pViewEvent && !pViewEvent->GetEvent()->IsEqualIDs(pEvent)) return FALSE; } return TRUE; } CXTPCalendarViewEventsPtr CXTPCalendarView::GetSelectedEvents() const { CXTPCalendarViewEventsPtr ptrEventsWithViews = new CXTPCalendarViewEvents(); CXTPCalendarEvents arEvents; ASSERT(m_pSelectedEvents); if (!ptrEventsWithViews || !m_pSelectedEvents) { return NULL; } int nCount = m_pSelectedEvents->GetCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarViewEvent* pViewEvent = m_pSelectedEvents->GetAt(i); CXTPCalendarEvent* pEvent = pViewEvent ? pViewEvent->GetEvent() : NULL; if (pEvent && arEvents.Find(pEvent) < 0) { arEvents.Add(pEvent, TRUE); ptrEventsWithViews->Add(pViewEvent, TRUE); } } return ptrEventsWithViews; } BOOL CXTPCalendarView::GetSelection(COleDateTime* pBegin, COleDateTime* pEnd, BOOL* pbAllDayEvent, int* pnGroupIndex, COleDateTimeSpan* pspSelectionResolution) const { if (!m_selectedBlock.IsValid()) { return FALSE; } if (pspSelectionResolution) { *pspSelectionResolution = COleDateTimeSpan(1, 0, 0, 0); } if (pbAllDayEvent) { *pbAllDayEvent = TRUE; } if (pnGroupIndex) { *pnGroupIndex = m_selectedBlock.nGroupIndex; } //--------------------------------------------------------------------------- if (pBegin) { *pBegin = min(m_selectedBlock.dtBegin, m_selectedBlock.dtEnd); } if (pEnd) { *pEnd = max(m_selectedBlock.dtBegin, m_selectedBlock.dtEnd) + COleDateTimeSpan(1, 0, 0, 0); } return TRUE; } void CXTPCalendarView::SetSelection(const COleDateTime& dtBegin, const COleDateTime& dtEnd, BOOL bAllDayEvent, int nGroupIndex) { m_selectedBlock.dtBegin = dtBegin; m_selectedBlock.dtEnd = dtEnd; m_selectedBlock.bAllDayEvent = bAllDayEvent; m_selectedBlock.nGroupIndex = nGroupIndex; CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays); } void CXTPCalendarView::ResetSelection() { if (IsEditingSubject()) { CXTPCalendarEventPtr ptrEditingEvent(m_ptrDraggingEventOrig, TRUE); EndEditSubject(xtpCalendarEditSubjectCancel); } m_selectedBlock.dtBegin.SetStatus(COleDateTime::null); m_selectedBlock.dtEnd.SetStatus(COleDateTime::null); m_selectedBlock.bAllDayEvent = FALSE; m_selectedBlock.nGroupIndex = -1; CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays); } BOOL CXTPCalendarView::SelectionContains(COleDateTime date, int nGroupIndex, BOOL* pbAllDaySelection) { COleDateTime dtBegin; COleDateTime dtEnd; int nSelGroupIndex; if (GetSelection(&dtBegin, &dtEnd, pbAllDaySelection, &nSelGroupIndex)) { if (nGroupIndex < 0 || nGroupIndex == nSelGroupIndex) { return (dtBegin <= date && (double)date <= (double)dtEnd - XTP_HALF_SECOND); } } return FALSE; } COleDateTime CXTPCalendarView::GetNextTimeEditByTAB() const { ASSERT(GetViewDayCount() != 0); COleDateTime dtDay; if (m_selectedBlock.dtEnd.GetStatus() == COleDateTime::valid) { dtDay = m_selectedBlock.dtEnd; } else { dtDay = GetViewDayDate(0); } dtDay = CXTPCalendarUtils::ResetTime(dtDay); return dtDay; } void CXTPCalendarView::UpdateNextTimeEditByTAB(COleDateTime dtNext, BOOL /*bReverse*/, BOOL /*bReset*/) { COleDateTime dtNextDay = CXTPCalendarUtils::ResetTime(dtNext); COleDateTime dtCurrDay = CXTPCalendarUtils::ResetTime(GetNextTimeEditByTAB()); if (dtNextDay != dtCurrDay) { SelectDay(dtNextDay); } } CXTPCalendarViewEvent* CXTPCalendarView::FindEventToEditByTAB(COleDateTime dtMinStart, BOOL bReverse, CXTPCalendarEvent* pAfterEvent) { COleDateTime dtMinStartDay = CXTPCalendarUtils::ResetTime(dtMinStart); COleDateTime dtMinStart2 = dtMinStartDay + COleDateTimeSpan(1, 0, 0, 0); BOOL bAfterEventWas = pAfterEvent == NULL; if (pAfterEvent) { COleDateTime dtAEStartDay = GetDateTimeDay(pAfterEvent->GetStartTime(), pAfterEvent->IsAllDayEvent()); if (bReverse ? dtAEStartDay > dtMinStartDay : dtAEStartDay < dtMinStartDay) { bAfterEventWas = TRUE; } } int nDays = GetViewDayCount(); for (int nDay = bReverse ? nDays-1 : 0; bReverse ? nDay >= 0 : nDay < nDays; bReverse ? nDay-- : nDay++) { CXTPCalendarViewDay* pVDay = GetViewDay_(nDay); if (!pVDay) { ASSERT(FALSE); continue; } COleDateTime dtDay = pVDay->GetDayDate(); if (bReverse ? dtDay > dtMinStartDay : dtDay < dtMinStartDay) { continue; } int nGroupsCount = pVDay->GetViewGroupsCount(); for (int nGroup = bReverse ? nGroupsCount - 1 : 0; bReverse ? nGroup >= 0 : nGroup < nGroupsCount; bReverse ? nGroup-- : nGroup++) { CXTPCalendarViewGroup* pViewGroup = pVDay->GetViewGroup_(nGroup); ASSERT(pViewGroup); if (!pViewGroup) { continue; } int nEvents = pViewGroup->GetViewEventsCount(); for (int nEvent = bReverse ? nEvents - 1 : 0; bReverse ? nEvent >= 0 : nEvent < nEvents; bReverse ? nEvent-- : nEvent++) { CXTPCalendarViewEvent* pVEvent = pViewGroup->GetViewEvent_(nEvent); if (!pVEvent || !pVEvent->GetEvent()) { ASSERT(FALSE); continue; } if (pAfterEvent) { if (pAfterEvent->IsEqualIDs(pVEvent->GetEvent())) { bAfterEventWas = TRUE; continue; } } COleDateTime dtES = pVEvent->GetEvent()->GetStartTime(); COleDateTime dtESDay = GetDateTimeDay(dtES, pVEvent->GetEvent()->IsAllDayEvent()); if (bReverse ? (dtES > dtMinStart2 || dtESDay != dtDay) : (dtES < dtMinStart || dtESDay < dtDay)) { continue; } if (bAfterEventWas) { return pVEvent; } } } } return NULL; } void CXTPCalendarView::UnselectAllEvents() { if (!m_pSelectedEvents || !GetCalendarControl()) { return; } int nCount = m_pSelectedEvents->GetCount(); m_pSelectedEvents->RemoveAll(); if (nCount) { CXTPCalendarControl::CUpdateContext updateContext(GetCalendarControl(), xtpCalendarUpdateRedraw); CSelectionChangedContext selChanged(this, xtpCalendarSelectionEvents); } } void CXTPCalendarView::_ReSelectSelectEvents() { if (!m_pSelectedEvents) return; CXTPCalendarViewEventsPtr ptrSelEvents = GetSelectedEvents(); m_pSelectedEvents->RemoveAll(); CXTPCalendarEvent* pEvent; if (ptrSelEvents) { int nCount = ptrSelEvents->GetCount(); for (int i = 0; i < nCount; i++) { if (ptrSelEvents->GetAt(i)) { pEvent = ptrSelEvents->GetAt(i)->GetEvent(); if (pEvent) SelectEvent(pEvent); } } } } void CXTPCalendarView::SelectDays(COleDateTime dtNewSel) { CXTPCalendarControl::CUpdateContext updateContext(GetCalendarControl(), xtpCalendarUpdateRedraw); m_selectedBlock.dtEnd = dtNewSel; CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays); } void CXTPCalendarView::SelectDay(COleDateTime dtSelDay, int nGroupIndex) { CXTPCalendarControl::CUpdateContext updateContext(GetCalendarControl(), xtpCalendarUpdateRedraw); m_selectedBlock.dtBegin = m_selectedBlock.dtEnd = dtSelDay; m_selectedBlock.nGroupIndex = nGroupIndex; CSelectionChangedContext selChanged(this, xtpCalendarSelectionDays); } void CXTPCalendarView::SelectDay(CXTPCalendarViewDay* pDay, int nGroupIndex) { ASSERT(pDay); if (pDay) { SelectDay(pDay->GetDayDate(), nGroupIndex); } } void CXTPCalendarView::SelectViewEvent(CXTPCalendarViewEvent* pViewEvent, BOOL bSelect) { if (!m_pSelectedEvents || !pViewEvent || !pViewEvent->GetEvent()) { ASSERT(FALSE); return; } m_pSelectedEvents->Remove(pViewEvent->GetEvent()); if (bSelect) { pViewEvent->InternalAddRef(); m_pSelectedEvents->Add(pViewEvent); } CSelectionChangedContext selChanged(this, xtpCalendarSelectionEvents); } CXTPCalendarViewEvent* CXTPCalendarView::GetLastSelectedViewEvent() const { if (m_pSelectedEvents && m_pSelectedEvents->GetCount() > 0) return m_pSelectedEvents->GetAt(m_pSelectedEvents->GetCount() - 1); return NULL; } void CXTPCalendarView::SelectEvent(CXTPCalendarEvent* pEvent, BOOL bSelect) { if (!pEvent) { ASSERT(FALSE); return; } int nCount = GetViewDayCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarViewDay* pViewDay = GetViewDay_(i); if (!pViewDay) { ASSERT(FALSE); continue; } int nGroupsCount = pViewDay->GetViewGroupsCount(); for (int g = 0; g < nGroupsCount; g++) { CXTPCalendarViewGroup* pViewGroup = pViewDay->GetViewGroup_(g); ASSERT(pViewGroup); if (!pViewGroup) { continue; } int nECount = pViewGroup->GetViewEventsCount(); for (int j = 0; j < nECount; j++) { CXTPCalendarViewEvent* pViewEvent = pViewGroup->GetViewEvent_(j); CXTPCalendarEvent* pEv = pViewEvent ? pViewEvent->GetEvent() : NULL; ASSERT(pEv); if (pEv && pEvent->IsEqualIDs(pEv) && pEvent->IsEqualStartEnd(pEv)) { CXTPCalendarControl::CUpdateContext updateContext(GetCalendarControl(), xtpCalendarUpdateRedraw); SelectViewEvent(pViewEvent, bSelect); } } } } } BOOL CXTPCalendarView::OnDragging(CPoint /*point*/, XTP_CALENDAR_HITTESTINFO* pHitTest) { ASSERT(pHitTest); if (!pHitTest || !m_ptrDraggingEventNew || m_eDraggingMode == xtpCalendaDragModeEditSubject) { return FALSE; } //--------------------------------------------------------------------------- if (pHitTest->pViewDay) { if (m_eDraggingMode == xtpCalendaDragModeResizeBegin || m_eDraggingMode == xtpCalendaDragModeResizeEnd) { SelectDay(pHitTest->pViewDay, pHitTest->nGroup); } } //--------------------------------------------------------------------------- COleDateTime dtNewTime; if (_IsDragModeCopyMove(m_eDraggingMode)) { if (!pHitTest->bTimePartValid) { dtNewTime = CXTPCalendarUtils::UpdateDate(m_ptrDraggingEventNew->GetStartTime(), pHitTest->dt); } else { dtNewTime = pHitTest->dt; } dtNewTime -= m_spDraggingStartOffset; BOOL bChanged = FALSE; //------------------------------------ if (!CXTPCalendarUtils::IsEqual(dtNewTime, m_ptrDraggingEventNew->GetStartTime())) { m_ptrDraggingEventNew->MoveEvent(dtNewTime); bChanged = TRUE; } //*** if (bChanged) { return TRUE; } } else if (m_eDraggingMode == xtpCalendaDragModeResizeBegin) { dtNewTime = pHitTest->dt; COleDateTime dtEventEnd = m_ptrDraggingEventNew->GetEndTime(); if (!CXTPCalendarUtils::IsEqual(dtNewTime, m_ptrDraggingEventNew->GetStartTime())) { if (dtNewTime > dtEventEnd) { dtNewTime = dtEventEnd; } m_ptrDraggingEventNew->SetStartTime(dtNewTime); BOOL bIsZeroStartEnd = CXTPCalendarUtils::IsZeroTime(m_ptrDraggingEventNew->GetStartTime()) && CXTPCalendarUtils::IsZeroTime(m_ptrDraggingEventNew->GetEndTime()); BOOL bIsZeroLen = CXTPCalendarUtils::IsEqual(m_ptrDraggingEventNew->GetStartTime(), m_ptrDraggingEventNew->GetEndTime()); m_ptrDraggingEventNew->SetAllDayEvent(bIsZeroStartEnd && !bIsZeroLen); return TRUE; } } else if (m_eDraggingMode == xtpCalendaDragModeResizeEnd) { dtNewTime = pHitTest->dt; if (!pHitTest->bTimePartValid) { dtNewTime += COleDateTimeSpan(1, 0, 0, 0); } COleDateTime dtEventStart = m_ptrDraggingEventNew->GetStartTime(); if (!CXTPCalendarUtils::IsEqual(dtNewTime, m_ptrDraggingEventNew->GetEndTime())) { if ((pHitTest->uHitCode & xtpCalendarHitTestDayViewTimeScale) && (pHitTest->pViewDay == NULL)) { dtNewTime.SetDateTime( dtEventStart.GetYear(), dtEventStart.GetMonth(), dtEventStart.GetDay(), dtNewTime.GetHour(), dtNewTime.GetMinute(), dtNewTime.GetSecond()); } if (dtNewTime < dtEventStart) { dtNewTime = dtEventStart; } m_ptrDraggingEventNew->SetEndTime(dtNewTime); BOOL bIsZeroStartEnd = CXTPCalendarUtils::IsZeroTime(m_ptrDraggingEventNew->GetStartTime()) && CXTPCalendarUtils::IsZeroTime(m_ptrDraggingEventNew->GetEndTime()); BOOL bIsZeroLen = CXTPCalendarUtils::IsEqual(m_ptrDraggingEventNew->GetStartTime(), m_ptrDraggingEventNew->GetEndTime()); m_ptrDraggingEventNew->SetAllDayEvent(bIsZeroStartEnd && !bIsZeroLen); return TRUE; } } return FALSE; } COleDateTime CXTPCalendarView::GetLastSelectedDate() const { if (m_selectedBlock.dtEnd.GetStatus() != COleDateTime::valid) { return GetViewDayDate(GetViewDayCount() / 2); } return CXTPCalendarUtils::ResetTime(m_selectedBlock.dtEnd); } int CXTPCalendarView::FindLastSelectedDay() const { COleDateTime dt = GetLastSelectedDate(); int nCount = GetViewDayCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarViewDay* pViewDay = GetViewDay_(i); ASSERT(pViewDay); if (pViewDay && CXTPCalendarUtils::IsEqual(pViewDay->GetDayDate(), dt)) return i; } return -1; } void CXTPCalendarView::ProcessDaySelection(XTP_CALENDAR_HITTESTINFO* pInfo, UINT nFlags) { ASSERT(pInfo); if (!pInfo) { UnselectAllEvents(); return; } if (nFlags & MK_SHIFT) { COleDateTime dtNewSelDay = GetViewDayDate(pInfo->nDay); SelectDays(dtNewSelDay); } else { UnselectAllEvents(); ASSERT(pInfo->pViewDay); if (pInfo->pViewDay) { pInfo->pViewDay->SetSelected(); } } } void CXTPCalendarView::ProcessEventSelection(XTP_CALENDAR_HITTESTINFO* pInfo, UINT nFlags) { ASSERT(pInfo); if (!pInfo) { return; } BOOL bUnselectEvents = !(nFlags & (MK_SHIFT | MK_CONTROL)); if (bUnselectEvents) UnselectAllEvents(); ASSERT(pInfo->pViewDay); ASSERT(pInfo->pViewEvent); if (pInfo->pViewDay) { pInfo->pViewDay->SetSelected(); } if (pInfo->pViewEvent) { BOOL bSelect = TRUE; if (nFlags & MK_CONTROL) { bSelect = !pInfo->pViewEvent->IsSelected(); } SelectEvent(pInfo->pViewEvent->GetEvent(), bSelect); } } UINT CXTPCalendarView::SetTimer(UINT uTimeOut_ms) { if (GetCalendarControl()) { return GetCalendarControl()->SetTimer(uTimeOut_ms); } return 0; } void CXTPCalendarView::KillTimer(UINT uTimerID) { if (GetCalendarControl()) { VERIFY(GetCalendarControl()->KillTimer(uTimerID)); } } BOOL CXTPCalendarView::OnTimer(UINT_PTR uTimerID) { if (TBase::OnTimer(uTimerID)) { return TRUE; } CXTPCalendarThemeOffice2007* pThemeX = DYNAMIC_DOWNCAST(CXTPCalendarThemeOffice2007, GetTheme()); if (pThemeX) { if (pThemeX->OnTimer(uTimerID)) return TRUE; } if (uTimerID == m_nTimerID_StartEditSubject) { KillTimer(m_nTimerID_StartEditSubject); m_nTimerID_StartEditSubject = 0; ASSERT(m_ptrEditingViewEvent); if (m_ptrEditingViewEvent) { EmptyUndoBuffer(); StartEditSubject(m_ptrEditingViewEvent); } return TRUE; } else if (uTimerID == m_nKeyStateTimerID) { BOOL bIsCtrl = (GetKeyState(VK_CONTROL) < 0); XTPCalendarDraggingMode eDraggingMode = bIsCtrl ? xtpCalendaDragModeCopy : xtpCalendaDragModeMove; BOOL bPopulate = FALSE; if (!_IsDragModeCopyMove(m_eDraggingMode)) { KillTimer(m_nKeyStateTimerID); m_nKeyStateTimerID = 0; } else if (m_eDraggingMode != eDraggingMode) { ASSERT(m_ptrDraggingEventNew); if (m_ptrDraggingEventNew) { CXTPCalendarViewEvent* pEventView = FindViewEvent(m_ptrDraggingEventNew, m_ptrDraggingEventNew->GetStartTime()); if (!IsEditOperationDisabledNotify(_DragMod2Operation(eDraggingMode), pEventView)) { m_eDraggingMode = eDraggingMode; bPopulate = TRUE; } } } if (bPopulate && GetCalendarControl()) { GetCalendarControl()->Populate(); GetCalendarControl()->m_mouseMode = m_eDraggingMode == xtpCalendaDragModeCopy ? xtpCalendarMouseEventDragCopy : xtpCalendarMouseEventDragMove; GetCalendarControl()->UpdateMouseCursor(); } return TRUE; } else if (uTimerID == m_nTimerID_ShowToolTip) { ShowToolTip(); return TRUE; } return FALSE; } BOOL CXTPCalendarView::OnLButtonDblClk(UINT nFlags, CPoint point) { if (m_nTimerID_StartEditSubject) { KillTimer(m_nTimerID_StartEditSubject); m_nTimerID_StartEditSubject = 0; m_ptrEditingViewEvent = NULL; } return TBase::OnLButtonDblClk(nFlags, point); } void CXTPCalendarView::OnDraw(CDC* pDC) { if (GetTheme()) Draw2(pDC); else Draw(pDC); } void CXTPCalendarView::AdjustLayout(CDC* pDC, const CRect& rcView, BOOL bCallPostAdjustLayout) { UNREFERENCED_PARAMETER(pDC); m_rcView = rcView; _CalculateEventTimeFormat(); if (bCallPostAdjustLayout) { OnPostAdjustLayout(); } } void CXTPCalendarView::AdjustLayout2(CDC* pDC, const CRect& rcView, BOOL bCallPostAdjustLayout) { UNREFERENCED_PARAMETER(pDC); UNREFERENCED_PARAMETER(bCallPostAdjustLayout); ASSERT(GetTheme()); m_rcView = rcView; //_CalculateEventTimeFormat(); // if (bCallPostAdjustLayout) // { // OnPostAdjustLayout(); // } } CXTPCalendarViewDay* CXTPCalendarView::_GetViewDay(const COleDateTime& dt) const { COleDateTime dtDay = CXTPCalendarUtils::ResetTime(dt); int nDaysCount = GetViewDayCount(); if (!nDaysCount || !GetViewDay_(0)) { return NULL; } COleDateTime dtDay0 = GetViewDay_(0)->GetDayDate(); COleDateTimeSpan spShift = dtDay - dtDay0; ASSERT((double)spShift == (double)((int)(double)spShift) ); int nShift = CXTPCalendarUtils::GetTotalDays(spShift); //(int)(double)spShift if (nShift < 0) { nShift = 0; } if (nShift >= nDaysCount) { nShift = nDaysCount - 1; } if (nShift >= 0 && nShift < nDaysCount) { return GetViewDay_(nShift); } return NULL; } COleDateTime CXTPCalendarView::GetDateTimeDay(const COleDateTime& dt, BOOL bWholeDayEvent) const { CXTPCalendarOptions* pOptions = GetCalendarControl()->GetCalendarOptions(); if ((DATE)pOptions->dtScaleMaxTime <= 1 || bWholeDayEvent) return CXTPCalendarUtils::ResetTime(dt); return CXTPCalendarUtils::ResetTime(dt - pOptions->dtScaleMinTime); } void CXTPCalendarView::StartEditNewEventInplace(LPCTSTR pcszInitialSubject) { if (m_ptrDraggingEventOrig || m_ptrDraggingEventNew || IsEditingSubject()) { MessageBeep(0); return; } BOOL bAllDayEvent = FALSE; //--------------------------------------------------------------------------- COleDateTime dtSelBegin, dtSelEnd; int nGroup = 0; if (!GetSelection(&dtSelBegin, &dtSelEnd, &bAllDayEvent, &nGroup)) { return; } //--------------------------------------------------------------------------- CXTPCalendarData* pData = NULL; //XTP_SAFE_GET1(GetCalendarControl(), GetDataProvider(), NULL); CXTPCalendarViewDay* pViewDay = _GetViewDay(dtSelBegin); if (!pViewDay) { return; } CXTPCalendarViewGroup* pViewGroup = NULL; if (pViewDay && nGroup < pViewDay->GetViewGroupsCount()) { pViewGroup = pViewDay->GetViewGroup_(nGroup); pData = pViewGroup ? pViewGroup->GetDataProvider() : NULL; } //if (pData != NULL // && pData->GetCustomProperties() != NULL) //{ // CString sType(_T("Public")); // CString sXML(_T("F:\\SecurityType.xml")); // COleVariant rVarValue(sType); // pData->GetCustomProperties()->LoadFromXML(sXML); // if (pData->GetCustomProperties()->GetProperty(_T("SecurityType"), rVarValue)) // { // AfxMessageBox(_T("SecurityType found")); // } // else // { // AfxMessageBox(_T("SecurityType not found")); // pData->GetCustomProperties()->SetProperty(_T("SecurityType"), rVarValue); // pData->GetCustomProperties()->SaveToXML(sXML); // } //} m_ptrDraggingEventNew = pData ? pData->CreateNewEvent() : NULL; if (!m_ptrDraggingEventNew) { return; } //--------------------------------------------------------------------------- UINT uScheduleID = XTP_SAFE_GET1(pViewGroup, GetScheduleID(), 0); m_ptrDraggingEventNew->SetScheduleID(uScheduleID); m_ptrDraggingEventNew->SetStartTime(min(dtSelBegin, dtSelEnd)); m_ptrDraggingEventNew->SetEndTime(max(dtSelBegin, dtSelEnd)); m_ptrDraggingEventNew->SetBusyStatus(bAllDayEvent ? xtpCalendarBusyStatusFree : xtpCalendarBusyStatusBusy); m_ptrDraggingEventNew->SetAllDayEvent(bAllDayEvent); //=========================================================================== XTP_SAFE_CALL1(GetCalendarControl(), Populate()); XTP_SAFE_CALL1(GetCalendarControl(), AdjustLayout()); //--------------------------------------------------------------------------- COleDateTime dtEventDay = m_ptrDraggingEventNew->GetStartTime(); dtEventDay = GetDateTimeDay(dtEventDay, m_ptrDraggingEventNew->IsAllDayEvent()); CXTPCalendarViewEvent* pViewEvent = FindViewEvent(m_ptrDraggingEventNew, dtEventDay); if (!pViewEvent) { CancelDraggingEvent(); return; } StartEditSubject(pViewEvent); CEdit* pEditor = DYNAMIC_DOWNCAST(CEdit, pViewEvent->GetSubjectEditor()); if (pEditor) { pEditor->SetWindowText(pcszInitialSubject); int nInitTxtLen = (int)_tcsclen(pcszInitialSubject); pEditor->SetSel(nInitTxtLen, nInitTxtLen); } } void CXTPCalendarView::StartEditSubject(CXTPCalendarViewEvent* pViewEvent) { if (!pViewEvent) return; if (m_nTimerID_StartEditSubject) { KillTimer(m_nTimerID_StartEditSubject); m_nTimerID_StartEditSubject = 0; } m_ptrEditingViewEvent = pViewEvent->StartEditSubject(); if (!m_ptrEditingViewEvent) return; CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateRedraw); m_ptrEditingViewEvent->InternalAddRef(); m_eDraggingMode = xtpCalendaDragModeEditSubject; if (!m_ptrDraggingEventOrig && !m_ptrDraggingEventNew) SetDraggingEvent(m_ptrEditingViewEvent->GetEvent()); SelectEvent(m_ptrDraggingEventNew); } void CXTPCalendarView::EndEditSubject(XTPCalendarEndEditSubjectAction eAction, BOOL bUpdateControl) { m_eDraggingMode = xtpCalendaDragModeUnknown; // kill timeout request to edit subject if (m_nTimerID_StartEditSubject) { ASSERT(m_ptrEditingViewEvent && !m_ptrDraggingEventOrig && !m_ptrDraggingEventNew); KillTimer(m_nTimerID_StartEditSubject); m_nTimerID_StartEditSubject = 0; m_ptrEditingViewEvent = NULL; return; } ASSERT(m_ptrEditingViewEvent && m_ptrDraggingEventNew); CXTPCalendarEventPtr ptrEventToSelect(m_ptrDraggingEventNew, TRUE); BOOL bPopulate = FALSE; CString strNewSubject; //- end edit subject operation in Event view (kill edit wnd) ---------------- if (m_ptrEditingViewEvent) strNewSubject = m_ptrEditingViewEvent->EndEditSubject(); m_ptrEditingViewEvent = NULL; //--------------------------------------------------------------------------- if (m_ptrDraggingEventNew) { if (eAction == xtpCalendarEditSubjectCommit) { m_ptrDraggingEventNew->SetSubject(strNewSubject); if (!strNewSubject.IsEmpty()) bPopulate = CommitDraggingEvent(); else { ptrEventToSelect.SetPtr(m_ptrDraggingEventOrig, TRUE); CancelDraggingEvent(); bPopulate = TRUE; } } else if (eAction == xtpCalendarEditSubjectCancel) { ptrEventToSelect.SetPtr(m_ptrDraggingEventOrig, TRUE); CancelDraggingEvent(); bPopulate = TRUE; } else { ASSERT(FALSE); } } if (bUpdateControl && bPopulate && GetCalendarControl()) { GetCalendarControl()->Populate(); if (ptrEventToSelect) { SelectEvent(ptrEventToSelect, TRUE); } } } void CXTPCalendarView::OnUpdateEditingSubject(CString strNewSubject) { if (m_ptrEditingViewEvent && m_ptrDraggingEventNew) m_ptrDraggingEventNew->SetSubject(strNewSubject); } CRect CXTPCalendarView::GetSubjectEditorRect() const { ASSERT(m_ptrEditingViewEvent); if (m_ptrEditingViewEvent) { return m_ptrEditingViewEvent->GetSubjectEditorRect(); } return CRect(INT_MAX, INT_MAX, INT_MAX, INT_MAX); } CRect CXTPCalendarView::GetTooltipRect(const CPoint& ptHit, const XTP_CALENDAR_HITTESTINFO& hitInfo) const { CRect rcTip; rcTip.SetRectEmpty(); if (hitInfo.pViewGroup) { rcTip = hitInfo.pViewGroup->GetTooltipRect(ptHit, hitInfo); CXTPCalendarThemeOffice2007* pThemeX = DYNAMIC_DOWNCAST(CXTPCalendarThemeOffice2007, GetTheme()); if (pThemeX) { CRect rcExclude = XTP_SAFE_GET2(pThemeX->GetPrevNextEventButtonsPartX(), GetNextEventButtonPartX(), GetRect(), CRect(0, 0, 0, 0)); if (!(rcTip.top > rcExclude.bottom || rcTip.bottom < rcExclude.top) && rcTip.right >= rcExclude.left) { rcTip.right = rcExclude.left - 1; } rcExclude = XTP_SAFE_GET2(pThemeX->GetPrevNextEventButtonsPartX(), GetPrevEventButtonPartX(), GetRect(), CRect(0, 0, 0, 0)); if (!(rcTip.top > rcExclude.bottom || rcTip.bottom < rcExclude.top) && rcTip.left <= rcExclude.right) { rcTip.left = rcExclude.right + 1; } } } return rcTip; } void CXTPCalendarView::ShowToolTip(BOOL bShow) { if (m_nTimerID_ShowToolTip) { KillTimer(m_nTimerID_ShowToolTip); m_nTimerID_ShowToolTip = 0; } CXTPCalendarControl* pControl = GetCalendarControl(); if (!pControl) return; if (!bShow) { // hide a tooltip pControl->HideToolTip(); return; } if (pControl->IsToolTipVisible()) { return; } // Verify whether mouse is still under tooltip rect CRect rcTooltip; rcTooltip.SetRectEmpty(); CPoint pt; GetCursorPos(&pt); pControl->ScreenToClient(&pt); XTP_CALENDAR_HITTESTINFO hitInfo; BOOL bHitTest = HitTest(pt, &hitInfo); if (bHitTest) { rcTooltip = GetTooltipRect(pt, hitInfo); } if (m_rcTooltip != rcTooltip) m_rcTooltip.SetRectEmpty(); if (m_rcTooltip.IsRectEmpty()) return; CString strTip; if (GetViewType() != xtpCalendarTimeLineView) { // if we are under event view -- do not show this tooltip if (NULL != hitInfo.pViewEvent) return; BOOL bTipEnabled = XTP_SAFE_GET2(pControl, GetCalendarOptions(), bEnableAddNewTooltip, TRUE); BOOL bAllowCreate = XTP_SAFE_GET2(pControl, GetCalendarOptions(), bEnableInPlaceCreateEvent, TRUE); if (!bTipEnabled || !bAllowCreate) return; // create tooltip text if (!pControl->m_bReadOnlyMode) strTip = XTP_SAFE_GET2(pControl, GetCalendarOptions(), strTooltipAddNewText, _T("Click to add appointment")); else strTip.Empty(); } else if (hitInfo.pViewEvent) //TimeLine mode { if (hitInfo.pViewEvent->GetEvent() && hitInfo.pViewEvent->GetEvent()->IsEventVisible()) strTip = hitInfo.pViewEvent->GetEvent()->GetSubject(); } // show tooltip window if (pControl) { CFont* pFont = &XTP_SAFE_GET2(GetPaintManager(), GetDayViewEventPart(), GetTextFont(), *((CFont*)(NULL))); pControl->ShowToolTip(strTip, m_rcTooltip, pFont, TRUE); } } void CXTPCalendarView::_CalculateEventTimeFormat() { //////////////////////////////////////////////////////////////////////////// // LOCALE_STIME // time separator // // LOCALE_ITLZERO //leading zeros in time field // 0 No leading zeros for hours. // 1 Leading zeros for hours. // // LOCALE_ITIME // time format specifier // 0 AM / PM 12-hour format. // 1 24-hour format. // // LOCALE_ITIMEMARKPOSN // time marker position // 0 Use as suffix. // 1 Use as prefix. // // LOCALE_S1159 // AM designator // LOCALE_S2359 // PM designator //////////////////////////////////////////////////////////////////////////// if(m_EventTimeFormat.isCustom == TRUE) return; CString strTmp; CString strTimeSeparator = CXTPCalendarUtils::GetLocaleString(LOCALE_STIME, 16); strTmp = CXTPCalendarUtils::GetLocaleString(LOCALE_ITIME, 16); BOOL b24_HFormat = _ttoi(strTmp) == 1; strTmp = CXTPCalendarUtils::GetLocaleString(LOCALE_ITLZERO, 16); BOOL bH_LZero = _ttoi(strTmp) == 1; strTmp = CXTPCalendarUtils::GetLocaleString(LOCALE_ITIMEMARKPOSN, 16); BOOL bAM_PM_Prefix = _ttoi(strTmp) == 1; //--------------------------------------------------------------------------- CString strTimeFormat; strTimeFormat += strTimeSeparator; strTimeFormat += _T("mm"); if (b24_HFormat) { strTmp = bH_LZero ? _T("HH") : _T("H"); strTimeFormat = strTmp + strTimeFormat; } else //12 AM/PM Format { strTmp = bH_LZero ? _T("hh") : _T("h"); strTimeFormat = strTmp + strTimeFormat; if (bAM_PM_Prefix) { strTimeFormat = _T("tt ") + strTimeFormat; } else { strTimeFormat = strTimeFormat + _T("tt"); } } //--------------------------------------------------------------------------- m_EventTimeFormat.strFormat = strTimeFormat; m_EventTimeFormat.b24_HFormat = b24_HFormat; m_EventTimeFormat.strAM = CXTPCalendarUtils::GetLocaleString(LOCALE_S1159, 20); m_EventTimeFormat.strPM = CXTPCalendarUtils::GetLocaleString(LOCALE_S2359, 20); } CString CXTPCalendarView::FormatEventTime(COleDateTime dtTime) const { CString strTime; SYSTEMTIME st; ZeroMemory(&st, sizeof(st)); if (CXTPCalendarUtils::GetAsSystemTime(dtTime, st)) { strTime = CXTPCalendarUtils::GetTimeFormat(&st, m_EventTimeFormat.strFormat); } if (strTime.IsEmpty()) { ASSERT(FALSE); strTime.Format(_T("%d:%02d"), dtTime.GetHour(), dtTime.GetMinute()); } //- make AM/PM as lower case --------------------------------------- if (!m_EventTimeFormat.b24_HFormat) { CString strAM_lower = m_EventTimeFormat.strAM; CString strPM_lower = m_EventTimeFormat.strPM; strAM_lower.MakeLower(); strPM_lower.MakeLower(); strTime.Replace(m_EventTimeFormat.strAM, strAM_lower); strTime.Replace(m_EventTimeFormat.strPM, strPM_lower); } return strTime; } void CXTPCalendarView::SetCustomTimeFormat(const CString& strFormat) { m_EventTimeFormat.strFormat = strFormat; m_EventTimeFormat.isCustom = TRUE; m_EventTimeFormat.b24_HFormat = TRUE; m_EventTimeFormat.strAM = _T(""); m_EventTimeFormat.strPM = _T(""); } void CXTPCalendarView::ResetCustomTimeFormat() { m_EventTimeFormat.isCustom = FALSE; _CalculateEventTimeFormat(); } CString CXTPCalendarView::GetItemTextEventTimeMax() const { COleDateTime dtTestTime; dtTestTime.SetTime(23, 59, 59); CString strTime = FormatEventTime(dtTestTime); DWORD dwFlags = GetCalendarControl()->GetAskItemTextFlags(); if (dwFlags & (xtpCalendarItemText_EventStartTimeText | xtpCalendarItemText_EventEndTimeText)) { XTP_CALENDAR_GETITEMTEXT_PARAMS objRequest; ::ZeroMemory(&objRequest, sizeof(objRequest)); objRequest.nItem = xtpCalendarItemText_EventStartTimeText /*| xtpCalendarItemText_EventEndTimeText*/; objRequest.pstrText = &strTime; GetCalendarControl()->SendNotificationAlways(XTP_NC_CALENDAR_GETITEMTEXT, (WPARAM)&objRequest, 0); } return strTime; } BOOL CXTPCalendarView::_Undo(CXTPCalendarEvent* pEvent) { if (IsEditingSubject()) EndEditSubject(xtpCalendarEditSubjectCommit); if (!GetCalendarControl()) return FALSE; CXTPAutoResetValue autoSet_UpdateCtrlNf(GetCalendarControl()->m_bUpdateWhenEventChangedNotify); autoSet_UpdateCtrlNf = FALSE; CXTPCalendarEventPtr ptrEventNew; CXTPCalendarEventPtr ptrEventOld; if (pEvent) { ptrEventNew = m_pUndoBuffer->UndoAllForEvent(pEvent); ptrEventOld = m_pUndoBuffer->RedoAllForEvent(pEvent); } else { CXTPCalendarEventPtr ptrUndoEvent = m_pUndoBuffer->GetFirstUndoEvent(); if (ptrUndoEvent) { if (m_eUndoMode == xtpCalendarUndoModeUndo) { ptrEventNew = m_pUndoBuffer->UndoAllForEvent(ptrUndoEvent); ptrEventOld = m_pUndoBuffer->RedoAllForEvent(ptrUndoEvent); m_eUndoMode = xtpCalendarUndoModeRedo; } else if (m_eUndoMode == xtpCalendarUndoModeRedo) { ptrEventNew = m_pUndoBuffer->RedoAllForEvent(ptrUndoEvent); ptrEventOld = m_pUndoBuffer->UndoAllForEvent(ptrUndoEvent); m_eUndoMode = xtpCalendarUndoModeUndo; } else { ASSERT(FALSE); return FALSE; } } } if (ptrEventNew || ptrEventOld) { CXTPCalendarControl::CUpdateContext updateContext(m_pControl, xtpCalendarUpdateLayout | xtpCalendarUpdateRedraw); if (ptrEventNew && ptrEventOld && ptrEventNew->GetDataProvider()) { VERIFY( ptrEventNew->GetDataProvider()->ChangeEvent(ptrEventNew) ); } else if (ptrEventNew && !ptrEventOld && ptrEventNew->GetDataProvider()) { VERIFY( ptrEventNew->GetDataProvider()->AddEvent(ptrEventNew) ); } else if (!ptrEventNew && ptrEventOld && ptrEventOld->GetDataProvider()) { VERIFY( ptrEventOld->GetDataProvider()->DeleteEvent(ptrEventOld) ); } XTP_SAFE_CALL1(GetCalendarControl(), Populate()); return TRUE; } return FALSE; } BOOL CXTPCalendarView::CanUndo() const { if (m_eUndoMode == xtpCalendarUndoModeUndo && m_pUndoBuffer->GetCount()) return TRUE; return _CanSubjectEditor(ID_EDIT_UNDO); } CWnd* CXTPCalendarView::_GetSubjectEditorWnd() const { if (m_ptrEditingViewEvent) return m_ptrEditingViewEvent->GetSubjectEditor(); return NULL; } BOOL CXTPCalendarView::_CanSubjectEditor(UINT idEditCmd) const { CWnd* pSEditorWnd = _GetSubjectEditorWnd(); if (!pSEditorWnd) return FALSE; CEdit* pSEditor = DYNAMIC_DOWNCAST(CEdit, pSEditorWnd); if (!pSEditor) return FALSE; BOOL bSEFocused = CWnd::GetFocus() && CWnd::GetFocus()->GetSafeHwnd() == pSEditorWnd->GetSafeHwnd(); if (!bSEFocused) return FALSE; int nSel1 = -1, nSel2 = -1; pSEditor->GetSel(nSel1, nSel2); switch (idEditCmd) { case ID_EDIT_UNDO: return pSEditor->CanUndo(); case ID_EDIT_CUT: return nSel1 < nSel2; case ID_EDIT_COPY: return nSel1 < nSel2; case ID_EDIT_PASTE: return ::IsClipboardFormatAvailable(CF_TEXT); } return FALSE; } BOOL CXTPCalendarView::CanRedo() const { return m_eUndoMode == xtpCalendarUndoModeRedo && m_pUndoBuffer->GetCount(); } BOOL CXTPCalendarView::Undo() { ASSERT(m_eUndoMode == xtpCalendarUndoModeUndo || _CanSubjectEditor(ID_EDIT_UNDO)); return _Undo(); } BOOL CXTPCalendarView::Redo() { ASSERT(m_eUndoMode == xtpCalendarUndoModeRedo); return _Undo(); } CString CXTPCalendarView::_GetMaxWidthFormat(CDC* pDC, CString strFormat, BOOL bMonth) const { if (!pDC) { ASSERT(FALSE); return _T(""); } SYSTEMTIME st; ZeroMemory(&st, sizeof(st)); st.wDay = 20; st.wMonth = 1; st.wYear = (WORD)CXTPCalendarUtils::GetCurrentTime().GetYear(); int nMax = 0; CString str; int nCount = bMonth ? 12 : 7; for (int i = 0; i < nCount; i++) { CString strResult = CXTPCalendarUtils::GetDateFormat(&st, strFormat); int nLen = pDC->GetTextExtent(strResult).cx; if (nMax < nLen) { str = strResult; nMax = nLen; } if (bMonth) st.wMonth++; else st.wDay++; } return str; } int CXTPCalendarView::_GetMaxWidth(CDC* pDC, CString strFormat) const { if (!pDC) { ASSERT(FALSE); return 1; } const TCHAR* chFormats[] = { _T("yyyy"), _T("yyy"), _T("yy"), _T("y"), _T("MMMM"), _T("MMM"), _T("dddd"), _T("ddd"), _T("dd"), _T("d") }; for (int i = 0; i < _countof(chFormats); i++) { int nPos = strFormat.Find(chFormats[i]); if (nPos >= 0) { strFormat.Replace(chFormats[i], _GetMaxWidthFormat(pDC, chFormats[i], i < 2)); } } return pDC->GetTextExtent(strFormat).cx; } void CXTPCalendarView::_RemoveYearPart(CString& strFormat) { strFormat = CXTPCalendarUtils::RemoveFormatPart(strFormat, _T('y')); } void CXTPCalendarView::_ReadDefaultHeaderFormats() { m_strDayHeaderFormatDefaultLong = CXTPCalendarUtils::GetLocaleString(LOCALE_SLONGDATE, 81); if (!GetCalendarControl()->m_bFullDateMode) _RemoveYearPart(m_strDayHeaderFormatDefaultLong); m_strDayHeaderFormatDefaultMiddle = m_strDayHeaderFormatDefaultLong; m_strDayHeaderFormatDefaultMiddle.Replace(_T("MMMM"), _T("MMM")); m_strDayHeaderFormatDefaultShort = m_strDayHeaderFormatDefaultMiddle; m_strDayHeaderFormatDefaultShort.Replace(_T("dddd"), _T("ddd")); m_strDayHeaderFormatDefaultShortest = CXTPCalendarUtils::GetLocaleString(LOCALE_SSHORTDATE, 81); if (!GetCalendarControl()->m_bFullDateMode) _RemoveYearPart(m_strDayHeaderFormatDefaultShortest); } // nLevel = 0 - Long, 1 - Middle, 2 - Short, 3 - Shortest. CString CXTPCalendarView::_GetDayHeaderFormat(int nLevel) const { switch (nLevel) { case 0: return m_strDayHeaderFormatLong.IsEmpty() ? m_strDayHeaderFormatDefaultLong : m_strDayHeaderFormatLong; case 1: return m_strDayHeaderFormatMiddle.IsEmpty() ? m_strDayHeaderFormatDefaultMiddle : m_strDayHeaderFormatMiddle; case 2: return m_strDayHeaderFormatShort.IsEmpty() ? m_strDayHeaderFormatDefaultShort : m_strDayHeaderFormatShort; case 3: return m_strDayHeaderFormatShortest.IsEmpty() ? m_strDayHeaderFormatDefaultShortest : m_strDayHeaderFormatShortest; } ASSERT(FALSE); return _T(""); } void CXTPCalendarView::CalculateHeaderFormat(CDC* pDC, int nWidth, CFont* pTextFont) { if (!GetCalendarControl() || !pTextFont || !pDC) { ASSERT(FALSE); return; } _ReadDefaultHeaderFormats(); CXTPFontDC fnt(pDC, pTextFont); int arBorder[] = {40, 35, 20, 0}; for (int i = 0; i <= 3; i++) { m_strHeaderFormat = _GetDayHeaderFormat(i); int nLen = _GetMaxWidth(pDC, m_strHeaderFormat); if (nLen < nWidth - arBorder[i]) { return; } } } COleDateTimeSpan CXTPCalendarView::GetEventDurationMin() const { return COleDateTimeSpan(0.); } BOOL CXTPCalendarView::CanCut() const { return !IsEditingSubject() && HasSelectedViewEvent() || IsEditingSubject() && _CanSubjectEditor(ID_EDIT_CUT); } BOOL CXTPCalendarView::CanCopy() const { return !IsEditingSubject() && HasSelectedViewEvent() || IsEditingSubject() && _CanSubjectEditor(ID_EDIT_COPY); } BOOL CXTPCalendarView::CanPaste() const { if (!GetSelection()) { return FALSE; } //- Register or get existing Clipboard Format ID ------------------------- UINT uCF_Event = ::RegisterClipboardFormat(XTPCALENDARCTRL_CF_EVENT); BOOL bIsEventInClipboard = ::IsClipboardFormatAvailable(uCF_Event); return !IsEditingSubject() && bIsEventInClipboard || IsEditingSubject() && _CanSubjectEditor(ID_EDIT_PASTE); } BOOL CXTPCalendarView::Cut() { if (IsEditingSubject() && _GetSubjectEditorWnd()) { if (CanCut()) { _GetSubjectEditorWnd()->SendMessage(WM_CUT); return TRUE; } return FALSE; } //=========================================================================== CXTPCalendarViewEventsPtr ptrSelViews = GetSelectedEvents(); if (!ptrSelViews || !ptrSelViews->GetCount()) { return FALSE; } if (OnBeforeEditOperationNotify(xtpCalendarEO_Cut, ptrSelViews)) { return FALSE; } //------------------------------------------------------------------------ DWORD dwCopyFlags = xtpCalendarCopyFlagCutMask; COleDataSource* pData = _CopySelectedEvents(dwCopyFlags); if (!pData) { return FALSE; } pData->SetClipboard(); int nCount = ptrSelViews->GetCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarViewEvent* pViewEvent = ptrSelViews->GetAt(i, FALSE); CXTPCalendarEvent* pEvent = pViewEvent ? pViewEvent->GetEvent() : NULL; VERIFY( XTP_SAFE_GET2(pEvent, GetDataProvider(), DeleteEvent(pEvent), FALSE) ); } XTP_SAFE_CALL1(GetCalendarControl(), Populate()); return TRUE; } BOOL CXTPCalendarView::Copy() { if (IsEditingSubject() && _GetSubjectEditorWnd()) { if (CanCopy()) { _GetSubjectEditorWnd()->SendMessage(WM_COPY); return TRUE; } return FALSE; } CXTPCalendarViewEventsPtr ptrSelViews = GetSelectedEvents(); if (!ptrSelViews || !ptrSelViews->GetCount()) return FALSE; if (OnBeforeEditOperationNotify(xtpCalendarEO_Copy, ptrSelViews)) return FALSE; COleDataSource* pData = _CopySelectedEvents(); if (!pData) return FALSE; pData->SetClipboard(); return TRUE; } BOOL CXTPCalendarView::Paste() { if (IsEditingSubject() && _GetSubjectEditorWnd()) { if (CanPaste()) { _GetSubjectEditorWnd()->SendMessage(WM_PASTE); return TRUE; } return FALSE; } COleDateTime dtSelBegin, dtSelEnd; COleDateTimeSpan spSelectionResolution; if (!GetSelection(&dtSelBegin, &dtSelEnd, NULL, NULL, &spSelectionResolution)) { return FALSE; } dtSelBegin = min(dtSelBegin, dtSelEnd); // Attach a COleDataObject to the clipboard and paste the data COleDataObject objData; if (!objData.AttachClipboard()) { return FALSE; } DWORD dwCopyFlags = 0; CXTPCalendarEventsPtr ptrEventsFromCB = _ReadEventsFromClipboard(&objData, &dwCopyFlags); if (!ptrEventsFromCB) return FALSE; if (!GetCalendarControl()) return FALSE; CXTPAutoResetValue autoSet_UpdateCtrlNf(GetCalendarControl()->m_bUpdateWhenEventChangedNotify); autoSet_UpdateCtrlNf = FALSE; COleDateTimeSpan spStartShift; int nCount = ptrEventsFromCB->GetCount(); for (int i = 0; i < nCount; i++) { BOOL bUseChangeEvent = FALSE; CXTPCalendarEvent* pNewEvent = ptrEventsFromCB->GetAt(i, FALSE); if (!pNewEvent) { ASSERT(FALSE); continue; } int nRState = pNewEvent->GetRecurrenceState(); if (nRState == xtpCalendarRecurrenceMaster) { ASSERT(FALSE); // WARNING. Master event in the clipboard - ??? VERIFY(pNewEvent->RemoveRecurrence()); } if (nRState == xtpCalendarRecurrenceOccurrence && dwCopyFlags & xtpCalendarCopyFlagROccurrence2RException) { VERIFY(pNewEvent->MakeAsRException()); bUseChangeEvent = TRUE; } else { VERIFY(pNewEvent->RemoveRecurrence()); } // Update recurrence state nRState = pNewEvent->GetRecurrenceState(); if (nRState == xtpCalendarRecurrenceException && dwCopyFlags & xtpCalendarCopyFlagKeepRException) { CXTPCalendarRecurrencePatternPtr ptrPattern = pNewEvent->GetRecurrencePattern(); bUseChangeEvent = ptrPattern != NULL; } if (!bUseChangeEvent && nRState == xtpCalendarRecurrenceException) { VERIFY( pNewEvent->RemoveRecurrence() ); } COleDateTime dtEventStart = pNewEvent->GetStartTime(); if (i == 0) { spStartShift = dtSelBegin - dtEventStart; spStartShift += ((double)spStartShift < 0 ? -1 : 1) * XTP_HALF_SECOND; double dCells = (double)spStartShift / (double)spSelectionResolution; int nCells = (int)dCells; //+ (dCells >= 0 ? 1 : 0); double dCellDrobTime = fabs(dCells - (DWORD)dCells)*(double)spSelectionResolution; double dCellDrobTimeLimit = XTP_HALF_SECOND*2*10; if (dCells >= 0 && dCellDrobTime > dCellDrobTimeLimit) { nCells++; } spStartShift = (double)spSelectionResolution * (double)nCells; } dtEventStart += spStartShift; pNewEvent->MoveEvent(dtEventStart); if (OnBeforePasteNotify(pNewEvent, bUseChangeEvent)) continue; if (bUseChangeEvent) { VERIFY( XTP_SAFE_GET2(pNewEvent, GetDataProvider(), ChangeEvent(pNewEvent), FALSE) ); } else { VERIFY( XTP_SAFE_GET2(pNewEvent, GetDataProvider(), AddEvent(pNewEvent), FALSE) ); } } if (dwCopyFlags & xtpCalendarCopyFlagClearCBAfterPaste) { if (::OpenClipboard(NULL)) { ::EmptyClipboard(); ::CloseClipboard(); } } XTP_SAFE_CALL1(GetCalendarControl(), Populate()); return TRUE; } CXTPCalendarEventsPtr CXTPCalendarView::_ReadEventsFromClipboard(COleDataObject* pData, DWORD* pdwCopyFlags) { //- Register or get existing Clipboard Format ID ------------------------- CLIPFORMAT uCF_Event = (CLIPFORMAT)::RegisterClipboardFormat(XTPCALENDARCTRL_CF_EVENT); ASSERT(pData); if (!pData || !pData->IsDataAvailable(uCF_Event)) { return NULL; } CXTPCalendarEventsPtr ptrEvents = new CXTPCalendarEvents(); if (!ptrEvents) { return NULL; } const int cErrTextSize = 1024; TCHAR szErrText[cErrTextSize + 1]; try { HGLOBAL hData = pData->GetGlobalData(uCF_Event); if (!hData) { return NULL; } CSharedFile fileSahred; fileSahred.SetHandle(hData, FALSE); CArchive ar(&fileSahred, CArchive::load); CXTPPropExchangeArchive px(ar); long nSchema = 0; DWORD dwCopyFlags = 0; PX_Long(&px, _T("Version"), (long&)nSchema); px.ExchangeLocale(); PX_DWord(&px, _T("CopyFlags"), (DWORD&)dwCopyFlags); if (nSchema != XTP_CLIPBOARD_EVENTS_DATA_VER) { ASSERT(FALSE); return NULL; } CXTPPropExchangeSection sec(px.GetSection(_T("Events"))); CXTPPropExchangeEnumeratorPtr pEnumerator(sec->GetEnumerator(_T("Event"))); POSITION pos = pEnumerator->GetPosition(); UINT uScheduleID = 0; CXTPCalendarData* pDPsel = _GetDataProviderBySelection(&uScheduleID); while (pos) { CXTPPropExchangeSection secEvent(pEnumerator->GetNext(pos)); CXTPCalendarData* pDPevent = NULL; //-- get data provider -------------------- CString strDataProvider; PX_String(&secEvent, _T("DataProvider_ConnectionString"), strDataProvider, _T("")); if (!strDataProvider.IsEmpty()) pDPevent = _GetDataProviderByConnStr(strDataProvider); CXTPCalendarData* pDataProvider = pDPevent ? pDPevent : pDPsel; ASSERT(pDataProvider); //-- create event and read its data --------- CXTPCalendarEventPtr ptrEvent = pDataProvider ? pDataProvider->CreateNewEvent() : NULL; if (!ptrEvent) return NULL; ptrEvent->DoPropExchange(&secEvent); if (!pDPevent || !_IsScheduleVisible(pDPevent, ptrEvent->GetScheduleID())) ptrEvent->SetScheduleID(uScheduleID); ptrEvents->Add(ptrEvent, TRUE); } ar.Close(); // detach from file if (pdwCopyFlags) *pdwCopyFlags = dwCopyFlags; return ptrEvents; } catch(CArchiveException* pE) { if (pE->GetErrorMessage(szErrText, cErrTextSize)) { TRACE(_T("EXCEPTION: CXTPCalendarView::_ReadEventsFromClipboard() - %s\n"), szErrText); } pE->Delete(); } catch(CFileException* pE) { if (pE->GetErrorMessage(szErrText, cErrTextSize)) { TRACE(_T("EXCEPTION: CXTPCalendarView::_ReadEventsFromClipboard() - %s\n"), szErrText); } pE->Delete(); } catch(...) { TRACE(_T("EXCEPTION: CXTPCalendarView::_ReadEventsFromClipboard() - Unhandled Exception!\n")); } ASSERT(FALSE); return NULL; } COleDataSource* CXTPCalendarView::_CopySelectedEvents(DWORD dwCopyFlags) { CXTPCalendarViewEventsPtr ptrSelViews = GetSelectedEvents(); if (!ptrSelViews || !ptrSelViews->GetCount()) return NULL; const int cErrTextSize = 1024; TCHAR szErrText[cErrTextSize + 1]; try { CSharedFile fileSahred(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT); CArchive ar(&fileSahred, CArchive::store); CXTPPropExchangeArchive px(ar); long nSchema = XTP_CLIPBOARD_EVENTS_DATA_VER; PX_Long(&px, _T("Version"), (long&)nSchema); px.ExchangeLocale(); PX_DWord(&px, _T("CopyFlags"), (DWORD&)dwCopyFlags); int nCount = ptrSelViews->GetCount(); CXTPPropExchangeSection sec(px.GetSection(_T("Events"))); CXTPPropExchangeEnumeratorPtr pEnumerator(sec->GetEnumerator(_T("Event"))); POSITION posEnum = pEnumerator->GetPosition((DWORD)nCount); for (int i = 0; i < nCount; i++) { CXTPCalendarViewEvent* pViewEvent = ptrSelViews->GetAt(i, FALSE); CXTPCalendarEvent* pEvent = pViewEvent->GetEvent(); if (!pEvent) { ASSERT(FALSE); continue; } CXTPPropExchangeSection secEvent(pEnumerator->GetNext(posEnum)); CString strDataProvider = XTP_SAFE_GET2(pEvent, GetDataProvider(), GetConnectionString(), _T("")); PX_String(&secEvent, _T("DataProvider_ConnectionString"), strDataProvider); pEvent->DoPropExchange(&secEvent); } ar.Close(); // perform Flush() and detach from file //- Prepare Global data ---------------------------------------------- DWORD dwDataSize = (DWORD)fileSahred.GetLength(); HGLOBAL hData = fileSahred.Detach(); if (!hData) { ASSERT(FALSE); return NULL; } hData = ::GlobalReAlloc(hData, dwDataSize, GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT); if (!hData) { ASSERT(FALSE); return NULL; } //- Register Clipboard Format ---------------------------------------- CLIPFORMAT uCF_Event = (CLIPFORMAT)::RegisterClipboardFormat(XTPCALENDARCTRL_CF_EVENT); // Cache data COleDataSource* pSource = new COleDataSource(); if (pSource) { pSource->CacheGlobalData(uCF_Event, hData); } return pSource; } catch(CArchiveException* pE) { if (pE->GetErrorMessage(szErrText, cErrTextSize)) { TRACE(_T("EXCEPTION: CXTPCalendarView::_CopySelectedEvents() - %s\n"), szErrText); } pE->Delete(); } catch(CFileException* pE) { if (pE->GetErrorMessage(szErrText, cErrTextSize)) { TRACE(_T("EXCEPTION: CXTPCalendarView::_CopySelectedEvents() - %s\n"), szErrText); } pE->Delete(); } catch(...) { TRACE(_T("EXCEPTION: CXTPCalendarView::_CopySelectedEvents() - Unhandled Exception!\n")); } ASSERT(FALSE); return NULL; } //////////////////////////////////////////////////////////////////////////// CXTPCalendarPaintManager* CXTPCalendarView::GetPaintManager() const { ASSERT(m_pControl); return m_pControl ? m_pControl->GetPaintManager() : NULL; } CXTPCalendarTheme* CXTPCalendarView::GetTheme() const { return m_pControl ? m_pControl->GetTheme() : NULL; } void CXTPCalendarView::SendNotification(XTP_NOTIFY_CODE EventCode, WPARAM wParam , LPARAM lParam) { if (m_pControl) m_pControl->SendNotification(EventCode, wParam, lParam); } BOOL CXTPCalendarView::IsEditOperationDisabledNotify(XTPCalendarEditOperation eOperation, CXTPCalendarViewEvent* pEventView) const { return _EditOperationNotify(XTP_NC_CALENDAR_IS_EVENT_EDIT_OPERATION_DISABLED, eOperation, pEventView); } BOOL CXTPCalendarView::OnBeforeEditOperationNotify(XTPCalendarEditOperation eOperation, CXTPCalendarViewEvent* pEventView) { if (IsEditOperationDisabledNotify(eOperation, pEventView)) return TRUE; return _EditOperationNotify(XTP_NC_CALENDAR_BEFORE_EVENT_EDIT_OPERATION, eOperation, pEventView); } BOOL CXTPCalendarView::OnBeforeEditOperationNotify(XTPCalendarEditOperation eOperation, CXTPCalendarViewEvents* pEventViews) { if (_EditOperationNotify(XTP_NC_CALENDAR_IS_EVENT_EDIT_OPERATION_DISABLED, eOperation, NULL, pEventViews)) return TRUE; return _EditOperationNotify(XTP_NC_CALENDAR_BEFORE_EVENT_EDIT_OPERATION, eOperation, NULL, pEventViews); } BOOL CXTPCalendarView::OnBeforePasteNotify(CXTPCalendarEvent* pEvent, BOOL bPasteWillChangeExistingEvent) { XTP_EVENT_PASTE_OPERATION_PARAMS opPasteParams; ::ZeroMemory(&opPasteParams, sizeof(opPasteParams)); opPasteParams.eOperation = xtpCalendarEO_Paste; opPasteParams.pEvent = pEvent; opPasteParams.bPasteWillChangeExistingEvent = bPasteWillChangeExistingEvent; BOOL bDisabledHandled = FALSE; if (m_pControl) { m_pControl->SendNotification(XTP_NC_CALENDAR_IS_EVENT_EDIT_OPERATION_DISABLED, (WPARAM)&opPasteParams, (LPARAM)&bDisabledHandled); } if (bDisabledHandled) return TRUE; if (m_pControl) { m_pControl->SendNotification(XTP_NC_CALENDAR_BEFORE_EVENT_EDIT_OPERATION, (WPARAM)&opPasteParams, (LPARAM)&bDisabledHandled); } return bDisabledHandled; } BOOL CXTPCalendarView::OnInPlaceCreateEvent(LPCTSTR pcszInitialSubject) { XTP_EVENT_IN_PLACE_CREATE_EVENT_OPERATION_PARAMS opCrParams; ::ZeroMemory(&opCrParams, sizeof(opCrParams)); opCrParams.eOperation = xtpCalendarEO_InPlaceCreateEvent; opCrParams.pcszInitialSubject = pcszInitialSubject; BOOL bDisabledHandled = FALSE; if (m_pControl) { m_pControl->SendNotification(XTP_NC_CALENDAR_IS_EVENT_EDIT_OPERATION_DISABLED, (WPARAM)&opCrParams, (LPARAM)&bDisabledHandled); } if (bDisabledHandled) return TRUE; if (m_pControl) { m_pControl->SendNotification(XTP_NC_CALENDAR_BEFORE_EVENT_EDIT_OPERATION, (WPARAM)&opCrParams, (LPARAM)&bDisabledHandled); } return bDisabledHandled; } CXTPCalendarOptions* CXTPCalendarView::GetCalendarOptions() const { return this && m_pControl ? m_pControl->GetCalendarOptions() : NULL; } BOOL CXTPCalendarView::_EditOperationNotify(XTP_NOTIFY_CODE ncEvent, XTPCalendarEditOperation eOperation, CXTPCalendarViewEvent* pEventView, CXTPCalendarViewEvents* pEventViews) const { ASSERT(pEventView || pEventViews && !(pEventView && pEventViews)); XTP_EVENT_EDIT_OPERATION_PARAMS opParams; ::ZeroMemory(&opParams, sizeof(opParams)); CXTPCalendarViewEvents arEvents; arEvents.Add(pEventView, TRUE); opParams.eOperation = eOperation; opParams.pEventViews = pEventView ? &arEvents : pEventViews; BOOL bDisabledHandled = FALSE; if (m_pControl) { m_pControl->SendNotification(ncEvent, (WPARAM)&opParams, (LPARAM)&bDisabledHandled); } return bDisabledHandled; } XTPEnumCalendarUpdateResult CXTPCalendarView::OnEventChanged_InDataProvider( XTP_NOTIFY_CODE nfCode, CXTPCalendarEvent* pEvent) { if (!pEvent) return xtpCalendar_Skip; if (nfCode != XTP_NC_CALENDAREVENTWASADDED && nfCode != XTP_NC_CALENDAREVENTWASDELETED && nfCode != XTP_NC_CALENDAREVENTWASCHANGED) return xtpCalendar_Skip; int nDaysCount = GetViewDayCount(); COleDateTime dtFirstDay = nDaysCount ? XTP_SAFE_GET1(GetViewDay_(0), GetDayDate(), (DATE)0) : (DATE)0; COleDateTime dtLastDay = nDaysCount ? XTP_SAFE_GET1(GetViewDay_(nDaysCount - 1), GetDayDate(), (DATE)0) : (DATE)0; if (nfCode == XTP_NC_CALENDAREVENTWASADDED || nfCode == XTP_NC_CALENDAREVENTWASDELETED) { if (GetDateTimeDay(pEvent->GetStartTime(), pEvent->IsAllDayEvent()) > dtLastDay || GetDateTimeDay(pEvent->GetEndTime(), pEvent->IsAllDayEvent()) < dtFirstDay) return xtpCalendar_Skip; return xtpCalendar_Populate; } return xtpCalendar_Populate; // ***** // An Idea how changing event processing can be optimized // from xtpCalendar_Populate to xtpCalendar_Redraw or even xtpCalendar_Skip. // // int nRState_new = pEvent->GetRecurrenceState(); // if (nRState_new == xtpCalendarRecurrenceMaster) { // return xtpCalendar_Populate; // } // // //----------------------------------------------------------------------- // BOOL bUpdateEvent = FALSE; // int nDays = GetViewDayCount(); // for (int nDay = 0; nDay < nDays; nDay++) // { // CXTPCalendarViewDay* pDay = GetViewDay_(nDay); // ASSERT(pDay); // if (!pDay) // continue; // // // int nEvents = pDay->GetViewEventsCount(); // for (int nEvent = 0; nEvent < nEvents; nEvent++) // { // CXTPCalendarViewEvent* pEventView = pDay->GetViewEvent_(nEvent); // if (!pEventView && !pEventView->GetEvent()) // { // ASSERT(FALSE); // continue; // } // CXTPCalendarEvent* pEvent_I = pEventView->GetEvent(); // if (pEvent_I->GetEventID() == dwEventID) // { // if (!bUpdateEvent) // { // if (pEvent_I->IsEqualStartEnd(pEvent)) // bUpdateEvent = TRUE; // else // return xtpCalendar_Populate; // } // // if (bUpdateEvent) // { // int nRState_I = pEvent_I->GetRecurrenceState(); // //int nRState_new = pEvent->GetRecurrenceState(); // // if (nRState_I == xtpCalendarRecurrenceOccurrence) // pEvent_I->SetRecurrenceState_ExceptionOccurrence(xtpCalendarRecurrenceException); // // pEvent_I->Update(pEvent); // // if (nRState_new == xtpCalendarRecurrenceOccurrence || // nRState_new == xtpCalendarRecurrenceException) // { // ASSERT(nRState_I == xtpCalendarRecurrenceOccurrence || // nRState_I == xtpCalendarRecurrenceException); // // pEvent_I->SetRecurrenceState_ExceptionOccurrence((XTPCalendarEventRecurrenceState)nRState_new); // } // } // } // } // // } // // //----------------------------------------------------------------------- // if (!bUpdateEvent && // !(CXTPCalendarUtils::ResetTime(pEvent->GetStartTime()) > dtLastDay || // CXTPCalendarUtils::ResetTime(pEvent->GetEndTime()) < dtFirstDay) // ) // { // return xtpCalendar_Populate; // } // return bUpdateEvent ? xtpCalendar_Redraw : xtpCalendar_Skip; } CXTPCalendarData* CXTPCalendarView::_GetDataProviderBySelection(UINT* puScheduleID) { COleDateTime dtSelBegin; int nGroup = 0; if (!GetSelection(&dtSelBegin, NULL, NULL, &nGroup)) return NULL; CXTPCalendarViewDay* pViewDay = _GetViewDay(dtSelBegin); if (!pViewDay) return NULL; CXTPCalendarData* pData = NULL; CXTPCalendarViewGroup* pViewGroup = NULL; if (pViewDay && nGroup < pViewDay->GetViewGroupsCount()) { pViewGroup = pViewDay->GetViewGroup_(nGroup); if (pViewGroup) { pData = pViewGroup->GetDataProvider(); if (puScheduleID) *puScheduleID = pViewGroup->GetScheduleID(); } } return pData; } CXTPCalendarData* CXTPCalendarView::_GetDataProviderByConnStr(LPCTSTR pcszConnStr, BOOL bCompareNoCase) { CXTPCalendarViewDay* pViewDay = GetViewDay_(0); COleDateTime dtSelBegin; if (GetSelection(&dtSelBegin)) pViewDay = _GetViewDay(dtSelBegin); if (!pViewDay) return NULL; int nGCount = pViewDay->GetViewGroupsCount(); for (int g = 0; g < nGCount; g++) { CXTPCalendarViewGroup* pViewGroup = pViewDay->GetViewGroup_(g); if (pViewGroup) { CXTPCalendarData* pData = pViewGroup->GetDataProvider(); if (pData) { CString strConn_i = pData->GetConnectionString(); int nCmp = bCompareNoCase ? strConn_i.CompareNoCase(pcszConnStr) : strConn_i.Compare(pcszConnStr); if (nCmp == 0) return pData; } } } return NULL; } BOOL CXTPCalendarView::_IsScheduleVisible(CXTPCalendarData* pDataProvider, UINT uScheduleID) { CXTPCalendarViewDay* pViewDay = GetViewDay_(0); COleDateTime dtSelBegin; if (GetSelection(&dtSelBegin)) pViewDay = _GetViewDay(dtSelBegin); if (!pViewDay) return FALSE; int nGCount = pViewDay->GetViewGroupsCount(); for (int g = 0; g < nGCount; g++) { CXTPCalendarViewGroup* pViewGroup = pViewDay->GetViewGroup_(g); CXTPCalendarData* pData = pViewGroup ? pViewGroup->GetDataProvider() : NULL; if (pData && pData == pDataProvider) { int nRCCount = XTP_SAFE_GET2(pViewGroup, GetResources(), GetCount(), 0); for (int i = 0; i < nRCCount; i++) { if (XTP_SAFE_GET3(pViewGroup, GetResources(), GetAt(i), ExistsScheduleID(uScheduleID), FALSE)) return TRUE; } } } return FALSE; } CXTPCalendarWMHandler* CXTPCalendarView::GetChildHandlerAt(int nIndex) const { CXTPCalendarWMHandler* pDay = GetViewDay_(nIndex); if (!pDay) return NULL; ASSERT_KINDOF(CXTPCalendarWMHandler, pDay); return pDay; } CXTPCalendarResources* CXTPCalendarView::GetResources() const { ASSERT(this); if (m_pResources) return m_pResources; return GetCalendarControl() ? GetCalendarControl()->GetResources() : NULL; } void CXTPCalendarView::SetResources(CXTPCalendarResources* pResources) { BOOL bChanged = TRUE; if (!pResources) { bChanged = m_pResources != NULL; CMDTARGET_RELEASE(m_pResources); } else { if (!m_pResources) m_pResources = new CXTPCalendarResources(); if (!m_pResources) return; // copy data to allow using self as input parameter CXTPCalendarResources arRes; arRes.Append(pResources); m_pResources->RemoveAll(); m_pResources->Append(&arRes); } if (bChanged) SendNotification(XTP_NC_CALENDAR_RESOURCES_WHERE_CHANGED, 1, (LPARAM)this); } BOOL CXTPCalendarView::IsTodayVisible() const { COleDateTime dtToday = CXTPCalendarUtils::GetCurrentTime(); dtToday = GetDateTimeDay(dtToday, FALSE); int nCount = GetViewDayCount(); for (int i = 0; i < nCount; i++) { COleDateTime dtDay = GetViewDayDate(i); if (CXTPCalendarUtils::IsEqual(dtDay, dtToday)) return TRUE; } return FALSE; } void CXTPCalendarView::EmptyUndoBuffer() { m_pUndoBuffer->RemoveAll(); m_eUndoMode = xtpCalendarUndoModeUnknown; } BOOL CXTPCalendarView::HitTest(CPoint pt, XTP_CALENDAR_HITTESTINFO* pHitTest) const { return HitTestEx(pt, pHitTest); } BOOL CXTPCalendarView::HitTestEx(CPoint pt, XTP_CALENDAR_HITTESTINFO* pHitTest) const { if (!pHitTest) { ASSERT(FALSE); return FALSE; } int nCount = GetViewDayCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarViewDay* pViewDay = GetViewDay_(i); ASSERT(pViewDay); if (pViewDay && pViewDay->HitTestEx(pt, pHitTest)) { ASSERT(!pHitTest->pViewDay || pHitTest->pViewDay == pViewDay); pHitTest->nDay = i; pHitTest->pViewDay = pViewDay; return TRUE; } } return FALSE; } ///////////////////////////////////////////////////////////////////////////// CXTPCalendarView::CSelectionChanged_ContextData::CSelectionChanged_ContextData() { m_nLockCount = 0; m_nLockCount_Day = 0; m_nLockCount_Event = 0; m_bRequest_Day = FALSE; m_bRequest_Event = FALSE; } ///////////////////////////////////////////////////////////////////////////// // class CSelectionChangedContext // CXTPCalendarView::CSelectionChangedContext::CSelectionChangedContext(CXTPCalendarView* pView, int eSelType) { if (!pView) { ASSERT(FALSE); return; } m_pView = pView; m_eSelType = eSelType; m_pView->m_cntSelChanged.m_nLockCount += eSelType == xtpCalendarSelectionUnknown ? 1 : 0; m_pView->m_cntSelChanged.m_nLockCount_Day += eSelType == xtpCalendarSelectionDays ? 1 : 0; m_pView->m_cntSelChanged.m_nLockCount_Event += eSelType == xtpCalendarSelectionEvents ? 1 : 0; } CXTPCalendarView::CSelectionChangedContext::~CSelectionChangedContext() { if (!m_pView) { ASSERT(FALSE); return; } if (m_eSelType == xtpCalendarSelectionUnknown) m_pView->m_cntSelChanged.m_nLockCount--; if (m_eSelType == xtpCalendarSelectionDays) { m_pView->m_cntSelChanged.m_nLockCount_Day--; if (m_pView->m_cntSelChanged.m_nLockCount_Day == 0) m_pView->m_cntSelChanged.m_bRequest_Day = TRUE; } if (m_eSelType == xtpCalendarSelectionEvents) { m_pView->m_cntSelChanged.m_nLockCount_Event--; if (m_pView->m_cntSelChanged.m_nLockCount_Event == 0) m_pView->m_cntSelChanged.m_bRequest_Event = TRUE; } if (m_pView->m_cntSelChanged.m_nLockCount == 0 && m_pView->m_cntSelChanged.m_bRequest_Day) { m_pView->m_cntSelChanged.m_bRequest_Day = FALSE; m_pView->SendNotification(XTP_NC_CALENDAR_SELECTION_CHANGED, (WPARAM)xtpCalendarSelectionDays); } if (m_pView->m_cntSelChanged.m_nLockCount == 0 && m_pView->m_cntSelChanged.m_bRequest_Event) { m_pView->m_cntSelChanged.m_bRequest_Event = FALSE; m_pView->SendNotification(XTP_NC_CALENDAR_SELECTION_CHANGED, (WPARAM)xtpCalendarSelectionEvents); } } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // CXTPCalendarWMHandler CXTPCalendarWMHandler::CXTPCalendarWMHandler() { } int CXTPCalendarWMHandler::GetChildHandlersCount() const { return 0; } CXTPCalendarWMHandler* CXTPCalendarWMHandler::GetChildHandlerAt(int nIndex) const { UNREFERENCED_PARAMETER(nIndex); return NULL; } BOOL CXTPCalendarWMHandler::OnLButtonDown(UINT nFlags, CPoint point) { BOOL bHandled = FALSE; int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild && pChild->OnLButtonDown(nFlags, point)) { bHandled = TRUE; break; } } return bHandled; } BOOL CXTPCalendarWMHandler::OnLButtonUp(UINT nFlags, CPoint point) { BOOL bHandled = FALSE; int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild && pChild->OnLButtonUp(nFlags, point)) { bHandled = TRUE; break; } } return bHandled; } BOOL CXTPCalendarWMHandler::OnLButtonDblClk(UINT nFlags, CPoint point) { BOOL bHandled = FALSE; int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild && pChild->OnLButtonDblClk(nFlags, point)) { bHandled = TRUE; break; } } return bHandled; } void CXTPCalendarWMHandler::OnMouseMove(UINT nFlags, CPoint point) { int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild) pChild->OnMouseMove(nFlags, point); } } void CXTPCalendarWMHandler::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild) pChild->OnChar(nChar, nRepCnt, nFlags); } } void CXTPCalendarWMHandler::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild) pChild->OnKeyDown(nChar, nRepCnt, nFlags); } } void CXTPCalendarWMHandler::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild) pChild->OnKeyUp(nChar, nRepCnt, nFlags); } } BOOL CXTPCalendarWMHandler::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { BOOL bHandled = FALSE; int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild && pChild->OnSysKeyDown(nChar, nRepCnt, nFlags)) { bHandled = TRUE; break; } } return bHandled; } BOOL CXTPCalendarWMHandler::OnTimer(UINT_PTR uTimerID) { int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild && pChild->OnTimer(uTimerID)) return TRUE; } return FALSE; } BOOL CXTPCalendarWMHandler::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) { ASSERT(NULL != pResult); BOOL bHandled = FALSE; const int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (NULL != pChild && pChild->OnWndMsg(message, wParam, lParam, pResult)) { bHandled = TRUE; break; } } return bHandled; } void CXTPCalendarWMHandler::OnPostAdjustLayout() { int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild) pChild->OnPostAdjustLayout(); } } void CXTPCalendarWMHandler::OnFinalRelease() { OnBeforeDestroy(); CCmdTarget::OnFinalRelease(); } void CXTPCalendarWMHandler::OnBeforeDestroy() { int nCount = GetChildHandlersCount(); for (int i = 0; i < nCount; i++) { CXTPCalendarWMHandler* pChild = GetChildHandlerAt(i); if (pChild) pChild->OnBeforeDestroy(); } }