首页 > 代码库 > MFC Month Calendar Control 控件使用

MFC Month Calendar Control 控件使用

在上层软件编程中,往往需要提供一个月历控件让用户选择相应日期或者用此月历控件来强调特定的一天。MFC的 Month Calendar Control 控件自系统升级到 Windows 7 之后,对于日期控件所能做的操作变少了,不能对指定的日期的背景颜色进行更改,在网上查了很久之后发现是操作系统绘图风格的关系。在这种情况下。只能通过加粗特定日期的字体粗细来凸显该日期的不同(至少本人只想到这个办法)。

首先拉入 Month Calendar Control 控件,为控件添加一个变量叫做 monthcontrol。将控件的 Day States 和 No Trailing Dates 属性置为 True。

在工程的初始化代码中加入如下代码:

int nCount;
SYSTEMTIME timeFrom;
SYSTEMTIME timeUntil;
nCount = monthcontrol.GetMonthRange(&timeFrom, &timeUntil, GMR_DAYSTATE);//返回月历显示的月份数,将控件的No Trailing Dates属性设为True之后,一个页面只显示一个月份
if (nCount == 1)
{
	LPMONTHDAYSTATE pDayState;//日期状态结构体
	pDayState = new MONTHDAYSTATE[nCount];
	memset(pDayState, 0, sizeof(MONTHDAYSTATE)* nCount);
	pDayState[0] |= 1 << (10 - 1);//设置本月的10日要加粗
	VERIFY(monthcontrol.SetDayState(nCount, pDayState));//设置本月的10日加粗
	delete[]pDayState;
}
这时候编译执行工程就会看到月历的10号被加粗了,但是一旦点击月份切换,其他月份的页面就会有很多莫名其妙的被加粗的日期。本人采取的办法是在控件的MCN_VIEWCHANGE控件事件中添加响应函数,让一个计时器启动,如下:

timerun = true;//计时器启动标志
SetTimer(0, 10, 0);//计时器启动

添加对话框的 WM_TIMER 消息

int nCount;
SYSTEMTIME timeFrom;
SYSTEMTIME timeUntil;
nCount = monthcontrol.GetMonthRange(&timeFrom, &timeUntil, GMR_DAYSTATE);//返回月历显示的月份数,将控件的No Trailing Dates属性设为True之后,一个页面只显示一个月份
if (nCount == 1)
{
	LPMONTHDAYSTATE pDayState;//日期状态结构体
	pDayState = new MONTHDAYSTATE[nCount];
	memset(pDayState, 0, sizeof(MONTHDAYSTATE)* nCount);
	pDayState[0] |= 1 << (10 - 1);//设置本月的10日要加粗
	VERIFY(monthcontrol.SetDayState(nCount, pDayState));//设置本月的10日加粗
	delete[]pDayState;
	if (timerun == true)
	{
		timerun = false;
		KillTimer(0);
	}
}
在控件的MCN_SELCHANGE控件事件中也添加响应函数,如下:

int nCount;
SYSTEMTIME timeFrom;
SYSTEMTIME timeUntil;
nCount = monthcontrol.GetMonthRange(&timeFrom, &timeUntil, GMR_DAYSTATE);//返回月历显示的月份数,将控件的No Trailing Dates属性设为True之后,一个页面只显示一个月份
if (nCount == 1)
{
	LPMONTHDAYSTATE pDayState;//日期状态结构体
	pDayState = new MONTHDAYSTATE[nCount];
	memset(pDayState, 0, sizeof(MONTHDAYSTATE)* nCount);
	pDayState[0] |= 1 << (10 - 1);//设置本月的10日要加粗
	VERIFY(monthcontrol.SetDayState(nCount, pDayState));//设置本月的10日加粗
	delete[]pDayState;
}
到此,所有月份页面中的10号就都加粗了,而不影响别的日期。如果稍加留意会发现上面代码的重复率非常高,为看起来简洁,可以用一个函数来封装一下,这样能大量缩减代码。
如果结合对于文件夹和文件的操作,可以实现搜索所有盘符指定文件夹中指定后缀文件,然后将月历中跟文件的修改日期相同的日期加粗的功能,代码如下:

void CDataTestDlg::selectfile()
{
	WCHAR Drive[MAX_PATH] = { 0 };
	int i = 0;
	GetLogicalDriveStrings(MAX_PATH, Drive);
	CString myDrive;
	CString strDBPath;
	bool dayset[33] = { 0 };
	int datlong = 0;
	int nCount;
	int month = 0;
	while (Drive[i - 1] != '\0' || Drive[i] != '\0')
	{
		myDrive = L"";
		myDrive = Drive[i];
		myDrive = myDrive + L":\\";
		strDBPath = myDrive + L"h264视频";//搜索所有盘符下面的名为“h264视频”的文件夹
		HTREEITEM hItem, hSubItem;
		if (PathFileExists(strDBPath))//判断文件夹是否存在
		{
			CFileFind finder;
			vector<CString>  allfile;
			vector<CString>  allfile1;
			CString mydrivewholefilepath;
			mydrivewholefilepath = strDBPath + L"\\*.*";
			bool bworking = finder.FindFile(mydrivewholefilepath); 
			while (bworking)
			{
				bworking = finder.FindNextFile();
				allfile.push_back(finder.GetFileName());//所有文件,文件夹的名称
			}
			for (int i = 0; i<allfile.size(); i++)      
			{
				int flag = allfile[i].Find(L".h264");//找文件夹下面后缀为“.h264”的文件
				if (flag >= 0)
				{
					CString myfilepath;
					myfilepath = strDBPath + L"\\" + allfile[i];
					//获得指定路径文件的修改日期
					SYSTEMTIME time;
					CStdioFile file;
					file.Open(myfilepath, CFile::modeRead);
					FILETIME file_time;
					GetFileTime(file.m_hFile, NULL, NULL, &file_time);
					FileTimeToSystemTime(&file_time, &time);

					SYSTEMTIME timeFrom;
					SYSTEMTIME timeUntil;
					nCount = monthcontrol.GetMonthRange(&timeFrom, &timeUntil, GMR_DAYSTATE);
					if (timeFrom.wYear == time.wYear && timeFrom.wMonth == time.wMonth)
					{
						month = timeFrom.wMonth;
						datlong = timeUntil.wDay - timeFrom.wDay;
						dayset[time.wDay] = true;
					}

					file.Close();
				}
			}
			finder.Close();
		}
		i += 4;
	}
	if (nCount == 1)
	{
		LPMONTHDAYSTATE pDayState;//日期状态结构体
		pDayState = new MONTHDAYSTATE[nCount];
		memset(pDayState, 0, sizeof(MONTHDAYSTATE)* nCount);
		for (int i = 0; i <= datlong + 1; i++)
		{
			if (dayset[i] == true)
			{
				pDayState[0] |= 1 << (i - 1);
			}
		}
		VERIFY(monthcontrol.SetDayState(nCount, pDayState));
		delete[]pDayState;
	}
}