第11课 日历应用程序

简介

本教程将演示如何使用UltimateGrid,以生成一个非常快速和准确的日历应用程序。此应用程序允许用户一个月一个月或一年一年的前后翻页。允许用户输入特定的月份或年份而跳转到那个特定的时间。

下图显示了完成后的的日历应用程序。


图4.22 – 日历应用程序


第1步– 启动一个新的MFC项目

启动MFC应用程序向导创建一个新的MFC项目,命名为:'Calendar5' 。


图 4.23 – MFC应用程序向导


选择基于对话框的选项,如下图。


图 4.24 – MFC应用程序向导的第一步


第2步– 添加源文件

添加两个必须的Ultimate Grid文件到项目,他们是Skel目录下的: mycug.cppmycug.h,然后再把source 目录的UG*.cpp添加到项目里,如下图。


第3步 –设计对话框界面

修改IDD_CALENDAR5_DLG对话框界面,如图4.25。
左键单击组合框的下拉列表按钮(倒三角),这时显示了组合框包括扩展列表框的大小,然后调整它的高度。


图 4.25 - IDD_CALENDAR5_DLG界面

参阅下表分配控件的名称

控件

控件名

组合框

IDC_MONTH

编辑框

IDC_YEAR

Set按钮

IDSET

Close按钮

IDCANCEL

主static区域(日历显示区域)

IDC_GRID

 

第4步– 创建一个CCalendar5Dlg类成员

主对话框是CCalendar5Dlg类。在其中添加一个新的MyCug类的成员变量m_grid。在CCalendar5Dlg类的头文件的前面包含MyCug.h。

/**********************************************************************************/
//******* Add the mycug.h file
#include "Mycug.h"
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CCalendar5Dlg : public CDialog
{
    // Construction
public:
    //****** Create a new object
    MyCug m_grid;


第5步– 在对话框界面上建立网格

贴附Ultimate Grid到对话框界面。添加下列代码到CCalendar5Dlg::OnInitDialog()函数。

/*********************************************************************************/
BOOL CCalendar5Dlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    m_grid.AttachGrid(this, IDC_GRID);
    //**** MORE CODE
}


第6步– 设计日历外表

由于这是一个日历程序,只能有5行7列。我们必须在OnSetup()函数中确定行列的宽和高。

可以没有侧标题栏,但会有多个顶部标题栏。星期几的名称被保存在'Days'字符串类数组中。'Days'数组的元素将填充相应的顶部标题。

最上面的标题栏将包含箭头单元格类型,这些单元格类型只有外表没有实际功能。

因此添加以下几行代码到MyCug类的OnSetup函数中。在代码片段中有额外的详细的注释。

