⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minicalendarctrl.cpp

📁 一款最完整的工业组态软源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		const int nOffset = (dtToday - dt).GetDays();
		ptToday.x = nOffset % nDaysPerWeek;
		ptToday.y = nOffset / nDaysPerWeek;
	}

	SelectFont(dc, FontDayNumber);

	CRect rectDate(xBeg, pt.y, xBeg + cxColumn, pt.y + m_dateSize.cy);

	for (int iRow = 0; iRow < nRowsPerCell; ++iRow)
	{
		rectDate.left = xBeg;
		rectDate.right = rectDate.left + cxColumn;

		for (int nCol = 0; nCol < nDaysPerWeek; ++nCol)
		{
			const int nMonth = dt.GetMonth();

			if (nMonth == nThisMonth ||	(m_bShowNonMonthDays &&
					((bBegRange && dt < dtCell) || (bEndRange && dt > dtCell)) ) )
			{
				const CRect rectDigits(
					rectDate.left + m_daySpace.cx / 2,
					rectDate.top,
					rectDate.right + m_daySpace.cx / 2,
					rectDate.bottom + 1);

				COLORREF crText = (nMonth == nThisMonth) ?
					GetSysColor(COLOR_BTNTEXT) : GetSysColor(COLOR_GRAYTEXT);

				if (IsDateSelected(dt))
				{
					crText = COLOR_GRAYTEXT;

					dc.FillSolidRect(
						rectDigits.left, 
						rectDigits.top,
						rectDigits.Width(), 
						rectDate.Height() + m_daySpace.cy,
						GetSysColor(COLOR_BTNFACE));
				}

				TCHAR szBuffer[10];
				_itot(dt.GetDay(), szBuffer, 10);

				dc.SetTextColor(crText);
				dc.DrawText(szBuffer, _tcslen(szBuffer), rectDate,
					DT_BOTTOM | DT_RIGHT | DT_SINGLELINE);

				// Check if date should be hilighted as today.
				if (ptToday.x == nCol && ptToday.y == iRow){
					CRect r = rectDigits;
					r.bottom += 3;
					dc.Draw3dRect(r, RGB(0x80,0,0), RGB(0x80,0,0));
				}
			}

			rectDate.OffsetRect(cxColumn, 0);
			dt += 1;
		}

		rectDate.OffsetRect(0, m_dateSize.cy + m_daySpace.cy);
	}

	return rectDate.bottom - pt.y;
}

// ----------------------------------------------------------------------------
void
CMiniCalendarCtrl::DoPaint(CDCHandle dc)
{
	CRect rectClient;
	GetClientRect(rectClient);

	CRect rectClip;

	dc.SaveDC();
	dc.SetBkMode(TRANSPARENT);
	dc.GetClipBox(rectClip);

	DrawBorder(dc, rectClient);

	for (int nRow = 0; nRow < m_nRows; ++nRow)
		for (int nCol = 0; nCol < m_nCols; ++nCol)
		{
			CRect rectCell(0, 0, m_cellSize.cx, m_cellSize.cy);

			rectCell.OffsetRect(
				nCol * m_cellSize.cx + rectClient.left,
				nRow * m_cellSize.cy + rectClient.top);

			if (rectClip & rectCell)
			{
				rectCell.top += DrawHeader(dc, rectCell.TopLeft(), nCol, nRow);
				dc.FillSolidRect(rectCell, m_crBack);

				rectCell.top += DrawDaysOfWeek(dc, rectCell.TopLeft(), nCol, nRow);
				DrawDays(dc, rectCell.TopLeft(), nCol, nRow);
			}
		}

	dc.RestoreDC(-1);
}

// ----------------------------------------------------------------------------
void
CMiniCalendarCtrl::NotifySelChanged()
{
	NMMCXSELCHANGED nm = {0};

	if (m_dtSelect.GetStatus() == COleDateTime::valid)
	{
		if (m_bMultiSelEnabled)
		{
			if (m_dtAnchor > m_dtSelect)
			{
				m_dtSelect.GetAsSystemTime(nm.dateFrom);
				m_dtAnchor.GetAsSystemTime(nm.dateTo);
			}
			else
			{
				m_dtAnchor.GetAsSystemTime(nm.dateFrom);
				m_dtSelect.GetAsSystemTime(nm.dateTo);
			}
		}
		else
		{
			m_dtSelect.GetAsSystemTime(nm.dateFrom);
			m_dtSelect.GetAsSystemTime(nm.dateTo);
		}
	}

	NotifyParent(MCXN_SELCHANGED, reinterpret_cast<NMHDR*>(&nm));
}

