📄 calendar1.cpp
字号:
// Calendar1.cpp : implementation file
//
/***************************************************************************
致看到这些源代码的兄弟:
你好!
这本来是我为一个商业PDA产品开发的日历程序,最近移植于PC机上, 所以算法
和数据部分是用纯C++写的,不涉及MFC,所有的代码都是以短节省存储空间为主要目
的.
很高兴你对这些代码有兴趣,你可以随意复制和使用些代码,唯一有一点小小的
愿望:在你使用和复制给别人时,别忘注明这些代码作者:-)。程序代码也就罢了,后
面的数据可是我辛辛苦苦从万年历上找出来输进去的。
如果你有什么好的意见不妨Mail给我。
wangfei@hanwang.com.cn
或
wangfei@engineer.com.cn
2000年3月
****************************************************************************/
#include "stdafx.h"
#include "Calendar.h"
#include "Calendar1.h"
#include "Calendarfrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CCalendar
extern WORD gLunarMonthDay[];
extern BYTE gLunarMonth[];
extern BYTE gLunarHolDay[];
const WORD START_YEAR =1901;
const WORD END_YEAR =2050;
void CCalendar::l_InitData()
{
SYSTEMTIME systime;
::GetSystemTime(&systime);
m_iYear = systime.wYear;
m_iMonth = systime.wMonth;
m_iDay = systime.wDay;
m_dwBackColor = RGB(255,255,255);
m_dwForeColor = RGB(0,0,0);
m_dwSelColor = RGB(150,150,230);
m_dwSelForeColor = RGB(255,255,255);
m_dwTitleBkColor = RGB(190,70,70);
m_dwTitleColor = RGB(255,255,0);
}
CCalendar::CCalendar(WORD iYear, WORD iMonth, WORD iDay)
{
if(!SetDate(iYear, iMonth, iDay))
l_InitData();
}
CCalendar::CCalendar()
{
l_InitData();
}
CCalendar::~CCalendar()
{
DestroyWindow();
}
BEGIN_MESSAGE_MAP(CCalendar, CWnd)
//{{AFX_MSG_MAP(CCalendar)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_CONTEXTMENU()
ON_WM_CREATE()
//}}AFX_MSG_MAP
ON_COMMAND(ID_TITLEBKCOLOR, OnTitleBkColor)
ON_COMMAND(ID_TITLECOLOR, OnTitleColor)
ON_COMMAND(ID_SELCOLOR, OnSelColor)
ON_COMMAND(ID_FORECOLOR, OnForeColor)
END_MESSAGE_MAP()
#define COL_WIDTH 32
#define ROW_HEIGHT 20
#define TITLE_HEIGHT 20
BOOL CCalendar::Create(RECT &rect, CWnd *pParentWnd, UINT nID)
{
CString szClassName = AfxRegisterWndClass(CS_CLASSDC|CS_SAVEBITS|
CS_HREDRAW|CS_VREDRAW,
0, (HBRUSH)CBrush(RGB(255,255,255)), 0);
rect.right = rect.left + COL_WIDTH*7 +4;
rect.bottom = rect.top + TITLE_HEIGHT+ROW_HEIGHT*6 +10 ;
if(!CWnd::CreateEx(WS_EX_CLIENTEDGE, szClassName, _T(""),
WS_CHILD|WS_VISIBLE|WS_TABSTOP, rect,
pParentWnd, nID, NULL))
return FALSE;
UpdateWindow();
for(int i=0; i<42; i++)
m_oBitMapList[i].LoadBitmap(IDB_BITMAP1+i);
m_oPopMenu.CreatePopupMenu();
m_oPopMenu.AppendMenu(MF_STRING, ID_TITLEBKCOLOR, _T("标题背景色..."));
m_oPopMenu.AppendMenu(MF_STRING, ID_TITLECOLOR, _T("标题前景色..."));
m_oPopMenu.AppendMenu(MF_STRING, ID_FORECOLOR , _T("日期前景色..."));
m_oPopMenu.AppendMenu(MF_STRING, ID_SELCOLOR, _T("选中区颜色..."));
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CCalendar message handlers
void CCalendar::l_PaintTitle(CPaintDC &dc)
{
CRect rect ;
GetClientRect(&rect);
rect.left ++; rect.top ++;
rect.right --; rect.bottom = rect.top + TITLE_HEIGHT;
dc.FillRect(&rect, &CBrush(m_dwTitleBkColor));
dc.SetBkColor(m_dwTitleBkColor);
dc.SetTextColor(m_dwTitleColor);
int startx = rect.left +8;
char sztext[][3]={"日","一","二","三","四","五","六"};
for(int i=0; i <7; i++)
{
dc.TextOut(startx, rect.top +2, sztext[i]);
startx += COL_WIDTH;
}
}
void CCalendar:: l_PaintOneDay(CPaintDC &dc, CDC &imgdc, WORD &iDay,
WORD &iLunarYear, WORD &iLunarMonth,
WORD &iLunarDay,
LONG startx, LONG starty, BYTE bSecondLeapMonth)
{
char text[3];
sprintf(text, "%2d", iDay);
// select icon
if(iLunarDay!=1)
imgdc.SelectObject(&m_oBitMapList[iLunarDay-1]);
else
imgdc.SelectObject(&m_oBitMapList[29+iLunarMonth]);
// if day == current day
if(iDay++ == m_iDay)
{
SetRect(&m_sSelRect, startx-1, starty, startx +COL_WIDTH-3,starty + ROW_HEIGHT);
dc.FillRect(m_sSelRect, &CBrush(m_dwSelColor));
dc.SetTextColor(m_dwSelForeColor);
dc.SetBkColor(m_dwSelColor);
dc.TextOut(startx, starty +2, text);
dc.SetBkColor(m_dwBackColor);
dc.SetTextColor(m_dwForeColor);
dc.BitBlt(startx+17, starty +2, 8,16,&imgdc,0,0,MERGEPAINT);
}
else
{
dc.TextOut(startx, starty+2, text);
dc.BitBlt(startx+17, starty +2, 8,16,&imgdc,0,0,SRCCOPY);
}
if(iLunarYear <START_YEAR && iLunarDay == 29)
iLunarDay = 1, iLunarMonth++;
else if(iLunarDay<29)
iLunarDay++;
else
{
LONG days = LunarMonthDays(iLunarYear, iLunarMonth);
if(!HIWORD(days) && iLunarDay == LOWORD(days)
|| bSecondLeapMonth && iLunarDay == HIWORD(days))
iLunarMonth = (iLunarMonth)%12+1;
if(iLunarDay < LOBYTE(days))
iLunarDay++;
else
iLunarDay =1;
}
}
void CCalendar::l_PaintDate(CPaintDC &dc)
{
CDC imgdc;
imgdc.CreateCompatibleDC(&dc);
RECT rect;
GetClientRect(&rect);
rect.top +=TITLE_HEIGHT+6;
dc.SetBkColor(m_dwBackColor);
dc.SetTextColor(m_dwForeColor);
WORD day =1;
WORD iLunarYear, iLunarMonth, iLunarDay;
BYTE bSecondLeapMonth = l_CalcLunarDate(iLunarYear, iLunarMonth, iLunarDay,
CalcDateDiff(m_iYear, m_iMonth, 1));
//GetLunarDate(m_iYear, m_iMonth, 1, iLunarYear, iLunarMonth, iLunarDay);
for(int i=0; i<6; i++, rect.top += ROW_HEIGHT)
{
long startx = rect.left +2;
for(int j=0; j<7; j++,startx += COL_WIDTH)
{
if(j < WeekDay(m_iYear, m_iMonth, 1) && i==0)
continue;
if(day > MonthDays(m_iYear, m_iMonth))
break;
l_PaintOneDay(dc, imgdc, day, iLunarYear, iLunarMonth,
iLunarDay, startx, rect.top, bSecondLeapMonth);
}
}
}
void CCalendar::OnPaint()
{
CPaintDC dc(this); // device context for painting
CFont *font = ((CCalendarFrm *)GetParent())->GetDispFont();
dc.SelectObject(font);
dc.SetMapMode(0);
l_PaintTitle(dc);
l_PaintDate(dc);
}
LONG CCalendar::CalcDateDiff(WORD iEndYear, WORD iEndMonth, WORD iEndDay,
WORD iStartYear, WORD iStartMonth, WORD iStartDay)
{
WORD monthday[]={0, 31, 59 ,90, 120, 151, 181, 212, 243, 273, 304, 334};
//计算两个年份1月1日之间相差的天数
LONG iDiffDays =(iEndYear - iStartYear)*365;
iDiffDays += (iEndYear-1)/4 - (iStartYear-1)/4;
iDiffDays -= ((iEndYear-1)/100 - (iStartYear-1)/100);
iDiffDays += (iEndYear-1)/400 - (iStartYear-1)/400;
//加上iEndYear年1月1日到iEndMonth月iEndDay日之间的天数
iDiffDays += monthday[iEndMonth-1] +
(IsLeapYear(iEndYear)&&iEndMonth>2? 1: 0);
iDiffDays += iEndDay;
//减去iStartYear年1月1日到iStartMonth月iStartDay日之间的天数
iDiffDays -= (monthday[iStartMonth-1] +
(IsLeapYear(iStartYear)&&iStartMonth>2 ? 1: 0));
iDiffDays -= iStartDay;
return iDiffDays;
}
BYTE CCalendar::l_CalcLunarDate(WORD &iYear, WORD &iMonth ,WORD &iDay, LONG iSpanDays)
{
//阳历1901年2月19日为阴历1901年正月初一
//阳历1901年1月1日到2月19日共有49天
BYTE rcode =0;
if(iSpanDays <49)
{
iYear = START_YEAR-1;
if(iSpanDays <19)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -