Files
minigui-docs/programming-guide-zh/MiniGUIProgGuidePart6Chapter15-zh.md
lisimeng123 12ea4e47e4 update
2022-11-18 00:00:48 +08:00

7.7 KiB
Raw Permalink Blame History

月历控件

月历控件monthcalendar提供一个类似日历的用户界面使用户可以方便的选择和设置日期。应用程序可以通过向月历控件发送消息来获取和设置日期。

你可以通过调用CreateWindow函数,使用控件类名称 CTRL_MONTHCALENDAR,来创建一个月历控件。

1.1 月历控件风格

月历控件可以用中文或英文等多种格式显示星期和月份等日期信息,这可以通过指定控件的风格为 MCS_CHNMCS_ENG_LMCS_ENG_S 来完成。如果月历控件风格中包括 MCS_CHN 的话,控件以中文显示日期信息;如果包括 MCS_ENG_L,以英文显示日期信息;如果包括 MCS_ENG_S 的话,将以简写的英文格式显示。

如果风格中包括 MCS_NOTIFY 的话,月历控件将在响应用户操作时等情况下产生相应的通知消息。

1.2 月历控件消息

1.2.1 获取日期

MCM_GETCURDAY 消息用来获取当前选择的日期中是当月中的第几天:

int day;
day = SendMessage (hwndMonthcal, MCM_GETCURDAY, 0, 0) ;

SendMessage 函数返回值就是当前的天数。

MCM_GETCURMONTH 消息用来获取当前选择的日期中的月份值:

int month;
month = SendMessage (hwndMonthcal, MCM_GETCURMONTH, 0, 0) ;

SendMessage 函数返回值就是当前的月份。

MCM_GETCURYEAR 消息用来获取当前选择日期中的年份:

int year;
year = SendMessage (hwndMonthcal, MCM_GETCURYEAR, 0, 0) ;

SendMessage 函数返回值就是当前的年份。

MCM_GETCURMONLEN 消息用来获取当前月份的长度(该月有几天):

int monthlen;
monthlen = SendMessage (hwndMonthcal, MCM_GETCURMONLEN, 0, 0) ;

SendMessage 函数返回值就是当前月份的长度。

MCM_GETFIRSTWEEKDAY 消息用来确定当前月份中的第一天是星期几:

int weekday;
weekday = SendMessage (hwndMonthcal, MCM_GETFIRSTWEEKDAY, 0, 0) ;

SendMessage 函数返回值就是当前月份第一天的星期号,从 0 到 60 表示星期天。

MCM_GETCURDATE 消息获取月历控件中当前选择的日期:

SYSTEMTIME systime;
SendMessage (hwndMonthcal, MCM_GETCURDATE, 0, (LPARAM)&systime) ;

systime 是一个 SYSTEMTIME 类型的结构,存放获取的年、月、日和星期几等日期信息。该结构还用于 MCM_GETTODAY 等消息,其结构定义如下:

typedef struct _SYSTEMTIME
{
        /* 年 */
        int year;
        /* 月 */
        int month;
        /* 日 */
        int day;
        /* 星期几 */
        int weekday;
} SYSTEMTIME;
typedef SYSTEMTIME *PSYSTEMTIME;

MCM_GETTODAY 消息获取“今天”的日期:

SYSTEMTIME systime;
SendMessage (hwndMonthcal, MCM_GETTODAY, 0, (LPARAM)&systime) ;

systime 也是一个 SYSTEMTIME 类型的结构。

1.2.2 设置日期