// ----------------------------------------------------------------------------
void
CMiniCalendarCtrl::NotifyParent(UINT nCode, LPNMHDR lpnmh)
{
	lpnmh->code = nCode;
	lpnmh->hwndFrom = m_hWnd;
	lpnmh->idFrom = GetDlgCtrlID();

	::SendMessage(hNotifyWindow,WM_NOTIFY, lpnmh->idFrom, (LPARAM) lpnmh);
}

// ----------------------------------------------------------------------------
BOOL
CMiniCalendarCtrl::HitTest(HitTestInfo& ht)
{
	ht.nFlags = 0;
	ht.nCol = -1;
	ht.nRow = -1;
	ht.dtHit.SetStatus(COleDateTime::invalid);

	CPoint ptHit = ht.ptHit;

	CRect rectClient;
	GetClientRect(rectClient);

	if (m_bShow3dBorder)
	{
		rectClient.DeflateRect(nBorderSize, nBorderSize);
		ptHit -= CSize(nBorderSize, nBorderSize); 
	}

	if (! rectClient.PtInRect(ht.ptHit))
		return FALSE;

	//rectClient.OffsetRect(-nBorderSize, -nBorderSize);

	// Determine which cell was hit.

	const int nCol = ptHit.x / m_cellSize.cx;
	const int nRow = ptHit.y / m_cellSize.cy;

	if (nCol >= m_nCols)
		return FALSE;

	// Determine if a button was hit.

	if (nRow >= m_nRows)
	{
		return FALSE;
	}

	ht.nCol = nCol;
	ht.nRow = nRow;

	// Determine which part of the cell was hit.

	ptHit.x %= m_cellSize.cx;
	ptHit.y %= m_cellSize.cy;

	if (ptHit.y < (int) m_cyHeader)
	{
		ht.nFlags = htHeader;

		const CRect rectHeader(0, 0, m_cellSize.cx, m_cyHeader);

		if (nRow == 0)
		{
			CRect rl = MC_GetArrowRect(rectHeader, TRUE);
			CRect rr = MC_GetArrowRect(rectHeader, FALSE);
			rl.InflateRect(4,4);
			rr.InflateRect(4,4);
			
			if (nCol == 0 && rl.PtInRect(ptHit))
				ht.nFlags |= htBack;

			else if (nCol == m_nCols - 1 && rr.PtInRect(ptHit))
				ht.nFlags |= htNext;
		}

		return TRUE;
	}

	ptHit.y -= m_cyHeader + m_dateSize.cy + 4;

	// Determine if a date was hit.

	const int cxColumn = m_dateSize.cx + m_daySpace.cx;

	CRect rectDate(CPoint(m_xCol, 0), m_dateSize);

	for (int r = 0; r < nRowsPerCell; ++r)
	{
		rectDate.left = m_xCol;
		rectDate.right = rectDate.left + cxColumn;

		for (int c = 0; c < nDaysPerWeek; ++c)
		{
			if (rectDate.PtInRect(ptHit))
			{
				const COleDateTime dtCell = GetMonthFromCell(nCol, nRow);
				//const COleDateTime dtCell = m_dtSelect;

				const int nDay = r * nDaysPerWeek + c;
				const int nMonth = dtCell.GetMonth();

				const COleDateTime dtBeg = GetFirstDayInCell(nCol, nRow);
				const COleDateTime dtHit = dtBeg + COleDateTimeSpan(nDay);

				if (dtHit.GetMonth() == nMonth)
				{
					ht.nFlags = htDate;
					ht.dtHit = dtHit;
					return TRUE;
				}

				if (m_bShowNonMonthDays)
				{
					if (nCol == 0 && nRow == 0 && dtHit < dtCell)
					{
						ht.nFlags = htDate | htBack;
						ht.dtHit = dtHit;
						return TRUE;
					}

					if (nCol == m_nCols - 1 && nRow == m_nRows - 1 && dtHit > dtCell)
					{
						ht.nFlags = htDate | htNext;
						ht.dtHit = dtHit;
						return TRUE;
					}
				}

				return FALSE;
			}

			rectDate.OffsetRect(cxColumn, 0);
		}

		rectDate.OffsetRect(0, m_dateSize.cy + m_daySpace.cy);
	}

	return FALSE;

}