/*************************************************************************************/
void MyCug::OnSetup()
{
    //******* 声明所有的变量
    CString days[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
    CUGCell cell;
    //******* 配置行和列
    SetNumberCols(7);
    SetNumberRows(5);
    //******配置行高!!
    for (int v = 0; v < 5; v++)
    {
        SetRowHeight(v, 40);
    }
    //****** 配置列宽!!
    for (int vv = 0; vv < 7; vv++)
    {
        SetColWidth(vv, 80);
    }
    //********* 消除侧边标题栏
    SetSH_Width(0);
    //********* 配置两个顶部标题栏
    SetTH_NumberRows(2);
    //******** 配置两个顶部标题栏的大小
    SetTH_Height(50);
    SetTH_RowHeight(-1, 25);
    SetTH_RowHeight(-2, 25);
    //***** 在顶部标题栏显示星期
    for (int zz = 0; zz < 7; zz++)
    {
        QuickSetText(zz, -1, days[zz]);
    }
    //********* 合并顶部标题栏的几个单元格!!!!
    JoinCells(2, -2, 4, -2);
    //******** 配置顶部标题栏箭头单元格类型
    GetCell(6, -2, &cell);
    cell.SetCellType(UGCT_ARROW);
    cell.SetCellTypeEx(64);
    SetCell(6, -2, &cell);
    GetCell(0, -2, &cell);
    cell.SetCellType(UGCT_ARROW);
    cell.SetCellTypeEx(128);
    SetCell(0, -2, &cell);
    GetCell(1, -2, &cell);
    cell.SetCellType(UGCT_ARROW);
    cell.SetCellTypeEx(32);
    SetCell(1, -2, &cell);
    GetCell(5, -2, &cell);
    cell.SetCellType(UGCT_ARROW);
    cell.SetCellTypeEx(16);
    SetCell(5, -2, &cell);
}
/********************************************************************************************************************/

当您添加了上面的代码,你应该能够执行应用程序。下面的图应该是这个结果。


图 4.26 – 一个没有功能的日历应用程序

第7步– 修改网格属性

有几个属性必须修改。第一项任务是不允许用户调整行和列的大小。

7.1 – 修改OnCanSizeCol()

默认情况下,列的宽度是能够调整的。当改变这个消息函数的返回值TRUE为FALSE后,用户无法调整列的宽度。

int MyCug::OnCanSizeCol(int col){ 
    return FALSE; 
}

7.2 – 修改OnCanSizeRow()

默认情况下,行的高度是能够调整的。当改变这个消息函数的返回值TRUE为FALSE后,用户无法调整行的高度。

int MyCug::OnCanSizeRow(long row){ 
    return FALSE; 
}

7.3 – 修改OnCanSizeTopHdg()

当改变这个消息函数的返回值TRUE为FALSE后,用户无法调整顶部标题栏。

int MyCug::OnCanSizeTopHdg(){ 
    return FALSE; 
}

第8步– 创建MyCug 类成员变量

这个类的三个新的成员变量为m_current_month ,m_current_year和m_months。m_current_year成员变量与当前年保持关联,m_current_month成员变量与当前的月保持关联,m_months成员变量与存放每月有多少天的整数数组保持关联。

在MyCug头文件中添加以下几行代码。

/*************************************************************************************/
class MyCug: public CUGCtrl
{
public:
    MyCug();
    ~MyCug();
    int m_current_month, m_current_year;
    int m_months[15] ;

第9步– 给新的成员变量赋以适当的值

在MyCug的构造函数中,你必须给这三个成员函数赋以适当的值。

在这代码片段中所完成的另外的一项重要任务是创建一个'time'的COleDateTime对象。调用time.GetMonth()和time.GetYear()对两个成员变量m_current_month和m_current_year赋值。

/***********************************************************************************/
MyCug::MyCug()
{
    //*******给月份变量数组赋值
    m_months[0] = 30;
    m_months[1] = 28;
    m_months[2] = 31;
    m_months[3] = 30;
    m_months[4] = 31;
    m_months[5] = 30;
    m_months[6] = 31;
    m_months[7] = 31;
    m_months[8] = 30;
    m_months[9] = 31;
    m_months[10] = 30;
    m_months[11] = 31;
    //*******创建一个COleDateTime对象
    COleDateTime time = COleDateTime::GetCurrentTime();
    //*******给当前月份的成员变量赋值
    m_current_month = time.GetMonth();
    //*******给当前年份的成员变量赋值
    m_current_year = time.GetYear();
}

第10步– 创建一个MyCug 类成员函数

在MyCug类中添加一个名字为Date()返回类型为void的成员函数。这个函数负责跟踪日期,并往网格里放入正确的月份值。

在MyCug::Date()中添加后面的代码。

/************************************************************************************/
void MyCug::Date()
{
    //****** 声明所有的变量
    int row = 0;
    int numberofdays, dayofweek;
    CString today;
    CString nameMonths[13] = {"January", "February", "March", "April", "May", "June", "July",
                              "August", "September", "October", "November", "December"
                             };
    CUGCell cell;
    CString days;
    /****** 创建一个Time对象, 保存当前月份和当前年份和本月的第一天 *****/
    COleDateTime time(m_current_year, m_current_month, 1, 0, 0, 0);
    /***** 这个变量获取本月第一天的列值,作为循环嵌套For..Loop的索引,后面用来填充网格*****/
    dayofweek = time.GetDayOfWeek() - 1;
    /****** Cstring对象today保存当前月份,当前年份 ***** /
    today.Format("%s, %d", nameMonths[m_current_month -1], m_current_year);
    /******* 在合并单元格的顶部标题栏上显示CString 变量Today值 ********/
    GetCell(2, -2, &cell);
    cell.SetText(today);
    SetCell(2, -2, &cell);
    RedrawCell(2, -2);
    /******* 计算本月份中的天数 ********/
    numberofdays = m_months[m_current_month - 1 ];
    //******* 闰年的测试!!!!!
    if ((m_current_month == 2) && ( m_current_year % 4 == 0))
        numberofdays++;
    //******** 清除整个网格
    int numrows = GetNumberRows();
    int numcols = GetNumberCols();
    for (int z = 0 ; z < numcols; z++)
    {
        for (int x = 0; x < numrows; x++)
        {
            QuickSetBackColor(z, -1, RGB(200, 200, 200));
            QuickSetText(z, x, "");
        }
    }
    RedrawAll();
    /********** 用正确的日期重新填充网格,注意星期几的变量作为列的索引值******/
    for (int index2 = 1; index2 <= numberofdays; index2++)
    {
        days.Format("%d", index2);
        QuickSetText(dayofweek, row, days);
        dayofweek++;
        if (dayofweek == 7)
        {
            dayofweek = 0;
            row++;
        }
    }
    RedrawAll();
    //********* 完工 !!!!!
}
/*********************************************************************************************************/


在CCalendar5Dlg:: OnPaint ()函数里面添加下面这一行。

m_grid.Date();

现在,所有的工作就结束了,你可以执行程序了,这将是一个全功能的应用程序,当然只显示当前月,请记住在MyCug 的构造函数中m_current_month变量分配月份,m_current_year变量分配年份。

现在,您的应用程序应该类似于下图。


图 4.27 – 一个全功能的日历应用程序

第11步– 修改OnTH_Lclicked消息函数

当用户左键单击指向右侧的双箭头按钮时(在顶部标题栏中),我们希望转到下一个年份。当用户左键单击指向右侧的单箭头按钮时,我们希望转到下一个月份。当用户左键单击指向左侧的单箭头按钮时,我们希望转到上一个月份。当用户左键单击指向左侧的双箭头按钮时,我们希望转到上一个年份。

添加下面的代码到 OnTH_LClicked()。

/*************************************************************************************/
void MyCug::OnTH_LClicked(int col, longrow, int updn, RECT *rect, POINT *point, BOOL processed)
{
    if(!updn)
    {
        //******* 下一个月!!!
        if((col == 5) && (row == -2))
        {
            m_current_month++;
            if(m_current_month > 12)
            {
                m_current_month = 1;
                m_current_year++;
            }
            Date();
        }
        //******* 上一个月
        if((col == 1) && (row == -2))
        {
            m_current_month--;
            if(m_current_month < 1)
            {
                m_current_month = 12;
                m_current_year--;
            }
            Date();
        }
        //******* 下一年!!!
        if((col == 6) && (row == -2))
        {
            m_current_year++;
            Date();
        }
        //******** 上一年!!!
        if((col == 0) && (row == -2))
        {
            m_current_year--;
            Date();
        }
    }
}


第12步– 创建自定义日期控件

你必须在CCalendar5Dlg类中添加一个成员变量,它是IDC_MONTH组合控件的实例化对象。用类向导创建一个m_month成员变量。请确保它是组合控件的实例化对象。

对m_month对象赋值

打开CCalendar5Dlg::OnInitDialog()添加下列代码行。

//********* 往组合框里用月份的名字赋值
m_month.AddString("January"); 
m_month.AddString("February"); 
m_month.AddString("March"); 
m_month.AddString("April"); 
m_month.AddString("May"); 
m_month.AddString("June"); 
m_month.AddString("July"); 
m_month.AddString("August"); 
m_month.AddString("September"); 
m_month.AddString("October"); 
m_month.AddString("November"); 
m_month.AddString("December");

第13步– 创建一个CCalendar5Dlg 类的成员函数

用类向导创建一个新的IDSET控件的消息函数,默认情况下这个消息函数为CCalendar5Dlg::OnSet()。

添加下列代码行到消息函数中。

/*********************************************************************************/
void CCalendar5Dlg::OnSet()
{
    //******** 声明所有变量
    int current_year, current_month;
    CString year, month;
    //******* 向两个字符串对象赋值
    GetDlgItemText(IDC_YEAR, year);
    GetDlgItemText(IDC_MONTH, month);
    //******* 获取月份的值!!!!
    if (month == "January")
        current_month = 1;
    if (month == "February")
        current_month = 2;
    if (month == "March")
        current_month = 3;
    if (month == "April")
        current_month = 4;
    if (month == "May")
        current_month = 5;
    if (month == "June")
        current_month = 6;
    if (month == "July")
        current_month = 7;
    if (month == "August")
        current_month = 8;
    if (month == "September")
        current_month = 9;
    if (month == "October")
        current_month = 10;
    if (month == "November")
        current_month = 11;
    if (month == "December")
        current_month = 12;
    //******** 填充日历!!!!!!
    current_year = atoi(year);
    m_grid.m_current_year = current_year;
    m_grid.m_current_month = current_month;
    //****** 调用日期函数
    m_grid.Date();
}

第14步– 创建和编辑OnCancel消息处理函数

当用户点击“关闭”按钮时,此消息函数将被调用。添加下面代码行。

/********************************************************************************************************************/
void CCalendar5Dlg::OnCancel(){ 
    OnOK(); 
}

结论

恭喜你,完成了一个日历应用程序。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值