?? minicalendarctrl.cpp
字號:
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 + -