// ========================================================================== // Class Implementation :COXCalendarPopup // ========================================================================== // Source file :COXCalendarPopup.cpp // Version: 9.3 // This software along with its related components, documentation and files ("The Libraries") // is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is // governed by a software license agreement ("Agreement"). Copies of the Agreement are // available at The Code Project (www.codeproject.com), as part of the package you downloaded // to obtain this file, or directly from our office. For a copy of the license governing // this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900. // ////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "OXCalendarPopup.h" #include "OXCalendar.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /* define message to inform that date selected */ #define WM_ENDPICK WM_USER+10 // Data members ------------------------------------------------------------- // protected: // int m_nFirstDayOfWeek; //--- number of first day of week // this value stored in internal format // 0 - Monday 1 - Tuesday, ect., 6 - Sunday // CButton m_ButtonMonth; //--- button displayed current month and year // CButton m_ButtonNone; //- button to chose none date // CButton m_ButtonToday; //- button to chose today's date // CString m_sNone; //--- name of button // CString m_sToday; //--- name of button // CRect m_rectGrid; //--- specified size and position of // days grid relative to client area // CSize m_SizeWnd; //--- size of calendar window // CSize m_szCell; //--- size of one cell displayed day number // CFont m_font; // window font // CRect m_rectRightNavBar; //--- size and position of right navigation arrow // relative to client area // CRect m_rectLeftNavBar; //--- size and position of left navigation arrow // relative to client area // COleDateTime m_DatePicked; // store selected date // COleDateTime m_DateToday; // store today's date // private: // COleDateTime m_InitialSelectedDate; // previous selected date (showing inversed) // COleDateTime m_DateEnd; // COleDateTime m_DateStart; // values specified valid range of date // COleDateTime m_CurrentMonth; // current month showing // int m_nTick; // if 0 - no timer set, // 1 - timer set to repeate jump to prev month // 2 - timer set to repeate jump to next month // COXCalendarPopup::COXCalendarPopup() // --- In : // --- Out : // --- Returns: // --- Effect : constructor { VERIFY(m_sToday.LoadString(IDS_OX_CALENDARTODAY)); //"Today" VERIFY(m_sNone.LoadString(IDS_OX_CALENDARNONE)); //"None" m_nTick = 0; // no timer set m_nDragMode=dragNothing;//no dragging m_nFirstDayOfWeek=COXCalendar::GetLocaleFirstDayOfWeek(); if(COXCalendar::ms_straWeekDays.GetSize()==0 || COXCalendar::ms_straMonthNames.GetSize()==0) { COXCalendar::GetCalendarLocaleData(); } } COXCalendarPopup::~COXCalendarPopup() { if(::IsWindow(m_hWnd)) { DestroyWindow(); } } BEGIN_MESSAGE_MAP(COXCalendarPopup, CWnd) //{{AFX_MSG_MAP(COXCalendarPopup) ON_WM_LBUTTONDOWN() ON_WM_PAINT() ON_WM_TIMER() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() //}}AFX_MSG_MAP ON_MESSAGE(WM_SETTINGCHANGE,OnSettingChanged) END_MESSAGE_MAP() BOOL COXCalendarPopup::Create(COXCalendar * pBaseCalendar) // --- In : // --- Out : // --- Returns: TRUE if window created successfully, // FALSE otherwise // --- Effect : { static CString sClassName; if(sClassName.IsEmpty()) { sClassName = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,0, (HBRUSH)GetStockObject(WHITE_BRUSH)); } if(!CWnd::CreateEx(WS_EX_OVERLAPPEDWINDOW |WS_EX_STATICEDGE | WS_EX_TOOLWINDOW |WS_EX_DLGMODALFRAME, sClassName,_T(""),WS_POPUP|WS_BORDER,0,0,0,0, NULL,NULL,NULL)) { TRACE(_T("COXCalendarPopup::Create fail!")); return FALSE; } if(pBaseCalendar) { ASSERT(::IsWindow(pBaseCalendar->m_hWnd)); // Set default font from COXCalendar edit control LOGFONT lf; pBaseCalendar->m_font.GetLogFont(&lf); m_font.CreateFontIndirect(&lf); } // Now performing size calculation CalcWindowSize(); if(!m_ButtonToday.Create(m_sToday,WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),this,100)) { // failed to create today button ASSERT(FALSE); DestroyWindow(); return FALSE; } if(!m_ButtonNone.Create(m_sNone,WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),this,101)) { // failed to create none button ASSERT(FALSE); DestroyWindow(); return FALSE; } if(!m_ButtonMonth.Create(m_sNone,WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),this,102)) { // failed to create month button ASSERT(FALSE); DestroyWindow(); return FALSE; } SetButtons(); if(pBaseCalendar) { // Set default font from COXCalendar edit control m_ButtonToday.SetFont(&m_font); m_ButtonNone.SetFont(&m_font); m_ButtonMonth.SetFont(&m_font); } return TRUE; } void COXCalendarPopup::CalcCellSize() { // --- In : // --- Out : // --- Returns: // --- Effect : calculate size of elemental cell that show day ASSERT(::IsWindow(m_hWnd)); CClientDC dc(this); CFont *oldfont = dc.SelectObject(&m_font); //assumed that all digits have approximately equal size CString strSampleDigits("0123456789"); m_szCell = dc.GetTextExtent(strSampleDigits); m_szCell.cx =m_szCell.cx / 5; // One cell is kept 2 digits m_szCell.cy += m_szCell.cy / 5; m_szCell.cx += m_szCell.cx/4; dc.SelectObject(oldfont); } CSize COXCalendarPopup::CalcWindowSize() { ASSERT(::IsWindow(m_hWnd)); CalcCellSize(); ASSERT(COXCalendar::ms_straMonthNames.GetSize() == 12); // calculate width of month navigatoin bar // now add size of left and right navigation arrows //now calculate a size of grid that show days int nGridX = m_szCell.cx*7,nGridY=m_szCell.cy*6; int nMonthBarExtentX,nMonthBarExtentY; int nArrowX=::GetSystemMetrics(SM_CXHSCROLL); nMonthBarExtentX = CalcBarWidth(); nMonthBarExtentY = m_szCell.cy; m_SizeWnd.cx = __max(nMonthBarExtentX,nGridX+nArrowX*2); m_SizeWnd.cy = nMonthBarExtentY + nGridY + m_szCell.cy*3;// One cell for weekdays, other for bottom buttons // add borders m_SizeWnd.cx += ::GetSystemMetrics(SM_CXEDGE)*2; m_SizeWnd.cy += ::GetSystemMetrics(SM_CYEDGE)*2; SetWindowPos(NULL,0,0,m_SizeWnd.cx,m_SizeWnd.cy,SWP_NOACTIVATE | SWP_NOZORDER); CRect rClient; GetClientRect(&rClient); m_rectGrid.top = nMonthBarExtentY+m_szCell.cy + 2; m_rectGrid.left = (rClient.Width() - nGridX)/2; m_rectGrid.BottomRight()=m_rectGrid.TopLeft()+CPoint(nGridX,nGridY); GetClientRect(&m_rectLeftNavBar); m_rectLeftNavBar.bottom = nMonthBarExtentY; m_rectLeftNavBar.right = nArrowX; GetClientRect(&m_rectRightNavBar); m_rectRightNavBar.left = m_rectRightNavBar.right - nArrowX; m_rectRightNavBar.bottom = nMonthBarExtentY; return m_SizeWnd; } BOOL COXCalendarPopup::Pick(COleDateTime& pickDate, const COleDateTime& startDate, const COleDateTime& endDate, CRect rectCalendar) // --- In : valid date range to show,window rect of major COXCalendar control // --- Out : date selected from calendar // --- Returns: TRUE if user select date from calendar window, //FALSE if user cancel selection // --- Effect : display calendar window, process date selections { if(startDate.GetStatus() == 0 && endDate.GetStatus() == 0 && startDate >= endDate) { TRACE(_T("COXCalendarPopup::Pick: passed StartDate > EndDate!")); ASSERT(FALSE); return FALSE; } m_DateToday = COleDateTime::GetCurrentTime(); m_DateToday.m_dt = (int)m_DateToday.m_dt; int x = __max(0,rectCalendar.right - m_SizeWnd.cx); int y; BOOL bPicked = FALSE; if(rectCalendar.bottom + m_SizeWnd.cy >= ::GetSystemMetrics(SM_CYSCREEN)) y = rectCalendar.top - m_SizeWnd.cy; //drop Up else y = rectCalendar.bottom; m_DateStart = startDate; m_DateEnd = endDate; m_InitialSelectedDate = pickDate; // clear time value for date comparation m_DateStart.m_dt = (int)m_DateStart.m_dt; m_DateEnd.m_dt = (int)m_DateEnd.m_dt; m_InitialSelectedDate.m_dt = (int)m_InitialSelectedDate.m_dt; m_ButtonToday.EnableWindow(m_DateToday >= m_DateStart && m_DateToday <= m_DateEnd); if(m_InitialSelectedDate.GetStatus() == 0)//valid date m_CurrentMonth = m_InitialSelectedDate; else { m_CurrentMonth = COleDateTime::GetCurrentTime(); m_CurrentMonth.m_dt = (int)m_CurrentMonth.m_dt; if(m_DateStart.GetStatus() == 0 && m_CurrentMonth < m_DateStart) { m_CurrentMonth = m_DateStart; } if(m_DateEnd.GetStatus() == 0 && m_CurrentMonth > m_DateEnd) { m_CurrentMonth = m_DateEnd; } } // show calendar window SetWindowPos(NULL,x,y,m_SizeWnd.cx,m_SizeWnd.cy,SWP_SHOWWINDOW|SWP_NOZORDER); ShowWindow(SW_SHOW); SetCapture(); // init message loop for(;;) { MSG msg; VERIFY(::GetMessage(&msg, NULL, 0, 0)); if (::GetCapture() != m_hWnd) break; switch (msg.message) { case WM_ENDPICK: // date selection finished, hide window now bPicked = (BOOL)msg.wParam;// if TRUE, date has been selected, // otherwise, user canceled date selection goto ExitLoop; case WM_KEYDOWN: if (msg.wParam != VK_ESCAPE) break; case WM_RBUTTONDOWN: goto ExitLoop; break; default: DispatchMessage(&msg); break; } } ExitLoop: if (::GetCapture() == m_hWnd) ReleaseCapture(); ShowWindow(SW_HIDE); if(bPicked) //date has been selected pickDate = m_DatePicked; return bPicked; } void COXCalendarPopup::OnLButtonDown(UINT /* nFlags */, CPoint point) { CRect rWnd; GetWindowRect(&rWnd); CPoint p = point; ClientToScreen(&p); if(!rWnd.PtInRect(p)) { PostMessage(WM_ENDPICK);// now cancel showing return; } int nHitTest = GridHitTest(point); if(nHitTest != -1) { m_nDragMode = dragGrid; GetFirstShownDate(m_DatePicked); m_DatePicked += nHitTest; if ( m_InitialSelectedDate.GetStatus() != COleDateTimeSpan::valid ) m_InitialSelectedDate = m_DatePicked; else if ( m_InitialSelectedDate != m_DatePicked ) { InvalidateSelChange(m_InitialSelectedDate,m_DatePicked); m_InitialSelectedDate = m_DatePicked; } return; } if(ButtonTodayHit(point)) { // user press button and Today is between // Start and End Date values m_nDragMode = dragTodayButton; m_DatePicked = m_DateToday; m_ButtonToday.SetState(TRUE); return; } if(ButtonNoneHit(point)) { m_nDragMode = dragNoneButton; m_DatePicked.m_dt = 0; m_DatePicked.SetStatus(COleDateTime::null); m_ButtonNone.SetState(TRUE); return; } // otherwise process check for navigation arrows DoNavigationCheck(point); } void COXCalendarPopup::OnPaint() { CPaintDC dc(this); // device context for painting CPen RedPen(PS_SOLID,1,RGB(192,0,0)); // pen for outline today's date CFont *oldfont=NULL; static COLORREF clrLight = ::GetSysColor(COLOR_3DSHADOW), clrNormal = 0, clrHighLightBg = ::GetSysColor(COLOR_HIGHLIGHT), clrHighLightText = ::GetSysColor(COLOR_HIGHLIGHTTEXT); CRect rClip,r;int i; dc.GetClipBox(&rClip); //draw navigation arrows if(r.IntersectRect(rClip,m_rectLeftNavBar)) dc.DrawFrameControl(&m_rectLeftNavBar,DFC_SCROLL,DFCS_SCROLLLEFT); if(r.IntersectRect(rClip,m_rectRightNavBar)) dc.DrawFrameControl(&m_rectRightNavBar,DFC_SCROLL,DFCS_SCROLLRIGHT); CString sMonth; // set current showing month name and year sMonth = COXCalendar::ms_straMonthNames[m_CurrentMonth.GetMonth() -1] + m_CurrentMonth.Format(_T(" %Y")); m_ButtonMonth.SetWindowText(sMonth); oldfont = dc.SelectObject(&m_font); dc.SelectStockObject(BLACK_PEN); COleDateTime DateShow; GetFirstShownDate(DateShow); dc.SetTextColor(clrNormal); CRect rCell; // draw days of week r.SetRect(0,m_rectGrid.top - m_szCell.cy, m_rectRightNavBar.right,m_rectGrid.top); if(r.IntersectRect(rClip,r)) for(i=0;i < 7;i++) { /// CString sWeekDay = (CString)COXCalendar::ms_straWeekDays[(i + m_nFirstDayOfWeek)%7][0]; ASSERT(!sWeekDay.IsEmpty()); sWeekDay=sWeekDay.Left(1); /// rCell.SetRect(m_rectGrid.left + m_szCell.cx*i, m_rectGrid.top - m_szCell.cy, m_rectGrid.left + m_szCell.cx*(i+1), m_rectGrid.top); dc.DrawText(sWeekDay,&rCell,DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP); } // draw separator lines dc.MoveTo(m_rectGrid.left,m_rectGrid.top -1); dc.LineTo(m_rectGrid.right,m_rectGrid.top-1); dc.MoveTo(m_rectGrid.right,m_rectGrid.bottom+1); dc.LineTo(m_rectGrid.left,m_rectGrid.bottom+1); // draw calendar grid for(i=0;i < 6;i++) for(int j=0;j < 7;j++) { if(DateShow.GetStatus() != COleDateTime::valid || DateShow.GetDay() < 0) { DateShow.m_dt += 1; continue;// ignore invalid dates (like > 12/31/9999) } rCell.TopLeft()=m_rectGrid.TopLeft(); rCell.left += m_szCell.cx*j; rCell.top += m_szCell.cy*i; rCell.BottomRight()=rCell.TopLeft()+m_szCell; r = rCell; if(!r.IntersectRect(r,rClip)) { DateShow.m_dt += 1; continue;// this date not needed to be drawn } if(DateShow.GetMonth() == m_CurrentMonth.GetMonth()) dc.SetTextColor(clrNormal); else dc.SetTextColor(clrLight); CString sDay; sDay.Format(_T("%d"),DateShow.GetDay()); // check date to be drawn in selected colors if(m_InitialSelectedDate.GetStatus() == 0 && DateShow == m_InitialSelectedDate) { int oldBkMode = dc.SetBkMode(TRANSPARENT); int oldBkColor = dc.SetBkColor(clrHighLightBg); int oldTextColor = dc.SetTextColor(clrHighLightText); r=rCell; r.OffsetRect(1,0); dc.FillSolidRect(&r,clrHighLightBg); dc.DrawText(sDay,&rCell,DT_RIGHT | DT_VCENTER | DT_SINGLELINE|DT_NOCLIP); dc.SetBkMode(oldBkMode); dc.SetBkColor(oldBkColor); dc.SetTextColor(oldTextColor); } else dc.DrawText(sDay,&rCell,DT_RIGHT | DT_VCENTER | DT_SINGLELINE|DT_NOCLIP); DateShow.m_dt += 1.0; } GetFirstShownDate(DateShow); COleDateTime DateEnd = DateShow; DateEnd.m_dt += 41; if(m_DateToday >= DateShow && m_DateToday <= DateEnd) { // Outline today's date in red int offset = (int)(m_DateToday.m_dt - DateShow.m_dt); GetDayRect(offset,rCell); r=rCell; CPen *oldpen = dc.SelectObject(&RedPen); int oldBkMode = dc.SetBkMode(TRANSPARENT); CBrush *oldbrush = (CBrush*)dc.SelectStockObject(NULL_BRUSH); r.OffsetRect(1,0); dc.Rectangle(&r); dc.SetBkMode(oldBkMode); dc.SelectObject(oldbrush); dc.SelectObject(oldpen); } dc.SelectObject(oldfont); } void COXCalendarPopup::GetFirstShownDate(COleDateTime& d) // --- In : // --- Out :value of first shown date in calendar // --- Returns: // --- Effect : { d.SetDate(m_CurrentMonth.GetYear(),m_CurrentMonth.GetMonth(),1); int dow = d.GetDayOfWeek(); if(dow == 1) dow = 6; else dow -=2; int pos = (dow + 7 - m_nFirstDayOfWeek)%7; if(!pos) pos = 7; d.m_dt -= pos; // roll date back } void COXCalendarPopup::GetLastShownDate(COleDateTime& d) // --- In : // --- Out :value of last shown date in calendar // --- Returns: // --- Effect : { GetFirstShownDate(d); d.m_dt += 41; } int COXCalendarPopup::GridHitTest(CPoint pt) // --- In :coordinate of cursor // --- Out : // --- Returns::hit test for cursor over showing dates // -1 if no dates hit or date not in valid range // otherwise offset of first shown date // example: HitDate.m_dt = FirstShownDate.m_dt + HitTest // --- Effect : { if(!m_rectGrid.PtInRect(pt)) return -1;// hit nothing pt -= m_rectGrid.TopLeft(); int ht = (pt.x / m_szCell.cx + 7*(pt.y / m_szCell.cy)); COleDateTime TestDate; GetFirstShownDate(TestDate); TestDate.m_dt += ht; if(TestDate < m_DateStart || TestDate > m_DateEnd) return -1; // selected date not in range return ht; } int COXCalendarPopup::HitTestNavigation(CPoint pt) // --- In : coordinate of cursor // --- Out : // --- Returns:hit test for cursor over one of navigation // arrows as 0 - nothing hit, 1 - left (prev. month) arrow hit // 2 - right (next month) arrow hit // --- Effect : { if(m_rectLeftNavBar.PtInRect(pt)) return 1;//left arrow hit if(m_rectRightNavBar.PtInRect(pt)) return 2;//right arrow hit return 0; // noting hit } void COXCalendarPopup::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default ASSERT(nIDEvent == 0);// only one timer set /* timer is used when user click mouse button over navigation arrow and hold it.Each tick repeate jump to next or previous month if possible */ COleDateTime NewMonth = m_CurrentMonth; ASSERT(m_nTick); if(m_nTick == 1) //left arrow pressed DecMonth(NewMonth); else { // only 0,1 and 2 is valid values for hit test ASSERT(m_nTick == 2); IncMonth(NewMonth); } if(CanShowMonth(NewMonth)) { m_CurrentMonth = NewMonth; CRect r; GetClientRect(&r); r.top = m_rectGrid.top; r.bottom = m_rectGrid.bottom; InvalidateRect(&r); } CWnd::OnTimer(nIDEvent); } BOOL COXCalendarPopup::CanShowMonth(COleDateTime& month) { COleDateTime tmpDate=m_CurrentMonth; BOOL bCanShow = TRUE; m_CurrentMonth = month; COleDateTime DateCheck; GetFirstShownDate(DateCheck); if(DateCheck.GetStatus() != COleDateTime::valid) { m_CurrentMonth = tmpDate; return FALSE; } if(DateCheck > m_DateEnd) { bCanShow=FALSE; } else { GetLastShownDate(DateCheck); if(DateCheck < m_DateStart) { bCanShow=FALSE; } } m_CurrentMonth = tmpDate; return bCanShow; } void COXCalendarPopup::DoNavigationCheck(CPoint pt) // --- In :coordinate of cursor // --- Out : // --- Returns: // --- Effect : check coordinate for navigation // jump to next or previous month if possible { int nHitTest = HitTestNavigation(pt); if(!nHitTest) return;//arrows not clicked COleDateTime NewMonth = m_CurrentMonth; if(nHitTest == 1) //left arrow pressed DecMonth(NewMonth); else { // only 0,1 and 2 is valid values for hit test ASSERT(nHitTest == 2); IncMonth(NewMonth); } // check new month can be shown if(CanShowMonth(NewMonth)) { m_CurrentMonth = NewMonth; CRect r; GetClientRect(&r); r.top = m_rectGrid.top; r.bottom = m_rectGrid.bottom; InvalidateRect(&r); m_nTick = nHitTest; // set timer to repeateble SetTimer(0,200,NULL); } else InvalidateRect(NULL); } void COXCalendarPopup::IncMonth(COleDateTime& month) // --- In : // --- Out : // --- Returns: // --- Effect : increase given date until jump // to next month { int m = month.GetMonth(); while(m == month.GetMonth()) month.m_dt += 1; } void COXCalendarPopup::DecMonth(COleDateTime& month) // --- In : // --- Out : // --- Returns: // --- Effect : decrease given date until jump // to previous month { int m = month.GetMonth(); while(m == month.GetMonth()) month.m_dt -= 1; } void COXCalendarPopup::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if(m_nTick) if(m_nTick != HitTestNavigation(point)) { KillTimer(0); m_nTick = 0; } switch(m_nDragMode) { case dragNoneButton: m_ButtonNone.SetState(ButtonNoneHit(point)); break; case dragTodayButton: m_ButtonToday.SetState(ButtonTodayHit(point)); break; case dragGrid: { int nHitTest = GridHitTest(point); if(nHitTest != -1) { GetFirstShownDate(m_DatePicked); m_DatePicked.m_dt += nHitTest; InvalidateSelChange(m_InitialSelectedDate,m_DatePicked); m_InitialSelectedDate = m_DatePicked; } } break; case dragNothing: break; default: TRACE(_T("Undefined dragging mode!\n")); ASSERT(FALSE); break; } CWnd::OnMouseMove(nFlags, point); } void COXCalendarPopup::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if(m_nTick) { KillTimer(0); m_nTick=0; } switch(m_nDragMode) { case dragGrid: { int nHitTest = GridHitTest(point); if(nHitTest != -1) { GetFirstShownDate(m_DatePicked); m_DatePicked += nHitTest; PostMessage(WM_ENDPICK,1);// now end showing and return today } } break; case dragNoneButton: m_ButtonNone.SetState(FALSE); if(ButtonNoneHit(point)) { m_DatePicked.m_dt = 0; m_DatePicked.SetStatus(COleDateTime::null); PostMessage(WM_ENDPICK,1);// now end showing and return today } break; case dragTodayButton: m_ButtonToday.SetState(FALSE); if(ButtonTodayHit(point)) { // user press button and Today is between // Start and End Date values m_DatePicked = m_DateToday; PostMessage(WM_ENDPICK,1);// now end showing and return today } break; } m_nDragMode = dragNothing; CWnd::OnLButtonUp(nFlags, point); } int COXCalendarPopup::CalcBarWidth() // --- In : // --- Out : // --- Returns: width, in pixels, of navigation bar //that shows current month name, year and two arrows to jump //to next or previous month based on current font // --- Effect : { CClientDC dc(this); CFont * oldfont = dc.SelectObject(&m_font); int nMonthBarExtentX=0,curLenght,nLongerMonth=0; for(int i=0;i < 12;i++) { curLenght = dc.GetTextExtent(COXCalendar::ms_straMonthNames[i]).cx; if(curLenght > nMonthBarExtentX) { nMonthBarExtentX = curLenght; nLongerMonth=i; } } CString strTest; // init string with average value strTest.Format(_T(" %s 1997 "),(LPCTSTR)COXCalendar::ms_straMonthNames[nLongerMonth]); nMonthBarExtentX = dc.GetTextExtent(strTest).cx; int nArrowX=::GetSystemMetrics(SM_CXHSCROLL); nMonthBarExtentX += nArrowX*2; dc.SelectObject(oldfont); return nMonthBarExtentX; } void COXCalendarPopup::SetButtons() // --- In : // --- Out : // --- Returns : // --- Effect :set up sizes and positions of buttons { CRect rectButton; rectButton.TopLeft() = CPoint(m_rectGrid.left, m_rectGrid.bottom + m_szCell.cy/2); rectButton.BottomRight() = rectButton.TopLeft(); rectButton.right += m_szCell.cx*3; rectButton.bottom += m_szCell.cy; m_ButtonToday.MoveWindow(&rectButton,FALSE); rectButton.TopLeft() = CPoint(m_rectGrid.right - m_szCell.cx*3, m_rectGrid.bottom + m_szCell.cy/2); rectButton.BottomRight() = rectButton.TopLeft(); rectButton.right += m_szCell.cx*3; rectButton.bottom += m_szCell.cy; m_ButtonNone.MoveWindow(&rectButton,FALSE); rectButton.top = m_rectLeftNavBar.top; rectButton.bottom = m_rectLeftNavBar.bottom; rectButton.right=m_rectRightNavBar.left; rectButton.left = m_rectLeftNavBar.right; m_ButtonMonth.MoveWindow(&rectButton,FALSE); } BOOL COXCalendarPopup::ButtonTodayHit(CPoint point) { CRect rButton; m_ButtonToday.GetWindowRect(&rButton); ScreenToClient(&rButton); if(rButton.PtInRect(point) && m_ButtonToday.IsWindowEnabled()) return TRUE; return FALSE; } BOOL COXCalendarPopup::ButtonNoneHit(CPoint point) { CRect rButton; m_ButtonNone.GetWindowRect(&rButton); ScreenToClient(&rButton); if(rButton.PtInRect(point)) return TRUE; return FALSE; } void COXCalendarPopup::GetDayRect(int offset,CRect& rect) { ASSERT(offset >= 0 && offset <= 41); int i = offset % 7,j = offset / 7; rect.SetRect(m_rectGrid.left + m_szCell.cx*i, m_rectGrid.top + m_szCell.cy*j, m_rectGrid.left + m_szCell.cx*(i+1), m_rectGrid.top + m_szCell.cy*(j+1)); } void COXCalendarPopup::InvalidateSelChange(COleDateTime& SelOld,COleDateTime& SelNew) // --- In :old and new highlighted date value // --- Out : // --- Returns: // --- Effect :Calculate and Invalidate areas for update window while //dragging mouse { COleDateTime FirstDate,LastDate; GetFirstShownDate(FirstDate); GetLastShownDate(LastDate); int nHitNew = (int)(SelNew.m_dt - FirstDate.m_dt); int nHitOld = (int)(SelOld.m_dt - FirstDate.m_dt); if(SelOld == SelNew) return; CRect rOld,rNew;CString sDay; // old selections check if(SelOld.GetStatus() == COleDateTime::valid && SelOld >= FirstDate && SelOld <= LastDate) { GetDayRect(nHitOld,rOld); rOld.OffsetRect(1,0); rOld.NormalizeRect(); } else rOld.SetRectEmpty(); GetDayRect(nHitNew,rNew); rNew.OffsetRect(1,0); rNew.NormalizeRect(); InvalidateRect(&rNew); if(!rOld.IsRectEmpty()) InvalidateRect(&rOld); } void COXCalendarPopup::PostNcDestroy() { // TODO: Add your specialized code here and/or call the base class m_font.DeleteObject(); CWnd::PostNcDestroy(); } LRESULT COXCalendarPopup::OnSettingChanged(WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); COXCalendar::GetCalendarLocaleData(); return 0; }