// ----------------------------------------------------------------------------
void
CMiniCalendarCtrl::DoScroll(UINT nFlags, int nMonths)
{
	ATLASSERT(nMonths > 0);

	if (nFlags & htBack)
		nMonths = -m_nMonthsToScroll;
	else if (nFlags & htNext)
		nMonths = m_nMonthsToScroll;
	else
		nMonths = 0;

	if (nMonths)
	{
		m_nStartYear += nMonths / nMonthsPerYear;
		m_nStartMonth += nMonths % nMonthsPerYear;

		if (m_nStartMonth < 1)
		{
			m_nStartMonth += nMonthsPerYear;
			--m_nStartYear;
		}
		else if (m_nStartMonth > nMonthsPerYear)
		{
			m_nStartMonth -= nMonthsPerYear;
			++m_nStartYear;
		}

		RedrawWindow();
	}
}

// ----------------------------------------------------------------------------
void
CMiniCalendarCtrl::GetMaxTextExtent(CDCHandle dc, SIZE& size)
{
	// Determine the maximum size for the range of day numbers.
	// Single-digit day numbers are obviously smaller, so start at 10.

	for (int i = 10; i <= 31; ++i)
	{
		TCHAR sz[10];
		_itot(i, sz, 10);

		SIZE sizeDate = {0};
		dc.GetTextExtent(sz, _tcslen(sz), &sizeDate);

		size.cx = max(sizeDate.cx, size.cx);
		size.cy = max(sizeDate.cy, size.cy);
	}
}

// ----------------------------------------------------------------------------
void
CMiniCalendarCtrl::RecalcLayout()
{
	ATLASSERT(IsWindow());

	CClientDC dc(m_hWnd);
	HFONT hFontOrig = dc.SelectStockFont(DEFAULT_GUI_FONT);

	m_dateSize = CSize(0, 0);
	
	SelectFont(dc.m_hDC, FontDayNumber);
	GetMaxTextExtent(dc.m_hDC, m_dateSize);

	SelectFont(dc.m_hDC, FontSpecialDayNumber);
	GetMaxTextExtent(dc.m_hDC, m_dateSize);

	// Now check names of weekdays.

	m_cyDayNames = 0;
	SelectFont(dc.m_hDC, FontDayName);

	LPCTSTR szNames = _T("SMTWF");

	for (size_t i = 0; i < _tcslen(szNames); ++i)
	{
		SIZE size = {0};
		dc.GetTextExtent(szNames + i, 1, &size);

		m_dateSize.cx = max(size.cx, m_dateSize.cx);
		m_cyDayNames = max((UINT) size.cy, m_cyDayNames);
	}

	// Lastly, calculate the header size.

	const int cxWeek = (m_dateSize.cx + m_daySpace.cx) * nDaysPerWeek + m_daySpace.cx;
	const int cxCalendar = cxWeek + nCellMargin * 2;

	int cxHeader = 0;

	m_cyHeader = 0;
	SelectFont(dc.m_hDC, FontHeader);

	CString str;

	for (int nYear = 1990; nYear < 2020; ++nYear)
		for (int nMonth = 1; nMonth <= nMonthsPerYear; ++nMonth)
		{
			const COleDateTime dt(nYear, nMonth, 1, 0, 0, 0);
			str = dt.Format(HEADER_FORMAT);

			SIZE size = {0};
			dc.GetTextExtent(str, str.GetLength(), &size);

			cxHeader = max(size.cx, cxHeader);
			m_cyHeader = max((UINT) size.cy, m_cyHeader);
		}

	// Header padding.
	m_cyHeader += 6;

	m_cellSize.cx = max(cxHeader + 30, cxCalendar);

	m_cellSize.cy = m_cyHeader + (m_cyDayNames + 4) + 
		(m_dateSize.cy + m_daySpace.cy) * nRowsPerCell;

	m_xCol = (m_cellSize.cx - cxWeek) / 2;

	dc.SelectFont(hFontOrig);
}