需要注意的是,在 Linux 系统中,设置日期可能需要特殊用户身份(如 root

MCM_SETCURDAY 消息设置当前选择的“天”,MCM_SETCURMONTH 消息设置当前的月,MCM_SETCURYEAR 消息设置当前的年:

int day;
int month;
int year;
SendMessage (hwndMonthcal, MCM_SETCURDAY, day, 0) ;
SendMessage (hwndMonthcal, MCM_SETCURMONTH, month, 0) ;
SendMessage (hwndMonthcal, MCM_SETCURYEAR, year, 0) ;

daymonthyear 分别指定新的天、月和年,如果这些值在合理的值范围之外,控件将采用最接近的一天、月或年。

MCM_SETCURDATE 消息设置当前选择的日期:

SYSTEMTIME systime;
SendMessage (hwndMonthcal, MCM_SETCURDATE, 0, (LPARAM)&systime) ;

MCM_SETTODAY 把“今天”设为当前选择的日期:

SendMessage (hwndMonthcal, MCM_SETTODAY, 0, 0) ;

1.2.3 调整颜色

应用程序可以通过 MCM_GETCOLORMCM_SETCOLOR 消息来获取和改变月历控件中各部分的颜色设置:

MCCOLORINFO color;
SendMessage (hwndMonthcal, MCM_GETCOLOR, 0, (LPARAM)&color) ;
SendMessage (hwndMonthcal, MCM_SETCOLOR, 0, (LPARAM)&color) ;

color 是一个 MCCOLORINFO 类型的结构,用于保存颜色信息。

typedef struct _MCCOLORINFO
{
        /* 标题的背景色 */
        int clr_titlebk;
        /* 标题的文字颜色 */
        int clr_titletext;
        /* 年和月箭头的颜色 */
        int clr_arrow;
        /* 箭头高亮时背景色 */
        int clr_arrowHibk;
        
        /* 星期标题背景色 */
        int clr_weekcaptbk;
        /* 星期标题文字颜色 */
        int clr_weekcapttext;
        
        /* 天数部分背景色 */
        int clr_daybk;
        /* 天数部分高亮时背景色 */
        int clr_dayHibk;
        /* 天数部分文字颜色 */
        int clr_daytext;
        /* 非当前月部分天数文字颜色 */
        int clr_trailingtext;
        /* 高亮的文字颜色 */
        int clr_dayHitext;
} MCCOLORINFO;

1.2.4 控件大小

为了能够正常显示其中的内容,月历控件有一个窗口最小限制值,MCM_GETMINREQRECTW 消息和 MCM_GETMINREQRECTH 消息分别用来获取最小宽度和最小高度值:

int minw, minh;
minw = SendMessage (hwndMonthcal, MCM_GETMINREQRECTW, 0, 0) ;
minh = SendMessage (hwndMonthcal, MCM_GETMINREQRECTH, 0, 0) ;

SendMessage 函数的返回值就是最小宽度和高度值。

1.3 月历控件通知码

当用户点击月历控件并造成当前日期发生改变时,控件将产生 MCN_DATECHANGE 通知码。

1.4 编程实例

清单 1.1 中的代码演示了月历控件的使用。该程序的完整源代码可见本指南示例程序包 mg-samples 中的 monthcal.c 程序。

清单 1.1 月历控件示例程序

#define IDC_MC                100
#define IDC_OK                200

/* 对话框模板:只有两个控件:月历控件和“确定”按钮 */
static CTRLDATA CtrlTime[]=
{
        {
                "monthcalendar",
                WS_CHILD | WS_VISIBLE | MCS_NOTIFY | MCS_CHN,
                10, 10, 240, 180,
                IDC_MC,
                "",
                0
        },
        {
                "button",
                WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                260, 180, 50, 22,
                IDC_OK,
                "确定",
                0
        }
};

static DLGTEMPLATE DlgTime = 
{
        WS_VISIBLE | WS_CAPTION | WS_BORDER,
        WS_EX_NONE,
        0, 0, 320, 240,
        "约会时间",
        0, 0,
        2, CtrlTime,
        0
};

static int TimeWinProc(HWND hDlg, int message, WPARAM wParam, LPARAM lParam)
{
        switch (message) {
                case MSG_INITDIALOG:
                break;
                
                case MSG_COMMAND:
                {
                        int id = LOWORD(wParam);
                        if (id == IDC_OK) {
                                char info[100];
                                SYSTEMTIME date;
                                /* 获取月历控件中的当前日期 */
                                SendMessage (GetDlgItem(hDlg, IDC_MC), MCM_GETCURDATE, 0, (LPARAM)&date);
                                sprintf (info, "你定于%d年%d月%d日会见总统!", 
                                date.year, date.month, date.day);
                                MessageBox (hDlg, info, "约会", MB_OK | MB_ICONINFORMATION);
                                EndDialog (hDlg, 0);
                        }
                }
                break;
                
                case MSG_CLOSE:
                {
                        EndDialog (hDlg, 0);
                }
                return 0;
        }
        
        return DefaultDialogProc (hDlg, message, wParam, lParam);
}

月历控件的使用 图 1.1 月历控件的使用