第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。

  1. /**********************************************************************************/ 
  2. //******* Add the mycug.h file 
  3. #include "Mycug.h" 
  4. #if _MSC_VER >= 1000 
  5. #pragma once 
  6. #endif // _MSC_VER >= 1000 
  7. class CCalendar5Dlg : public CDialog 
  8.     // Construction 
  9. public
  10.     //****** Create a new object 
  11.     MyCug m_grid; 
/**********************************************************************************/
//******* 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()函数。

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


第6步– 设计日历外表

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

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

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

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

  1. /*************************************************************************************/ 
  2. void MyCug::OnSetup() 
  3.     //******* 声明所有的变量 
  4.     CString days[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 
  5.     CUGCell cell; 
  6.     //******* 配置行和列 
  7.     SetNumberCols(7); 
  8.     SetNumberRows(5); 
  9.     //******配置行高!! 
  10.     for (int v = 0; v < 5; v++) 
  11.     { 
  12.         SetRowHeight(v, 40); 
  13.     } 
  14.     //****** 配置列宽!! 
  15.     for (int vv = 0; vv < 7; vv++) 
  16.     { 
  17.         SetColWidth(vv, 80); 
  18.     } 
  19.     //********* 消除侧边标题栏 
  20.     SetSH_Width(0); 
  21.     //********* 配置两个顶部标题栏 
  22.     SetTH_NumberRows(2); 
  23.     //******** 配置两个顶部标题栏的大小 
  24.     SetTH_Height(50); 
  25.     SetTH_RowHeight(-1, 25); 
  26.     SetTH_RowHeight(-2, 25); 
  27.     //***** 在顶部标题栏显示星期 
  28.     for (int zz = 0; zz < 7; zz++) 
  29.     { 
  30.         QuickSetText(zz, -1, days[zz]); 
  31.     } 
  32.     //********* 合并顶部标题栏的几个单元格!!!! 
  33.     JoinCells(2, -2, 4, -2); 
  34.     //******** 配置顶部标题栏箭头单元格类型 
  35.     GetCell(6, -2, &cell); 
  36.     cell.SetCellType(UGCT_ARROW); 
  37.     cell.SetCellTypeEx(64); 
  38.     SetCell(6, -2, &cell); 
  39.     GetCell(0, -2, &cell); 
  40.     cell.SetCellType(UGCT_ARROW); 
  41.     cell.SetCellTypeEx(128); 
  42.     SetCell(0, -2, &cell); 
  43.     GetCell(1, -2, &cell); 
  44.     cell.SetCellType(UGCT_ARROW); 
  45.     cell.SetCellTypeEx(32); 
  46.     SetCell(1, -2, &cell); 
  47.     GetCell(5, -2, &cell); 
  48.     cell.SetCellType(UGCT_ARROW); 
  49.     cell.SetCellTypeEx(16); 
  50.     SetCell(5, -2, &cell); 
  51. /********************************************************************************************************************/ 
/*************************************************************************************/
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后,用户无法调整列的宽度。

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

7.2 – 修改OnCanSizeRow()

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

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

7.3 – 修改OnCanSizeTopHdg()

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

  1. int MyCug::OnCanSizeTopHdg(){  
  2.     return 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头文件中添加以下几行代码。

  1. /*************************************************************************************/ 
  2. class MyCug: public CUGCtrl 
  3. public
  4.     MyCug(); 
  5.     ~MyCug(); 
  6.     int m_current_month, m_current_year; 
  7.     int m_months[15] ; 
/*************************************************************************************/
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赋值。

  1. /***********************************************************************************/ 
  2. MyCug::MyCug() 
  3.     //*******给月份变量数组赋值 
  4.     m_months[0] = 30; 
  5.     m_months[1] = 28; 
  6.     m_months[2] = 31; 
  7.     m_months[3] = 30; 
  8.     m_months[4] = 31; 
  9.     m_months[5] = 30; 
  10.     m_months[6] = 31; 
  11.     m_months[7] = 31; 
  12.     m_months[8] = 30; 
  13.     m_months[9] = 31; 
  14.     m_months[10] = 30; 
  15.     m_months[11] = 31; 
  16.     //*******创建一个COleDateTime对象 
  17.     COleDateTime time = COleDateTime::GetCurrentTime(); 
  18.     //*******给当前月份的成员变量赋值 
  19.     m_current_month = time.GetMonth(); 
  20.     //*******给当前年份的成员变量赋值 
  21.     m_current_year = time.GetYear(); 
/***********************************************************************************/
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()中添加后面的代码。

  1. /************************************************************************************/ 
  2. void MyCug::Date() 
  3.     //****** 声明所有的变量 
  4.     int row = 0; 
  5.     int numberofdays, dayofweek; 
  6.     CString today; 
  7.     CString nameMonths[13] = {"January", "February", "March", "April", "May", "June", "July"
  8.                               "August", "September", "October", "November", "December" 
  9.                              }; 
  10.     CUGCell cell; 
  11.     CString days; 
  12.     /****** 创建一个Time对象, 保存当前月份和当前年份和本月的第一天 *****/ 
  13.     COleDateTime time(m_current_year, m_current_month, 1, 0, 0, 0); 
  14.     /***** 这个变量获取本月第一天的列值,作为循环嵌套For..Loop的索引,后面用来填充网格*****/ 
  15.     dayofweek = time.GetDayOfWeek() - 1; 
  16.     /****** Cstring对象today保存当前月份,当前年份 ***** /
  17.     today.Format("%s, %d", nameMonths[m_current_month -1], m_current_year);
  18.     /******* 在合并单元格的顶部标题栏上显示CString 变量Today值 ********/ 
  19.     GetCell(2, -2, &cell); 
  20.     cell.SetText(today); 
  21.     SetCell(2, -2, &cell); 
  22.     RedrawCell(2, -2); 
  23.     /******* 计算本月份中的天数 ********/ 
  24.     numberofdays = m_months[m_current_month - 1 ]; 
  25.     //******* 闰年的测试!!!!! 
  26.     if ((m_current_month == 2) && ( m_current_year % 4 == 0)) 
  27.         numberofdays++; 
  28.     //******** 清除整个网格 
  29.     int numrows = GetNumberRows(); 
  30.     int numcols = GetNumberCols(); 
  31.     for (int z = 0 ; z < numcols; z++) 
  32.     { 
  33.         for (int x = 0; x < numrows; x++) 
  34.         { 
  35.             QuickSetBackColor(z, -1, RGB(200, 200, 200)); 
  36.             QuickSetText(z, x, ""); 
  37.         } 
  38.     } 
  39.     RedrawAll(); 
  40.     /********** 用正确的日期重新填充网格,注意星期几的变量作为列的索引值******/ 
  41.     for (int index2 = 1; index2 <= numberofdays; index2++) 
  42.     { 
  43.         days.Format("%d", index2); 
  44.         QuickSetText(dayofweek, row, days); 
  45.         dayofweek++; 
  46.         if (dayofweek == 7) 
  47.         { 
  48.             dayofweek = 0; 
  49.             row++; 
  50.         } 
  51.     } 
  52.     RedrawAll(); 
  53.     //********* 完工 !!!!! 
  54. /*********************************************************************************************************/ 
/************************************************************************************/
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()。

  1. /*************************************************************************************/ 
  2. void MyCug::OnTH_LClicked(int col, longrow, int updn, RECT *rect, POINT *point, BOOL processed) 
  3.     if(!updn) 
  4.     { 
  5.         //******* 下一个月!!! 
  6.         if((col == 5) && (row == -2)) 
  7.         { 
  8.             m_current_month++; 
  9.             if(m_current_month > 12) 
  10.             { 
  11.                 m_current_month = 1; 
  12.                 m_current_year++; 
  13.             } 
  14.             Date(); 
  15.         } 
  16.         //******* 上一个月 
  17.         if((col == 1) && (row == -2)) 
  18.         { 
  19.             m_current_month--; 
  20.             if(m_current_month < 1) 
  21.             { 
  22.                 m_current_month = 12; 
  23.                 m_current_year--; 
  24.             } 
  25.             Date(); 
  26.         } 
  27.         //******* 下一年!!! 
  28.         if((col == 6) && (row == -2)) 
  29.         { 
  30.             m_current_year++; 
  31.             Date(); 
  32.         } 
  33.         //******** 上一年!!! 
  34.         if((col == 0) && (row == -2)) 
  35.         { 
  36.             m_current_year--; 
  37.             Date(); 
  38.         } 
  39.     } 
/*************************************************************************************/
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()添加下列代码行。

  1. //********* 往组合框里用月份的名字赋值 
  2. m_month.AddString("January");  
  3. m_month.AddString("February");  
  4. m_month.AddString("March");  
  5. m_month.AddString("April");  
  6. m_month.AddString("May");  
  7. m_month.AddString("June");  
  8. m_month.AddString("July");  
  9. m_month.AddString("August");  
  10. m_month.AddString("September");  
  11. m_month.AddString("October");  
  12. m_month.AddString("November");  
  13. m_month.AddString("December"); 
//********* 往组合框里用月份的名字赋值
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()。

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

  1. /*********************************************************************************/ 
  2. void CCalendar5Dlg::OnSet() 
  3.     //******** 声明所有变量 
  4.     int current_year, current_month; 
  5.     CString year, month; 
  6.     //******* 向两个字符串对象赋值 
  7.     GetDlgItemText(IDC_YEAR, year); 
  8.     GetDlgItemText(IDC_MONTH, month); 
  9.     //******* 获取月份的值!!!! 
  10.     if (month == "January"
  11.         current_month = 1; 
  12.     if (month == "February"
  13.         current_month = 2; 
  14.     if (month == "March"
  15.         current_month = 3; 
  16.     if (month == "April"
  17.         current_month = 4; 
  18.     if (month == "May"
  19.         current_month = 5; 
  20.     if (month == "June"
  21.         current_month = 6; 
  22.     if (month == "July"
  23.         current_month = 7; 
  24.     if (month == "August"
  25.         current_month = 8; 
  26.     if (month == "September"
  27.         current_month = 9; 
  28.     if (month == "October"
  29.         current_month = 10; 
  30.     if (month == "November"
  31.         current_month = 11; 
  32.     if (month == "December"
  33.         current_month = 12; 
  34.     //******** 填充日历!!!!!! 
  35.     current_year = atoi(year); 
  36.     m_grid.m_current_year = current_year; 
  37.     m_grid.m_current_month = current_month; 
  38.     //****** 调用日期函数 
  39.     m_grid.Date(); 
/*********************************************************************************/
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消息处理函数

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

  1. /********************************************************************************************************************/ 
  2. void CCalendar5Dlg::OnCancel(){  
  3.     OnOK();  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值