// ----------------------------------------------------------------------------
void
CMiniCalendarCtrl::ApplyStyle(DWORD dwStyle)
{
	m_bShow3dBorder = (dwStyle & MCX_3DBORDER) != 0;
	m_bShowNonMonthDays = (dwStyle & MCX_SHOWNONMONTHDAYS) != 0;
	m_bHighlightToday = (dwStyle & MCX_HIGHLIGHTTODAY) != 0;
	m_bMultiSelEnabled = (dwStyle & MCX_MULTISELECT) != 0;

	if (! m_bMultiSelEnabled)
		ResetRange();

	Invalidate();
}

// ----------------------------------------------------------------------------
CString
CMiniCalendarCtrl::GetDayOfWeekName(int nDayOfWeek) const
{
	ATLASSERT(nDayOfWeek >= 1 && nDayOfWeek <= nDaysPerWeek);

	// NOTE: both m_nFirstDayOfWeek and nDayOfWeek are 1-based!

	// Apr 1, 2001 is known to be a Sunday, ie dayOfWeek == 1
	const COleDateTime dt =
		COleDateTime(2001, 4, 1, 0, 0, 0) + 
		COleDateTimeSpan((nDayOfWeek - 1) + (m_nFirstDayOfWeek - 1));

	return dt.Format(_T("%A"));
}

// ----------------------------------------------------------------------------
COleDateTime
CMiniCalendarCtrl::GetMonthFromCell(int nCol, int nRow) const
{
	ATLASSERT(nCol >= 0 && nRow >= 0);

	// NOTE: m_nMonth is 1-based!
	const int nMonth = (m_nStartMonth - 1) + nRow * m_nCols + nCol;
	
	return COleDateTime(m_nStartYear + nMonth / nMonthsPerYear, 
		nMonth % nMonthsPerYear + 1, 1, 0, 0, 0);
}

// ----------------------------------------------------------------------------
COleDateTime
CMiniCalendarCtrl::GetFirstDayInCell(int nCol, int nRow) const
{
	const COleDateTime dt = GetMonthFromCell(nCol, nRow);
	const int nPriorDays = 
		(dt.GetDayOfWeek() - m_nFirstDayOfWeek + nDaysPerWeek) % nDaysPerWeek;

	return dt - COleDateTimeSpan(nPriorDays);
}

// ----------------------------------------------------------------------------
void
CMiniCalendarCtrl::CreateFont(int nFont)
{
	ATLASSERT(nFont >= FontHeader && nFont <= FontSpecialDayNumber);

	FontInfo* pInfo = m_font + nFont;

	CFont font;
	font.CreatePointFont(pInfo->nFontSize * 10, pInfo->strFaceName);

	LOGFONT lf = {0};
	font.GetLogFont(&lf);	
	font.DeleteObject();

	{
		CClientDC dc(m_hWnd);
		lf.lfHeight	= -MulDiv(pInfo->nFontSize, dc.GetDeviceCaps(LOGPIXELSY), 72);
		lf.lfWeight = FW_NORMAL;
		lf.lfQuality = PROOF_QUALITY;
	}

	if (pInfo->bBold)
		lf.lfWeight = FW_BOLD;

	if (pInfo->bItalic)
		lf.lfItalic = TRUE;

	if (pInfo->bUnderline)
		lf.lfUnderline = TRUE;

	if (! pInfo->font.IsNull())
		pInfo->font.DeleteObject();

	pInfo->font.CreateFontIndirect(&lf);
}

// ----------------------------------------------------------------------------
void
CMiniCalendarCtrl::SelectFont(CDCHandle dc, int nFont)
{
	ATLASSERT(nFont >= FontHeader && nFont <= FontSpecialDayNumber);

	dc.SetTextColor(m_font[nFont].crColor);
	dc.SelectFont(m_font[nFont].font);
}

// ----------------------------------------------------------------------------
CMiniCalendarCtrl::FontInfo::FontInfo()
{
	strFaceName = _T("Tahoma");
	crColor = GetSysColor(COLOR_BTNTEXT);
	nFontSize = 9;
	bBold = FALSE;
	bItalic = FALSE;
	bUnderline = FALSE;
}

// ----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -